ZonedDateTime ignores 00 for ss part

杀马特。学长 韩版系。学妹 提交于 2020-01-30 12:23:51

问题


I am trying to convert string value "2018-10-11T12:00:00Z"; to ZonedDateTime. If I use the default ZonedDateTime.parse(zonedDateTime) then ss portion i.e. 00 is removed and I get "2018-10-11T12:00Z" as output.

Can you please help how to retain 00 as SS part.

String zonedDateTime = "2018-10-11T12:00:00Z";

ZonedDateTime z =  ZonedDateTime.parse(zonedDateTime);
System.out.println(z);  // return 2018-10-11T12:00Z

ZonedDateTime z1 =  ZonedDateTime.parse (zonedDateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ") );

System.out.println(z1);  // Exception : Text '2018-10-11T12:00:00Z' could not be parsed at index 19

回答1:


Printing the seconds

When you just print a ZonedDateTime using System.out.println, you are implicitly calling its toString method. When the seconds and fraction of second are 0, toString leaves them out. To print them anyway, use a formatter for formatting (as opposed to using one for parsing):

    DateTimeFormatter formatterWithSeconds = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX");
    System.out.println("z with seconds: " + z.format(formatterWithSeconds));

Output is:

z with seconds: 2018-10-11T12:00:00Z

The important distinction here is between the ZonedDateTime object and its string representation. The ZonedDateTimeobject always contains seconds and nanoseconds, also when they are 0. The string representation may or may not include them. The one-arg ZonedDateTime.parse has parsed the 00 seconds. BTW, it accepts strings both with and without seconds.

Use Instant or OffsetDateTime

As an aside, since your string contains an offset (Z) and no time zone (like Africa/Nairobi), an OffsetDateTime matches more precisely as representation. The code will work fine if you just search/replace ZonedDateTime with OffsetDateTime throughout since the APIs are similar.

If the offset is always Z (for “Zulu time zone” or offset 0 from UTC), use Instant:

    String instantString = "2018-10-11T12:00:00Z";
    Instant i = Instant.parse(instantString);
    System.out.println("As Instant: " + i);

I have given your String variable a name that is more appropriate for this snippet; it’s still the same string. Output:

As Instant: 2018-10-11T12:00:00Z

Curiously Instant.toString does print the seconds even when they are 0.

Please read more about the correct type to use in the answer by @Basil Bourque.

What went wrong in your code? Pattern letter for parsing Z

// Exception : Text '2018-10-11T12:00:00Z' could not be parsed at index 19

The problem here is not with the seconds, nor with the ss. Index 19 is where the Z is in your string. The two-arg ZonedDateTime.parse objects because pattern letter Z does not match a Z in the date-time string. If you do need to supply a format pattern string for parsing Z, use uppercase X (one or more of them depending on how a non-zero offset looks). From the documentation of pattern letters:

  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00

Links

  • DateTimeFormatter documentation
  • Related question: Parse Date String in Java



回答2:


The Answer by Ole V.V. is correct and should be accepted. I will add one thought and a handy reference table.

Instant

I want to emphasize the point made in that other Answer, that ZonedDateTime technically works but is not the most appropriate class to parse a string such as 2018-10-11T12:00:00Z. This format is define in the ISO 8601 standard. That Z on the end, pronounced “Zulu”, means UTC (an offset of zero hours-minutes-seconds).

The ISO 8601 standard formats are used by default in the java.time classes. No need to specify a formatting pattern.

Instant is the appropriate class to represent a moment in UTC.

Instant instant = Instant.parse( "2018-10-11T12:00:00Z" ) ;

Generate a String in the same ISO 8601 standard format.

String output = instant.toString() ;

The OffsetDateTime class represents a moment in UTC or with other offset-from-UTC values, any number of hours-minutes-seconds. This class is also more flexible such as in generating strings with various formats via DateTimeFormatter class. And this class is required to be supported by JDBC 4.2 and later drivers, whereas Instant and ZonedDateTime support is optional in JDBC.

Be clear on the difference between offset and time zone.

  • Offset-from-UTC
    Simply a number of hours-minutes-seconds. Positive for being ahead of UTC (towards the east) and negative for being behind UTC (towards the west).
  • Time zone
    A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region.

Date-time types in Java

Here is a reference table for the basic date-time data types in Java, both modern and legacy. Avoid the legacy types: They are terrible, designed by people who did not understand the complexities and subtleties of date-time handling.



来源:https://stackoverflow.com/questions/57325267/zoneddatetime-ignores-00-for-ss-part

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