Java 8 optional time part not working

流过昼夜 提交于 2020-07-04 12:00:51

问题


I am trying to create date time format for optional time part currently I implemented this

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.text.ParseException;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        System.out.println(Ideone.getDate("2017-07-01T00:00:00.0Z"));
        System.out.println(Ideone.getDate("2017-07-01T00:00:00.00Z"));
        System.out.println(Ideone.getDate("2017-07-01T00:00:00.000Z"));
    }
    
    public static LocalDateTime getDate(String date) {
        try {
           
            DateTimeFormatter formatter2 =
                DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'");
            LocalDateTime ldt = LocalDateTime.parse(date, formatter2);
            
            
            return ldt;
           
        } catch (DateTimeParseException ex) {
            return null;
        }
    }
}

And having output

null

2017-07-01T00:00

2017-07-01T00:00

Now my question is, why date with 1 time fraction is not working and it is working with 2 and 3 fractions? should it entertain 1,2 and 3 fractions? or only 3 fractions?

Thanks in advance


回答1:


This seems like a bug. The millisecond part of datetime parsing seems to be in general buggy in Java 8, see this issue and its duplicates.

Relevant quote:

Worse however is that the SSS pattern has therefore ended up using strict mode when lenient mode would be appropriate. As it currently stands, DateTimeFormatter.ofPattern("hhmmss.SSS") requires three digits for milliseconds, when it was originally intended to require 0 to 9 (the lenient behaviour).

Given that the current implementation requires three digits for SSS, it is thus very surprising that adjacent value parsing does not apply.

But you seem to have found a case where requirement mentioned above does not apply either. In addition, even though the issue above is in state "fixed", your example seems to have issues in both java 8 and java 9:

>java -version
java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)

>javac Ideone.java

>java Ideone
null
2017-07-01T00:00
2017-07-01T00:00

>"c:\Program Files\Java\jdk1.8.0\bin"\javac Ideone.java

>"c:\Program Files\Java\jdk1.8.0\bin"\java Ideone
null
2017-07-01T00:00
2017-07-01T00:00

should it entertain 1,2 and 3 fractions? or only 3 fractions?

Based on the quote, it should be only 3, though originally intended to be 0-9.




回答2:


I think what you want is DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS][.S]'Z'")

Basically it's saying to first check for the long-form of 2+ fraction-of-second digits, otherwise if that optional field is not present, check for the optional field of a single fraction-of-second digit specified by [.S]




回答3:


Reason why you are getting null when you pass this is

"2017-07-01T00:00:00.0Z"

you have told the parser to expect 3 char format (see below .SSS)

DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'");

If you change it to .SS, it should work, however your last input i.e. 2017-07-01T00:00:00.000Z will break. You may want to include some logic to handle different formats



来源:https://stackoverflow.com/questions/46321529/java-8-optional-time-part-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!