M.E.
M.E.

Reputation: 5527

Parsing a Date and Time string into a ZonedDateTime object

I am trying to parse a String with a date and time in a known time zone. The strings have the following format:

2019-03-07 00:05:00-05:00

I have tried this:

package com.example.test;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Test {

    public static void main( String[] args ) {

        ZoneId myTimeZone = ZoneId.of("US/Eastern");

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ssXX");

        ZonedDateTime zdt = ZonedDateTime.parse("2019-03-07 00:05:00-05:00", dateTimeFormatter.withZone(myTimeZone));

        System.out.println(zdt);

    }

}

This is the exception thrown:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-03-07 00:05:00-05:00' could not be parsed at index 19
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
    at com.example.test.Test.main(Test.java:24)
C:\Users\user\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)

I am using Java 1.8.0_191.

Upvotes: 2

Views: 1321

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 340230

tl;dr

OffsetDateTime.parse( 
    "2019-03-07 00:05:00-05:00".replace( " " , "T" ) 
)

Use the offset, Luke

You do not need the time zone. Your string carries an offset-from-UTC of five hours behind UTC. That tells us a specific moment, a point on the timeline.

ISO 8601

Replace that SPACE in the middle of your input with a T to comply with ISO 8601. The java.time classes use the standard formats by default. So no need to specify a formatting pattern.

OffsetDateTime

Parse as an OffsetDateTime.

String input = "2019-03-07 00:05:00-05:00".replace( " " , "T" ) ;
OffsetDateTime odt = OffsetDateTime.parse( input ) ;

ZonedDateTime

If you know for certain this value was intended to a particular time zone, you can apply a ZoneId to get a ZonedDateTime.

Be aware that US/Eastern is deprecated as a time zone name. The modern approach is Continent/Region. Perhaps you mean America/New_York.

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

Upvotes: 4

amseager
amseager

Reputation: 6391

Use this pattern: yyyy-MM-dd HH:mm:ssXXX

From the docs:

Offset X and x: ... Two letters outputs the hour and minute, without a colon, such as '+0130'. Three letters outputs the hour and minute, with a colon, such as '+01:30'.

So if your string contains a colon inside timezone, you should use 3 "X-es".

And capital Y means "week-based-year", not a regular one (y).

Upvotes: 4

Related Questions