当前位置: 首页 > 知识库问答 >
问题:

如何使用DateTimeFormatter在java8中处理yyyy-mm和yyyy

淳于枫
2023-03-14

我使用SimpleDateFormat来格式化或验证日期,但我想通过使用java 8 DateTimeFormatter使其线程安全。我在实现某些要求时遇到了麻烦。

我的应用程序将只接受三种类型的格式。“yyyy-MM-dd”, “yyyy-MM”, “yyyy”

Existing Code gives me desired output:
/*simple date format to process yyyy-MM-dd format
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd")
/*simple date format to process yyyy-MM format
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM")

/*simple date format to process yyyy format
SimpleDateFormat simpleDateFormat3 = new SimpleDateFormat("yyyy")

/* to parse input
simpleDateFormat.parse(input)
/* to format
simpleDateFormat.format(simpleDateFormat1)

以下是输入和预期输出:

  input             expected
'2018-03-19'       '2018-03-19'
'2018-03'          '2018-03'
'2018'             '2018'
'2017-02-54'       '2017-02'
'2016-13-19'       '2016'

>

  • 我如何在java 8 DateTimeForma中实现相同的结果,在这里输入代码tter?

    /* java 8日期时间格式化程序日期时间格式化程序日期时间格式化程序=新日期时间格式化程序(" yyyy-MM-dd ")

    当所有年份、月份和日期值都正确时,上面的代码片段才有效。任何帮助都将不胜感激。

  • 共有2个答案

    瞿健
    2023-03-14

    就像Basil Bourque在另一个回答中一样,我不一定相信你所要求的也是最适合你的。无论如何,作为对这个好答案的一个小小的补充,我想提出一种处理最后两种情况的方法,即你所说的无效日期。

    为了验证格式,我首先解析字符串,而不验证数字。这将拒绝三种格式中任何一种格式的字符串,例如<code>2016-03-19T12:00。DateTimeFormatter。parseUnresolved方法负责此部分。如果出现解析错误,此方法在我们传递给它的<code>ParsePosition</code>对象中设置错误索引,并返回<code>null</code>(因此不会引发任何异常)。所以我检查<code>null</code>是否返回。

    private static DateTimeFormatter yearMonthFormatter = DateTimeFormatter.ofPattern("uuuu-MM")
            .withResolverStyle(ResolverStyle.STRICT);
    private static DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern("uuuu")
            .withResolverStyle(ResolverStyle.STRICT);
    
    public static Temporal parse(String input) {
        // First try the three formats, uuuu-MM-dd, uuuu-MM, uuuu, in turn without resolving
        TemporalAccessor parsed = null;
        for (DateTimeFormatter formatter : Arrays.asList(DateTimeFormatter.ISO_LOCAL_DATE,
                yearMonthFormatter, yearFormatter)) {
            ParsePosition position = new ParsePosition(0);
            TemporalAccessor parseAttempt = formatter.parseUnresolved(input, position);
            if (parseAttempt != null && position.getIndex() == input.length()) {
                // Success; exit loop
                parsed = parseAttempt;
                break;
            }
        }
        if (parsed == null) { // didn’t match any of the three formats
            throw new IllegalArgumentException("Invalid format: " + input);
        }
    
        // Try resolving to either LocalDate, YearMonth or Year
        try {
            return LocalDate.of(parsed.get(ChronoField.YEAR),
                    parsed.get(ChronoField.MONTH_OF_YEAR),
                    parsed.get(ChronoField.DAY_OF_MONTH));
        } catch (DateTimeException dteRLd) {
            try {
                return YearMonth.of(parsed.get(ChronoField.YEAR),
                        parsed.get(ChronoField.MONTH_OF_YEAR));
            } catch (DateTimeException dteRYm) {
                return Year.of(parsed.get(ChronoField.YEAR));
            }
        }
    }
    

    让我们试试你的例子:

        String[] inputs = {
                "2018-03-19",
                "2018-03",
                "2018",
                "2017-02-54",
                "2016-13-19"
        };
    
        for (String input : inputs) {
            Temporal parsed = parse(input);
            System.out.format("%-10s  %-10s  %s%n", input, parsed, parsed.getClass().getName());
        }
    

    输出为:

    2018-03-19  2018-03-19  java.time.LocalDate
    2018-03     2018-03     java.time.YearMonth
    2018        2018        java.time.Year
    2017-02-54  2017-02     java.time.YearMonth
    2016-13-19  2016        java.time.Year
    
    皇甫宇定
    2023-03-14

    Am使用SimpleDateFormat格式化或验证日期

    切勿使用SimpleDataFormat

    与最早版本的Java捆绑在一起的可怕的日期时间类几年前被JSR 310中定义的现代java.time类所取代。

    thread-safe by using java 8 DateTimeFormatter

    是的,与传统的日期-时间类不同,java.time类使用不可变的对象,并且在设计上是线程安全的。

    以下是输入和预期输出:

    您的一些输入可以通过它们的长度来检测。

    // Ten-digits long, assume ISO 8601 date.
    LocalDate ld = LocalDate.parse( "2018-03-19" ) ;
    
    // Seven digits long, assume ISO 8601 year-month.
    YearMonth ym = YearMonth.parse( "2018-03" ) ;
    
    // Four digits, assume year.
    Year y = Year.parse( "2018" ) ;
    

    请注意,上述输入均符合 ISO 8601 标准。java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。因此,无需指定格式设置模式。因此,不需要显式的 DateTimeFormatter 对象。

    '2017-02-54''2017-02'

    这个例子让我困惑。如果你的意思是“当遇到无效的日期时,只使用年份和月份,而忽略日期”,我想你可能能够做到这一点。在< code>DateTimeFormatter上查看“宽松”模式。或许可以使用< code > DateTimeFormatterBuilder 来构建一个灵活的< code>DateTimeFormatter。但坦率地说,我会拒绝这样的数据作为错误的输入。提供可靠的数据应该是数据发布者的工作,而不是猜测错误数据背后意图的消费者的工作。

    预期输入

    '2016-13-19' '2016'

    同样,试图猜测危险游戏中无效输入的有效部分,我不会玩。如果月份和日期无效,您如何知道年份有效?更糟糕的是,如果这些数据的发布者可以发出这样的错误数据,你怎么知道一个明显有效的2018-03-19输入实际上是正确的?如果第13个月是一个错误,那么如何知道月份为03的输入也不是一个错误?

    向这些有问题的数据发布者传授有关ISO 8601标准的信息,并要求他们修复错误。

     类似资料: