如何识别日期格式?

How to identify date format?

1) 如果我打印出一个日历对象,我会得到: java.util.GregorianCalendar[time=1567535353679,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="GMT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=8,WEEK_OF_YEAR=36,WEEK_OF_MONTH=1,DAY_OF_MONTH=3,DAY_OF_YEAR=246,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=6,HOUR_OF_DAY=18,MINUTE=29,SECOND=13,MILLISECOND=679,ZONE_OFFSET=0,DST_OFFSET=0]

2) 如果我打印出 Date 对象,我得到:

Tue Sep 03 18:29:13 GMT 2019

3) 但是我正在检查生成的 XML 并且我观察到这种格式:

2014-02-28T08:00:00.000Z

我在 XML 中看到的是哪种格式?

Date-time对象没有“格式”

How to identify date format?

Date-time 对象没有“格式”。每个 class 都定义了自己的内部存储 date-time 值的机制。该机制通常是 none 我们的业务。 class的API,class的承诺,才是最重要的。

您可能将 date-time 对象生成的文本与 date-time 对象本身混为一谈。 Date-time classes 可以将文本解析为实例化的一部分。而 date-time classes 可以生成文本来表示它们的值。但是文本和对象是分开的和不同的。

避免Calendar

If I print out a calendar object I get:

Calendar::toString 方法只是其许多内部字段的一个 data-dump。显然仅用于调试,否则无用。

Calendar class and its commonly-used subclass GregorianCalendar are both now legacy。多年前,随着 JSR 310 的采用,它们被 java.time classes 所取代。永远不要使用它们。 GregorianCalendar 被专门替换为 ZonedDateTime

避免Date

If I print out a Date object I get:

Date::toString方法所在。该方法在生成文本时动态应用 JVM 当前的默认时区。 java.util.Date 实际上代表 UTC 中的一个时刻,而不是 toString 结果中看到的时区。 anti-feature 是从不使用 Date 的众多原因之一。

java.util.Date class 已替换为 java.time.Instant,也代表 UTC 中的时刻,但具有更精细的纳秒分辨率而不是毫秒分辨率。

ISO 8601

However I am examining the XML generated and I observe this format:

2014-02-28T08:00:00.000Z

该文本的格式在 ISO 8601 标准中定义。该标准被巧妙地设计为以文本形式表示 data-exchange 的各种 date-time 值。该标准取代了早期的 poorly-defined date-time 文本格式,例如早期的电子邮件协议。

java.timeclasses在parsing/generating个字符串时默认使用ISO 8601格式。

UTC 当前时刻

要以 UTC 格式捕获当前时刻,请使用 Instant

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

生成以标准 ISO 8601 格式表示该值的文本。末尾的 Z 表示 UTC,发音为“Zulu”。

2020-01-23T12:34:56.123456Z

解析这样一个字符串。

Instant instant = Instant.parse( "2020-01-23T12:34:56.123456Z" );

时区

通过特定地区、时区的人们使用的 wall-clock 时间查看同一时刻。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

通过在方括号中附加时区名称,以明智地扩展 ISO 8601 标准的格式生成字符串。

String output = zdt.toString() ;

看到这个code run live at IdeOne.com

instant.toString(): 2020-01-23T12:34:56.123456Z

zdt.toString(): 2020-01-23T07:34:56.123456-05:00[America/Montreal]

Date-time 输入 Java


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Which format am I seeing in the XML ?

XML 格式的灵感来自 ISO 8601, as specified by the XML schema documentation

3.2.7.1 Lexical representation

The ·lexical space· of dateTime consists of finite-length sequences of characters of the form: '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?