【问题标题】: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我有一个字符串日期格式 01/01/2017 6:54 PM 并想在 scala 中将其转换为 2017-01-01T00:00:05.383+0100 ISOFormat
【发布时间】:2018-02-05 10:22:50
【问题描述】:
   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:字符串索引超出范围:23

【问题讨论】:

  • 为什么我得到 java.lang.StringIndexOutOfBoundsException
  • 当您在长度小于 23 个字符的 StringBuilder 上调用 charAt(23) 时,您认为会发生什么?
  • 我已经编辑了代码,这就是我实际运行的内容
  • 当字符串少于 24 个字符时,您试图获取位置 23 的字符(因为第一个字符位于位置 0,第二个字符位于位置 1,依此类推)。所以你应该先检查length()。但是无论如何,如果您拥有的字符串格式为01/01/2017 6:54 PM,为什么需要检查字符串是否包含-?您需要将其解析为日期,然后使用ISO8601Format 进行格式化
  • 您标记了您的问题 jodatime,虽然 Joda-Time 是一个不错的选择,但它也处于维护模式,它的作者建议我们继续使用 java.time,它是由绘图的同一个人开发的来自 Joda-Time 的所有经验。那么这对您来说不是更好的选择吗?

标签: scala jodatime datetime-format datetime-parsing


【解决方案1】:

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") 返回2017-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 说:

    请注意,Joda-Time 被认为是一个基本“完成”的项目。 没有计划进行重大改进。如果使用 Java SE 8,请迁移 到java.time (JSR-310)。

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

【讨论】:

  • 这是一个很好的反馈。我特别了解编程和 scala,因此您的回答帮助我理解了为什么我应该使用每种方法以及何时寻找替代方法。
  • 好答案。还可以考虑调用 DateTimeFormatter.ofLocalizedDateTime 而不是硬编码特定的格式模式。
【解决方案2】:

假设您的输入字符串是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

【讨论】:

    【解决方案3】:

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

       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)
    

    【讨论】:

    • 是的,但为什么要使用早已过时且臭名昭著的麻烦SimpleDateFormat?现代的java.time.format.DateTimeFormatter 通常更好,更有帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多