【问题标题】:Parse Date String to Some Java Object将日期字符串解析为某个 Java 对象
【发布时间】:2012-02-09 21:43:06
【问题描述】:

我在一个读取文件和处理数据的项目中工作。例如,我必须处理日期:

  1. 2012-01-10 23:13:26
  2. 2012 年 1 月 13 日

我找到了 Joda 包,一个有趣的包,但不知道它是否是最简单的。

我能够将第一个示例解析为 DateTime 对象 (Joda) 正则表达式和字符串操作。 (例如:将空格替换为 '-' 并将其传递给构造函数。

new DateTime("2012-01-10 23:13:26".replace(' ', '-'))

我猜它有效,但问题在于第二种格式。我如何使用这样的输入来提取对象,最好是 Joda 对象。我当然可以编写一个函数来将格式更改为 Joda 支持的格式,但想知道是否还有其他方法(甚至是一些本机 Java 库)来做到这一点。

如果有什么比 Joda 更好的东西,也请告诉我。

谢谢。

【问题讨论】:

    标签: java datetime jodatime date-parsing


    【解决方案1】:

    使用Joda-Time,看看DateTimeFormat;它允许解析您提到的两种日期字符串(以及几乎任何其他任意格式)。如果您的需求更加复杂,请尝试DateTimeFormatterBuilder

    解析#1:

    DateTimeFormatter f = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
    DateTime dateTime = f.parseDateTime("2012-01-10 23:13:26");
    

    编辑:实际上LocalDateTime 是更适合没有时区的日期时间的类型:

    LocalDateTime dateTime = f.parseLocalDateTime("2012-01-10 23:13:26");
    

    对于#2:

    DateTimeFormatter f = DateTimeFormat.forPattern("MMMM dd, yyyy");
    LocalDate localDate = f.parseLocalDate("January 13, 2012");
    

    是的,就 Java 日期和时间处理而言,Joda-Time 绝对是最佳选择。 :)

    大多数人都会同意,Joda 是一个非常用户友好的库。例如,我以前从未使用 Joda 进行过这种解析,但我只花了几分钟就从 API 中弄清楚并编写了它。

    更新(2015 年)

    如果您使用的是 Java 8,在大多数情况下,您应该简单地使用 java.time 而不是 Joda-Time。它包含了几乎所有来自 Joda 的好东西——或它们的等价物。对于那些已经熟悉 Joda API 的人来说,Stephen Colebourne 的Joda-Time to java.time migration guide 会派上用场。

    这里是上述示例的 java.time 版本。

    解析#1:

    DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    LocalDateTime dateTime = LocalDateTime.from(f.parse("2012-01-10 23:13:26"));
    

    您无法将其解析为 ZonedDateTime 或 OffsetDateTime(它们是 Joda 的 DateTime 的对应物,在我的原始答案中使用),但这有点道理,因为解析的字符串中没有时区信息。

    解析#2:

    DateTimeFormatter f = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
    LocalDate localDate = LocalDate.from(f.parse("January 13, 2012"));
    

    这里 LocalDate 是最适合解析的类型(就像 Joda-Time 一样)。

    【讨论】:

    • 对于使用非英语语言环境但解析美国日期的用户,format = format.withLocale(Locale.US); 否则解析 January 将失败。 //乔达新手
    • 太棒了,感谢您提供的快速信息。我可能需要几天甚至几周的时间才能弄清楚。感谢大家的帮助!
    • 正确答案,但缺少两件事。 [a] 区域设置,如第一条评论中所述。 [b] 时区。 如果省略,JVM 的当前默认时区将分配给 DateTime 对象。最好明确说明该数据源的预期时区。在格式化程序对象上调用withZone,传递DateTimeZone.UTCDateTimeZone.forID( "Europe/Helsinki" ) 的结果。
    • Java 8 版本的解决方案可以通过使用以 TemporalQuery 对象作为第二个参数的重载的#parse 方法进行略微改进:LocalDateTime dateTime = f.parse("2012-01-10 23:13:26", LocalDateTime::from)
    【解决方案2】:

    SimpleDateFormat 会将日期解析为 Java Date 对象:

    http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html

    SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // first example
    SimpleDateFormat format2 = new SimpleDateFormat("MMMMM dd,yyyy"); // second example
    
    Date d1 = format1.parse( dateStr1 );
    Date d2 = format2.parse( dateStr2 );
    

    【讨论】:

    • 我认为 YYYY 需要小写
    • 如果您解析 24 小时制,您应该使用 HH 而不是 hhDocumentation
    【解决方案3】:

    我想 Joda 有一个 Formatter 来为你做这件事。我通过谷歌快速搜索找到了这个:http://johannburkard.de/blog/programming/java/date-time-parsing-formatting-joda-time.html

    DateTimeFormatter parser1 =
        DateTimeFormat.forPattern("dd/MMM/yyyy:HH:mm:ss Z");
    
    DateTimeFormatter parser2 =
        DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
    
    DateTime time = parser1.parseDateTime("<data>");
    

    用于评估模式的语法可以在X-Zero's link 中找到。

    【讨论】:

      【解决方案4】:

      JodaTime 在很大程度上被认为是 Java 中日期时间处理的事实标准 - 他们正在努力将其添加到 Java 库的下一个版本中(嗯,有效地)。

      要从字符串中获取 JodaTime 日期,您需要查看 DateTimeFormat 类。

      【讨论】:

        【解决方案5】:

        最简单的方法是根据您期望的格式正确设置 SimpleDateFormat,并使用其解析方法为您提供 Date 对象

        【讨论】:

          【解决方案6】:

          tl;博士

          LocalDateTime ldt = LocalDateTime.parse( "2012-01-10 23:13:26".replace( " " , "T" ) );
          

          ……和……

          LocalDate localDate = LocalDate.parse ( "January 13, 2012" , DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG ).withLocale ( Locale.US ) );
          

          详情

          Answer by Jonik 基本正确,但遗漏了一些重要问题。

          java.time

          如果有什么比 Joda 更好的东西,也请告诉我。

          是的,有更好的东西,java.time 框架。 Joda-Time 团队建议迁移到 java.time 作为其继任者。

          java.time 框架内置于 Java 8 及更高版本中。这些类取代了旧的麻烦的日期时间类,例如 java.util.Date.Calendarjava.text.SimpleDateFormat

          要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。

          大部分 java.time 功能在ThreeTen-Backport 中向后移植到 Java 6 和 7,并在 ThreeTenABP 中进一步适应 Android。

          日期时间

          您的第一个输入是日期加上时间。它缺少任何offset-from-UTCtime zone 信息,因此我们将其解析为LocalDateTime 对象。 “Local…”是指任何的地方,没有具体的地方。所以这不是时间线上的实际时刻,而只是一个关于时刻的粗略概念。

          要解析输入字符串2012-01-10 23:13:26,我们可以用T 替换中间的空格,以符合ISO 8601 日期时间值标准格式的规范样式。

          在解析和生成日期时间值的文本表示时,java.time 类默认使用 ISO 8601 格式。所以不需要定义解析模式。

          String input = "2012-01-10 23:13:26".replace( " " , "T" );
          LocalDateTime ldt = LocalDateTime.parse( input );
          

          如果您从该值的上下文中知道预期的时区,则应用它来定义时间轴上的实际时刻。

          ZoneId zoneId = ZoneId.of( "America/Montreal" );
          ZonedDateTime zdt = ldt.atZone( zoneId );
          

          转储到控制台。

          System.out.println ( "input: " + input + " | zdt: " + zdt );
          

          输入:2012-01-10T23:13:26 | zdt: 2012-01-10T23:13:26-05:00[美国/蒙特利尔]

          仅限日期

          你们中的第二个输入是一个仅日期值,没有时间和时区。为此,我们需要 LocalDate 类。

          我认为该输入的格式符合美国的语言(英语)和文化规范。因此无需明确指定格式模式。我们可以简单地通过指定Locale 来请求一个知道美国格式的格式化程序。我们根据这种格式的长度指定FormatStyle.LONG

          String input = "January 13, 2012";
          DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG ).withLocale ( Locale.US );
          LocalDate localDate = LocalDate.parse ( input , formatter );
          

          转储到控制台。

          System.out.println ( "input: " + input + " | localDate: " + localDate );
          

          输入:2012 年 1 月 13 日 |本地日期:2012-01-13

          【讨论】:

            猜你喜欢
            • 2013-06-05
            • 1970-01-01
            • 1970-01-01
            • 2012-10-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-09-11
            • 2012-07-11
            相关资源
            最近更新 更多