【问题标题】:Java8 equivalent of JodaTime DateTimeFormat.shortDate()Java8 等效于 JodaTime DateTimeFormat.shortDate()
【发布时间】:2020-01-29 08:05:51
【问题描述】:

什么是Java8 java.time 等价于

org.joda.time.formatDateTimeFormat.shortDate()

我尝试过以下方式,但无法解析“20/5/2016”或“20/5/16”等值。

DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) 

【问题讨论】:

    标签: java java-8 jodatime java-time date-parsing


    【解决方案1】:

    您是对的:Joda-Time DateTimeFormatter(这是您从 DateTimeFormat.shortDate() 获得的类型)比 java.time DateTimeFormatter 解析更宽松。在英语/新西兰语言环境中 (en-NZ) shortDate 使用格式模式 d/MM/yy 并将 20/5/201620/5/16 解析为 2016-05-20。

    坦率地说,我觉得将两位数和四位数的年份都解释为同一年很讨厌。当格式指定两位数年份时,我预计四位数字会成为更严格的输入验证的错误。当格式指定两位数时接受一位数的月份也很宽松,但可能没有那么危险,更符合我们的预期。

    java.time 也使用格式模式d/MM/yy(在 jdk-11.0.3 上测试)。解析时接受一位或两位数的日期,但坚持两位数的月份和两位数的年份。

    您可能会在 java.time 中获得 Joda-Time 行为,但它需要您自己指定格式模式:

        Locale loc = Locale.forLanguageTag("en-NZ");
        DateTimeFormatter dateFormatter
                = DateTimeFormatter.ofPattern("d/M/[yyyy][yy]", loc);
    
        System.out.println(LocalDate.parse("20/5/2016", dateFormatter));
        System.out.println(LocalDate.parse("20/5/16", dateFormatter));
    

    输出是:

    2016-05-20
    2016-05-20
    

    如果您想要一个适用于其他语言环境的高级解决方案,我相信您可以编写一段代码,从DateTimeFormatterBuilder.getLocalizedDateTimePattern 获取格式模式并通过将dd 替换为d、@987654335 来修改它@ 和 M 以及任意数量的 y[yyyy][yy]。然后将修改后的格式模式字符串传递给DateTimeFormatter.ofPattern

    编辑:很高兴你有工作要做。在您的评论中,您说您使用了:

        Stream<String> shortFormPatterns = Stream.of(
                "[d][dd]/[M][MM]",
                "[d][dd]-[M][MM]",
                "[d][dd].[M][MM]",
                "[d][dd] [M][MM]",
                "[d][dd]/[M][MM]/[yyyy][yy]",
                "[d][dd]-[M][MM]-[yyyy][yy]",
                "[d][dd].[M][MM].[yyyy][yy]",
                "[d][dd] [M][MM] [yyyy][yy]");
    
    1. 它涵盖了比您的 Joda-Time 格式化程序更多的情况。也许这很好。具体来说,您的 Joda-Time 格式化程序坚持在数字之间使用斜线 / 并拒绝连字符、点或空格。此外,我相信 Joda-Time 会反对将年份完全排除在外。
    2. 虽然您确实需要[yyyy][yy],但您不需要[d][dd][M][MM]。只需 dM 就足够了,因为它们也接受两位数(例如,您的代码中发生的情况是 [d] 解析一位或两位数,因此无论如何都不会使用 [dd])。
    3. 如果您只喜欢一个格式模式字符串,我希望 d[/][-][.][ ]M[/][-][.][ ][yyyy][yy] 可以工作(除了省略年份的情况)(我没有测试过)。

    【讨论】:

    • 是的,[] 运行良好。我只是使用Stream&lt;String&gt; shortFormPatterns = Stream.of( "[d][dd]/[M][MM]", "[d][dd]-[M][MM]", "[d][dd].[M][MM]", "[d][dd] [M][MM]", "[d][dd]/[M][MM]/[yyyy][yy]", "[d][dd]-[M][MM]-[yyyy][yy]", "[d][dd].[M][MM].[yyyy][yy]", "[d][dd] [M][MM] [yyyy][yy]"); 可能比joda.time 更详细,后者隐式支持更多案例,但java.time 在其他领域更好。
    • 感谢@wilmol 跟进。我有两个cmets。我已将它们添加为答案底部的编辑。
    • @OleV.V. d[/][-][.][ ]M[/][-][.][ ][yyyy][yy] 效果很好。至少对于像"20/5/2016", "20/5/16", "31.12.2009", "21 3 2017", "09/02/19", "1 5 20", "09 3 16" 这样的输入。
    【解决方案2】:

    FormatStyle.SHORT返回最短格式dd/MM/yyd/M/yy格式,所以需要使用pattern来获取自定义格式

    LocalDate date = LocalDate.now();   
    System.out.println(date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)));   //9/29/19
    

    您也可以使用DateTimeFormatter.ISO_DATEDateTimeFormatter.ISO_LOCAL_DATE 来获得像yyyy-MM-dd 这样的iso 格式,也可以在DateTimeFormatter 中查看可用的格式

    System.out.println(date.format(DateTimeFormatter.ISO_DATE));       //2019-09-29
    System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); //2019-09-29
    

    如果您想要像 yyyy/MM/dd 这样的自定义格式,请使用 ofPattern

    System.out.println(date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))); //2019/09/29
    

    【讨论】:

    • 问题是我不知道输入的格式。似乎 JodaTime shortDate() 覆盖的案例比 java.time FormatStyle.SHORT 更多。
    • @wilmol 请问什么情况?从文档中DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) 似乎等同于DateTimeFormat.shortDate()。我不太了解 Joda-Time,所以我可能会遗漏一些东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    • 2011-05-07
    • 2019-06-29
    • 2021-09-22
    • 1970-01-01
    • 2014-08-15
    • 2012-10-21
    相关资源
    最近更新 更多