Why I am not able to parse 2013-03-10T02:59:59Z from PST in Java using parse method of java.text.SimpleDateFormat?

179 Views Asked by At

For certain input values though format and all things are correct, I am getting ParseException from SimpleDateFormat.parse(String input) method.

I'm in a scenario where I need to convert time from PST timezone to local timezone; it works almost all of the time for acceptable input except for 2013-03-10T02:00:00Z to 2013-03-10T02:59:59Z. It seems strange; I tried several JDKs and machines, but the result is the same, it throws

Method threw 'java.text.ParseException' exception.

My expectation is to parse this date properly and return non null date object instead of throwing exception.

Snippet to test this:

    public static void main(String[] args) throws Exception {
        System.out.println(getDateFromString("2013-03-10T02:59:59Z", "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH));
    }

    public static Date getDateFromString(String dateText, String format, Locale locale) {
        Date date = null;
        SimpleDateFormat simpleDateFormat = null;
        try {
            simpleDateFormat = new SimpleDateFormat(format, locale);
            simpleDateFormat.setTimeZone(TimeZone.getTimeZone("PST"));
            //Supporting strict validation of date format
            simpleDateFormat.setLenient(false);
            date = simpleDateFormat.parse(dateText);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
1

There are 1 best solutions below

2
Basil Bourque On

tl;dr

Your parse attempt failed because you misinterpreted the input text. The resulting erroneous value represented a date and time in a particular time zone that never existed.

Instead, correctly parse your input, and adjust into a time zone, using java.time classes.

Instant
.parse( "2013-03-10T02:00:00Z" )
.atZone( ZoneId.of( "America/Los_Angeles" ) )
.toString()

See Ideone.com.

2013-03-09T18:00-08:00[America/Los_Angeles]

Your code

Never put quotes around the Z in a date-time formatting pattern. That says to expect but ignore vital information: an offset from UTC of zero hours-minutes-seconds.

You asked:

why am I getting an issue with current code?

As other commented, I assume the legacy date-time classes attempted to parse your input of xx while guessing the value PST meant the time zone America/Los_Angeles. This would have happened because (a) you told the formatter to ignore the actual intended offset of zero represented by that Z, and then you (b) told the formatter to assume a default zone of PST.

So your code defies the intentions of whomever sent you that input data. Instead of 2013-03-10 02:59:59 in UTC, you tried to parse a value of 2013-03-10 02:59:59 in America/Los_Angeles.

As others have commented, that moment never existed. At 2 AM on March 13, 2013 all the people using time zone America/Los_Angeles jumped their clocks forward to 3 AM. This jump is the “Spring Ahead” cutover for Daylight Saving Time (DST). That day of March 13th was only 23 hours long, not 24 hours. The 02:00-03:00 hour was excised.

So your parse attempted failed because your misinterpreted input was coincidentally found to be senseless.

Revised code

Use modern java.time classes. Never use the terrible legacy classes.

Your input is in standard ISO 8601 format. No need to define a formatting pattern.

Instant instant = Instant.parse( "2013-03-10T02:59:059Z" ) ;

instant.toString() = 2013-03-10T02:59:59Z

Adjust to a desired time zone.

PST is not a real time zone. Perhaps you meant the time zone used by much of the west coast of the United States mainland.

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

zdt.toString() = 2013-03-09T18:59:59-08:00[America/Los_Angeles]

Note the change in date as well as time-of-day.

See that code run.

If you must have a java.util.Date to interoperate with code not yet updated to java.time, use new conversion methods added to the old classes.

java.util.Date d = Date.from( instant ) ;  // A date-time as seen in UTC, an offset of zero hours-minutes-seconds. 

Always search Stack Overflow before posting. All this has been covered many times before. Search to learn more.