2

I am having problem parsing dates in Java. Below is the code.

 String dateString = "2017-12-13T16:49:20.730555904Z";
 List<String> formatStrings = Arrays.asList("yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS'Z'");

    for (String formatString : formatStrings)
    {
        try
        {
            SimpleDateFormat formatter = new SimpleDateFormat(formatString);
            formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date d = formatter.parse(dateString);
            System.out.println("Format is:" + formatString);
            System.out.println("Orignal Date: " + d);
            System.out.println("Orignal MS: " + d.getTime());

            return d;
        }
        catch (ParseException e) {}
    }

    return null;
}

When I run this program, I get the following output.

Format is:yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS'Z'
Orignal Date: Fri Dec 22 03:45:15 UTC 2017
Orignal MS: 1513914315904

I am not sure why it is giving me Dec 22 when it should be Dec 13. But if I change my input date to this.

String dateString = "2017-12-13T16:49:20.7Z";

i.e only one character before the Z. then I get the correct output.

Format is:yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS'Z'
Orignal Date: Wed Dec 13 16:49:20 UTC 2017
Orignal MS: 1513183760007

It gives me correct output till 3 numbers before the Z. If more than 3 numbers than I got the wrong output.

It would be great if someone can point me out what I am missing here.

PS: I am parsing these dates in android. I have set min API level to 16 and java.time is not available for API level below 26.

Ole V.V.
  • 76,217
  • 14
  • 120
  • 142
Waqar Ahmed
  • 4,831
  • 1
  • 22
  • 41
  • Related: [java.util.Date format SSSSSS: if not microseconds what are the last 3 digits?](https://stackoverflow.com/questions/19223171/java-util-date-format-ssssss-if-not-microseconds-what-are-the-last-3-digits) – Ole V.V. Dec 13 '17 at 19:23

1 Answers1

12

S in SimpleDateFormat specifies a number of milliseconds, not a fraction of a second. You've specified 730555904 milliseconds, which is ~8.45 days - hence the date change.

java.util.Date only has a precision of milliseconds. I would recommend using the java.time package, which has a precision of nanoseconds, like your input. Use DateTimeFormatter for parsing. Note that in DateTimeFormatter, the S specifier is for fraction-of-a-second.

Even better, Instant.parse uses the right format anyway:

import java.time.*;

public class Test {
    public static void main(String... args) throws Exception {
        String text = "2017-12-13T16:49:20.730555904Z";
        Instant instant = Instant.parse(text);
        System.out.println(instant);
    }
}
Jon Skeet
  • 1,335,956
  • 823
  • 8,931
  • 9,049