Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用DateTimeFormatter在java8中处理yyyy-mm和yyyy_Java_Date_Java 8_Date Parsing_Java Time - Fatal编程技术网

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

如何使用DateTimeFormatter在java8中处理yyyy-mm和yyyy,java,date,java-8,date-parsing,java-time,Java,Date,Java 8,Date Parsing,Java Time,我使用SimpleDataFormat格式化或验证日期,但我希望通过使用Java8DateTimeFormatter使其线程安全。我很难达到某些要求 我的应用程序只接受三种格式。 “yyyy-MM-dd”、“yyyy-MM”、“yyyy” 以下是输入和预期输出: input expected '2018-03-19' '2018-03-19' '2018-03' '2018-03' '2018' '2018' '2

我使用SimpleDataFormat格式化或验证日期,但我希望通过使用Java8DateTimeFormatter使其线程安全。我很难达到某些要求

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

以下是输入和预期输出:

  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中实现相同的结果

    /*Java8日期时间格式化程序 DateTimeFormatter DateTimeFormatter=新的DateTimeFormatter(“yyyy-MM-dd”)

  • 当所有的年、月和日期值都正确时,上面的代码段可以工作。任何帮助都将不胜感激

    我使用SimpleDataFormat格式化或验证日期

    切勿使用
    SimpleDataFormat

    多年前,与最早版本的Java捆绑在一起的糟糕的日期时间类被中定义的现代Java.time类所取代

    使用java 8 DateTimeFormatter实现线程安全

    是的,与传统的日期时间类不同,java.time类使用并且是经过设计的

    以下是输入和预期输出:

      input             expected
    '2018-03-19'       '2018-03-19'
    '2018-03'          '2018-03'
    '2018'             '2018'
    '2017-02-54'       '2017-02'
    '2016-13-19'       '2016'
    
    您的一些输入可以通过其长度来检测

    // 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" ) ;
    
    请注意,上述输入都符合。在解析/生成字符串时,java.time类默认使用ISO 8601格式。因此,无需指定格式化模式。因此不需要显式的
    DateTimeFormatter
    对象

    “2017-02-54”“2017-02”

    这个例子使我困惑。如果你的意思是“当遇到一个月的某一天无效时,只需使用年和月,而忽略该天”,我想你可以这样做。查看
    DateTimeFormatter
    上的“宽松”模式。也许可以使用
    DateTimeFormatterBuilder
    构建灵活的
    DateTimeFormatter
    。但坦率地说,我会拒绝这些数据作为错误的输入。产生可靠的数据应该是数据发布者的工作,而不是消费者猜测错误数据背后的意图的工作

    预期投入

    “2016-13-19”“2016”

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


    向出版商传授有关标准的这些有问题的数据,并要求他们修复错误。

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

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

    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());
        }
    
    输出为:

    我不明白为什么您有这些特殊的需求,也不明白您发布的旧代码如何产生您想要的结果。如果你解释得更深入一些,我们可能会提出更好的建议。在任何情况下,我们都祝贺您决定使用java.time,这是一种现代的java日期和时间API。
    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