Ben
Ben

Reputation: 11

String in UTC getting converted to EST Instant

I have a date time string with zoning:

“2019-07-15 00:00+00:00”

When I use the following code, the instant it produces is equivalent to the date time “2019-07-14 20:00:00+00:00”. Why is that? I want the Instant to be equivalent to the time initially given.

Instant myInstant = OffsetDateTime.parse(“2019-07-15 00:00+00:00”, DateTimeFormatter.ofPattern(“uuuu-MM-dd HH:mm:ssXXXXX”)).toInstant();

Upvotes: 0

Views: 65

Answers (1)

Basil Bourque
Basil Bourque

Reputation: 338516

tl;dr

ISO 8601

Replace SPACE with T, per ISO 8601 standard.

OffsetDateTime
.parse(
    "2019-07-15 00:00+00:00".replace( " " , "T" ) 
)
.toInstant()

See this code run live at IdeOne.com.

2019-07-15T00:00:00Z

Formatting pattern

Or specify a formatting pattern to match your exact input.

OffsetDateTime
.parse(
    "2019-07-15 00:00+00:00" ,
    DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mmxxx" )
)

Details

ISO 8601

Rather than wrestle the formatter, I recommend altering your input string to comply with ISO 8601 standard. Replace the SPACE in the middle with a T.

String input = "2019-07-15 00:00+00:00".replace( " " , "T" ) ;

2019-07-15T00:00+00:00

Parse as an OffsetDateTime. The java.time classes use the ISO 8601 formats by default when parsing/generating text. So no need to specify a formatting pattern.

OffsetDateTime odt = OffsetDateTime.parse( input ) ;

odt.toString(): 2019-07-15T00:00Z

That value is already in UTC (an offset of zero hours-minutes-seconds). But if you wish, you can extract an Instant which is always in UTC by definition.

Instant instant = odt.toInstant() ;

instant.toString(): 2019-07-15T00:00:00Z

OffsetDateTime vs Instant

I want the Instant to be equivalent to the time initially given.

They are equivalent. Both the odt & instant objects represent the same moment in time, as well as the same moment intended by your string input.

The Z on the end means an offset of zero, or UTC itself. The Z here is pronounced “Zulu” by tradition. The Z is short for +00:00.

A Instant is always in UTC, while a OffsetDateTime object may have any offset, zero or otherwise. Another difference is that OffsetDateTime is more flexible in generating strings, able to use a DateTimeFormatter.

Pattern: uuuu-MM-dd HH:mmxxx

Instant myInstant = OffsetDateTime.parse(“2019-07-15 00:00+00:00”, DateTimeFormatter.ofPattern(“uuuu-MM-dd HH:mm:ssXXXXX”)).toInstant();

I suggest you handle the DateTimeFormatter separately.

String input = "2019-07-15 00:00+00:00" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mmxxx" ) ;
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;
Instant instant = odt.toInstant() ;

➥ That formatting pattern above uses xxx to parse the +00:00. The x (or X) character is for numeric offsets. Three such letters are for an offset hours-with-minutes along with a COLON character in between (otherwise optional). The lowercase x characters are for zeros rather than the Z abbreviation. To quote the doc:

Three letters outputs the hour and minute, with a colon, such as '+01:30'.

… Pattern letter 'X' (upper case) will output 'Z' when the offset to be output would be zero, whereas pattern letter 'x' (lower case) will output '+00', '+0000', or '+00:00'.

Dump to console.

System.out.println( "odt.toString(): " + odt ) ;
System.out.println( "instant.toString(): " + instant ) ;

See this code run live at IdeOne.com.

odt.toString(): 2019-07-15T00:00Z

instant.toString(): 2019-07-15T00:00:00Z

Upvotes: 1

Related Questions