【问题标题】:How to use DateTimeFormatter for pattern dMMyyyy如何将 DateTimeFormatter 用于模式 dMMyyyy
【发布时间】:2021-12-08 21:19:15
【问题描述】:

我需要使用 DateTimeFormatter 将字符串解析为 LocalDate。

有 2 种不同的情况,模式字符串 dMMyy 或 ddMMyy (20320, 020320, 120320) 和模式字符串 ddMMyyyy 或 dMMyyyy (2032020, 02032020, 12032020)。

对于第一种情况,我可以只使用 DateTimeFormatter.ofPattern("dMMyy") 它适用于 5 或​​ 6 位长日期。

 @Test
    public void dateConversionyy() {
       DateTimeFormatter worksShortd = DateTimeFormatter.ofPattern("dMMyy");
       DateTimeFormatter worksShortdd = DateTimeFormatter.ofPattern("ddMMyy");
       String longString = "120320";
       String leadingZeroString = "020320";
       String shortString = "20320";

       LocalDate res = LocalDate.parse(longString, worksShortd);
       assertNotNull(res);

       LocalDate res2 = LocalDate.parse(longString, worksShortdd);
       assertNotNull(res2);
       assertEquals(res, res2);

       LocalDate res3 = LocalDate.parse(shortString, worksShortd);
       assertNotNull(res3);

       LocalDate res4 = LocalDate.parse(leadingZeroString, worksShortd);
       assertNotNull(res4);
       assertEquals(res3, res4);

       LocalDate res5 = LocalDate.parse(leadingZeroString, worksShortdd);
       assertNotNull(res);
       assertEquals(res3, res5);

    }

对于第二种情况,我认为我可以使用模式“dMMyyyy”,但它只是不解析任何输入字符串。

 @Test
    public void dateConversionyyyy() {
        LocalDate res;
       DateTimeFormatter failsLong = DateTimeFormatter.ofPattern("dMMyyyy");
       DateTimeFormatter worksLong = DateTimeFormatter.ofPattern("ddMMyyyy");
       String longString = "13082020";
       String shortString = "3082020";
       boolean notParsed1 = false;
       try {
           LocalDate.parse(longString, failsLong);
       } catch (DateTimeParseException e) {
           notParsed1 = true;
       }
       assertTrue(notParsed1);
       res = LocalDate.parse(longString, worksLong);
       assertNotNull(res);

        boolean notParsed2 = false;
        try {
            LocalDate.parse(shortString, failsLong);
        } catch (DateTimeParseException e) {
            notParsed2 = true;
        }
        assertTrue(notParsed2);

    }

编辑: 我的问题:有没有办法以解析 7-8 位变体的方式实例化 DateTimeFormatter use DateTimeFormatter.ofPattern

编辑了问题,以便@user16320675 的答案匹配,因为它解决了我的问题。

【问题讨论】:

  • @user16320675 这似乎有效。你能写一个答案让我接受吗?

标签: java parsing time


【解决方案1】:

DateTimeFormatterBuilder.appendValue(TemporalField, int)

我正在使用并稍微修改 user16320675 在评论中提到的想法:

尝试使用DateTimeFormatterBuilder 并使用 appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER),使用 其他字段的大小固定。

    DateTimeFormatter worksLong = new DateTimeFormatterBuilder()
            .appendPattern("dMM")
            .appendValue(ChronoField.YEAR, 4)
            .toFormatter(Locale.ROOT);
    System.out.println(LocalDate.parse("2032020", worksLong));
    System.out.println(LocalDate.parse("02032020", worksLong));
    System.out.println(LocalDate.parse("12032020", worksLong));

输出:

2020-03-02
2020-03-02
2020-03-12

如果您希望在构建格式化程序时更加一致:

    DateTimeFormatter worksLong = new DateTimeFormatterBuilder()
            .appendValue(ChronoField.DAY_OF_MONTH)
            .appendValue(ChronoField.MONTH_OF_YEAR, 2)
            .appendValue(ChronoField.YEAR, 4)
            .toFormatter(Locale.ROOT);

结果是一样的。

为什么你的模式 dMMyyyy 不起作用?

年份,或更准确地说是模式字母uyY,在DateTimeFormatter.ofPattern() 中是特殊的。对于其他数字字段,四个模式字母表示宽度正好为 4 的字段。多年来,这意味着 最小字段宽度为 4。这反过来又破坏了 相邻值解析的工作在两位数年份的情况下。相反,我认为解析器贪婪地使用所有 7 位或 8 位数字表示月份中的某一天,然后找不到它们之后的月份。

相邻值解析是使您的模式 dMMyy 起作用的原因。当所有其他字段具有固定宽度时,它基本上允许在它们之间没有分隔符的一系列字段中的 first (并且只有第一个)具有可变宽度。所以我们让相邻值解析再次起作用的技巧是让 year 字段的宽度固定为 4。builder 的 appendValue 方法可以做到这一点。

那么为什么yy 工作而yyyy 没有工作呢?因为岁月很特别。 yy 表示固定宽度为 2。yyyy 表示最小宽度为 4。

文档引用和链接

来自DateTimeFormatter的文档:

年份: 字母数决定了使用填充的最小字段宽度。如果字母数是两个,那么 使用减少的两位数形式。对于打印,这将输出 最右边两位数。对于解析,这将使用基础进行解析 2000 的值,导致 2000 到 2099 范围内的年份 包括的。如果字母数少于四个(但不是两个), 那么这个符号只在负年份输出 SignStyle.NORMAL。否则,如果焊盘宽度为 超出,根据SignStyle.EXCEEDS_PAD

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 2017-01-27
    • 1970-01-01
    • 2015-08-23
    • 2018-01-26
    • 1970-01-01
    相关资源
    最近更新 更多