我有一个字符串日期格式 01/01/2017 6:54 PM 并想在 scala 中将其转换为 2017-01-01T00:00:05.383+0100 ISOFormat

I have a string date format 01/01/2017 6:54 PM and want to convert it to 2017-01-01T00:00:05.383+0100 ISOFormat in scala

   def cleantz( time : String ) : String = {
    var sign_builder= new StringBuilder ++= time
    println(sign_builder)
    var clean_sign = ""
    if (sign_builder.charAt(23).toString == "-"){
      clean_sign= sign_builder.replace(23,24,"-").toString()
    }else{
      clean_sign = sign_builder.replace(23,24,"+").toString()
    }
    var time_builder= new StringBuilder ++= clean_sign
    if (time_builder.charAt(26).toString == ":"){
      val cleanz = time_builder.deleteCharAt(26)
      cleanz.toString()
    }else{
      time_builder.toString()
    }
  }

    val start = ISO8601Format.parse(cleantz(01/01/2017 6:54 PM))

我收到这个错误:

java.lang.StringIndexOutOfBoundsException: String index out of range: 23

假设您输入的字符串是01/01/2017 6:54 PM:它有18个字符。当您调用 charAt(23) 时,它会尝试获取位置 23 处的字符,该字符不存在:字符串的位置从零(第一个 0)到 17(M) .如果您尝试获得大于该位置的位置,它会抛出 StringIndexOutOfBoundsException.

但是您不需要进行所有这些字符串操作。如果您有一个以某种格式表示日期的字符串,并且想将其转换为另一种格式,您只需要:

  1. 将原始字符串解析为日期
  2. 将此日期格式化为另一种格式

因此您需要 2 个不同的 Joda 格式化程序(每个步骤一个)。但还有一个额外的细节。

输入有日期(01/01/2017)和时间(6:54 PM),输出有日期(2017-01-01),时间(18:54:00.000 ) 和 UTC offset (+0100)。所以你还有一个额外的步骤:

  1. 将原始字符串解析为日期
  2. +0100 偏移量添加到已解析的日期
  3. 将此日期格式化为另一种格式

使用 Joda-Time,这可以通过以下代码实现:

import org.joda.time.DateTimeZone
import org.joda.time.LocalDateTime
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.ISODateTimeFormat

val fmt = DateTimeFormat.forPattern("dd/MM/yyyy h:mm a")
// parse the date
val localDate = LocalDateTime.parse("01/01/2017 6:54 PM", fmt)
// add the +01:00 offset
val dt = localDate.toDateTime(DateTimeZone.forOffsetHours(1))
// format to ISO8601
print(ISODateTimeFormat.dateTime().print(dt))

输出将是:

2017-01-01T18:54:00.000+01:00

请注意,偏移量打印为 +01:00。如果你想要 +0100(没有 :),你需要创建另一个格式化程序:

val formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
println(formatter.print(dt))

输出将是:

2017-01-01T18:54:00.000+0100

这是我用来实现相同结果的代码。发生错误是因为我试图解析错误的日期格式。

   val inputForm = new SimpleDateFormat("MM/dd/yyyy h:mm a")
   val outputForm = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")

   val dateFormat1 = start_iso
   val dateFormat2 = stop_iso

   val start = outputForm.format(inputForm.parse(start_iso))
 val stop = outputForm.format(inputForm.parse(stop_iso))

   println(start)
println(stop)

java.time

为了完整起见,我想提供现代答案。非常简单明了。

很抱歉,我既不会编写Scala代码,也不会在我的电脑上测试它。我必须相信你翻译自 Java.

private static DateTimeFormatter inputFormatter 
        = DateTimeFormatter.ofPattern("MM/dd/yyyy h:mm a", Locale.US);

public static String cleantz(String time) {
    return LocalDateTime.parse(time, inputFormatter)
            .atOffset(ZoneOffset.ofHours(1))
            .toString();
}

现在cleantz("01/01/2017 6:54 PM")returns2017-01-01T18:54+01:00,格式为ISO 8601。我会立即假设你已经准备好了。如果出于某种原因您也想要或需要秒数,请将 .toString(); 替换为:

            .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);

现在结果是 2017-01-01T18:54:00+01:00。在这两种情况下,如果有的话,都会打印出毫秒数。

因为 AMPM 几乎不用于英语以外的其他语言,我建议你给 DateTimeFormatter.ofPattern() 一个英语语言环境(在我的例子中我使用 Locale.US).未能提供区域设置将导致代码在许多具有非英语语言设置的计算机上失败。

为什么 java.time

  • SimpleDateFormat 和朋友早就过时了,而且出了名的麻烦。我无法计算在 Stack Overflow 上提出的问题,因为 SimpleDateFormat 的行为与每个理智的程序员所期望的不同,或者没有提供任何帮助来调试我们不时犯的简单错误。
  • Joda-Time 在很长一段时间内都很好。今天 Joda-Time homepage 说:

    Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).

  • java.time 是现代 Java 日期和时间 API 使用 Joda-Time 的经验并在同一位首席开发人员 Stephen Colebourne 的指导下构建的。它内置于 Java 8 及更高版本中,Java 6 和 7 存在向后移植,因此您也可以在那里使用相同的 类。