ISO 8601 date-time format combining 'Z' and offset of '+0000'

Zilev av picture Zilev av · Mar 8, 2016 · Viewed 24.2k times · Source

I'm playing with date-time format from ISO 8601. I have this pattern:

"yyyy-MM-dd'T'HH:mm:ssZZ'Z'"

and the output is:

"2015-11-17T00:00:00+0000Z".

My question is if the output is ok, if is possible to have in a date +0000 and Z taking in account both has the same meaning time zone offset/id. Thanks in advance for clarification =)

Answer

Basil Bourque picture Basil Bourque · Mar 8, 2016

No, not OK

No, the Z is an offset-from-UTC so it should not be combined redundantly with a numerical offset of +00:00 or +0000.

ISO 8601

While I do not have access to a paid copy of the ISO 8601 spec, the Wikipedia page clearly states that the Z must follow the time-of-day:

…add a Z directly after the time without a space.

IETF RFC 3339

The freely-available RFC 3339, a profile of ISO 8601, defines a Z as being attached to a time-of-day:

A suffix … applied to a time …

The RFC also states with formal ABNF notation that we should use either a Z or a number. In ABNF, the slash (SOLIDUS) means “or” (exclusive ‘or’), while the pair of square brackets means “optional”.

time-numoffset = ("+" / "-") time-hour [[":"] time-minute]

time-zone = "Z" / time-numoffset

Furthermore, section 5.4 of the spec specifically recommends against including redundant information.

Java

The modern java.time classes built into Java use the standard ISO 8601 formats by default when parsing/generating strings. See Oracle Tutorial.

Parsing text input

With Z:

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

With +00:00:

OffsetDateTime odt = OffsetDateTime.parse( "2019-01-23T12:34:56.123456789+00:00" ) ;

Generating text output

To create a string with the Z, simply call Instant::toString.

String output = Instant.now().toString() ;  // Capture the current moment in UTC, then generate text representing that value in standard ISO 8601 using the `Z` offset-indicator.

2019-05-22T21:00:52.214709Z

To create a string with the 00:00, call OffsetDateTime::format. Generate text using a DateTimeFormatter with a formatting pattern you define.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSxxx" ) ;
String output = OffsetDateTime.now( ZoneOffset.UTC ).format( f ) ;

2019-05-22T21:00:52.319076+00:00

Truncating

You may want to truncate any microseconds or nanoseconds.

Instant
.now()
.truncatedTo( ChronoUnit.MILLIS )
.toString()

2019-05-22T21:11:28.970Z

…and…

OffsetDateTime
.now( ZoneOffset.UTC )
.truncatedTo( ChronoUnit.MILLIS )
.format( 
    DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSxxx" )
)

2019-05-22T21:11:29.078+00:00

See this code running live at IdeOne.com.