0

I'm trying, using java, to parse a given string to DateTime, given that the string is in the following format:
YYYY-MM-DDTHH:mm:ss[.s+]Z
The milliseconds are optional and can be any nubmer of numbers after the decimal point. How can it be done simply?

Bruce Kent
  • 73
  • 1
  • 6
  • "and can be any nubmer of numbers after the decimal point" - do you really mean that? Does ".1" mean 100 milliseconds or 1 millisecond? What about ".3456"? – Jon Skeet Mar 07 '17 at 14:36
  • Had you tried? Please post your code. – freedev Mar 07 '17 at 14:38
  • 1
    If milliseconds are optional than remove these from String before parsing – Sanjeev Mar 07 '17 at 14:44
  • http://stackoverflow.com/questions/1459656/how-to-get-the-current-time-in-yyyy-mm-dd-hhmisec-millisecond-format-in-java – jiveturkey Mar 07 '17 at 14:52
  • Do you need the milliseconds if they are present? – Ole V.V. Mar 07 '17 at 14:59
  • Sadly, I can't post my code online. First, I came to realize these aren't milliseconds. After the decimal point is 'sub-second', so .5 means half a second and not 5 milliseconds. Second, I would prefer not to remove these digits, since it will be considered as data lost in translation, and I try to minimize that. – Bruce Kent Mar 08 '17 at 15:23

2 Answers2

2

First, your format string is wrong. Year and day should be in lowercase, i.e. yyyy and dd, and the T is literal, so it should be quoted, i.e. 'T'.

Assuming that by "any number of numbers after the decimal point" you're actually talking about between 0 and 9 digits, i.e. nanoseconds, the use of the word "milliseconds" is misleading. Fractional seconds would be the right way to say that.

To support varying number of fractional digits with Java 8 Time API, use DateTimeFormatterBuilder like this:

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
        .appendPattern("uuuu-MM-dd'T'HH:mm:ss")
        .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
        .appendOffset("+HH:mm", "+00:00")
        .toFormatter();
System.out.println(OffsetDateTime.parse("2017-03-07T09:47:15+01:00", fmt));
System.out.println(OffsetDateTime.parse("2017-03-07T09:47:15.123456789-02:00", fmt));
System.out.println(OffsetDateTime.parse("2017-03-07T09:47:15.42000-05:30", fmt));
System.out.println(OffsetDateTime.parse("2017-03-07T09:47:15.2468000-05:30", fmt));

Output

2017-03-07T09:47:15+01:00
2017-03-07T09:47:15.123456789-02:00
2017-03-07T09:47:15.420-05:30
2017-03-07T09:47:15.246800-05:30

As you can see, trailing zeroes are truncated in 3-block increments when the OffsetDateTime value is printed, i.e. when toString() is used to format the result.

Andreas
  • 154,647
  • 11
  • 152
  • 247
1

OffsetDateTime.parse() does this out of the box. Say we have:

    String[] input = {
            "2017-03-07T16:06:13+01:00",
            "2017-03-07T16:06:13.1+01:00",
            "2017-03-07T16:06:13.22+01:00",
            "2017-03-07T16:06:13.333+01:00",
            "2017-03-07T16:06:13.4444+01:00",
            "2017-03-07T16:06:13.55555+01:00",
            "2017-03-07T16:06:13.666666+01:00",
            "2017-03-07T16:06:13.7777777+01:00",
            "2017-03-07T16:06:13.88888888+01:00",
            "2017-03-07T16:06:13.999999999+01:00"
    };

    for (String ips : input) {
        OffsetDateTime dt = OffsetDateTime.parse(ips);
        System.out.println(dt);
    }

This prints:

2017-03-07T16:06:13+01:00
2017-03-07T16:06:13.100+01:00
2017-03-07T16:06:13.220+01:00
2017-03-07T16:06:13.333+01:00
2017-03-07T16:06:13.444400+01:00
2017-03-07T16:06:13.555550+01:00
2017-03-07T16:06:13.666666+01:00
2017-03-07T16:06:13.777777700+01:00
2017-03-07T16:06:13.888888880+01:00
2017-03-07T16:06:13.999999999+01:00

As Andreas noted in his answer, OffsetDateTime.toString() prints as many groups of three decimals as necessary for full accuracy. You may of course do you own formatting, but I consider this outside the question.

You do get a DateTimeParseException if you try to feed it 10 decimals (or more), though.

Community
  • 1
  • 1
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161