1

My client sends me dates in ISO8601 which sometimes contains millisecond with zone and sometimes without millisecond and zone.

for example: 2019-05-01T06:55:43+01:00, 2019-05-01T06:55

I am using new time Java 8 API(LocalDateTime, DateTimeFormatter etc).

I didn't find a Date class with formatter which can handle both, with millisecond and zone and without this.

I am trying do do input date validation by using a single format

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(templateFormat, locale);


    try {
        ldt = LocalDateTime.parse(context, formatter );
        String result = ldt.format(formatter);
        return result.equals(context);
    } catch (DateTimeParseException e) {
        try {
            LocalDate ld = LocalDate.parse(context, formatter );
            String result = ld.format(formatter);
            return result.equals(context);

I am asking if there is a formatter which caches both, i can use multiple date classes, and if i fail continue to the next, for example (LocalDateTime, LocalDate, OffsetDateTime) but i need to use a single formatter

  • 2
    How do you want to handle each? I mean since they don’t contain the same information. – Ole V.V. May 05 '19 at 13:48
  • 1
    This is similar, though not the same: [How to parse different ISO date/time formats with Jackson and java.time?](https://stackoverflow.com/questions/49390734/how-to-parse-different-iso-date-time-formats-with-jackson-and-java-time) (doesn’t handle a format without any UTC offset, only different formats of that UTC offset). – Ole V.V. May 05 '19 at 13:53
  • You may try to parse using the 1-arg `OffsetDateTime.parse` and if it fails use the one-arg `LocalDateTime.parse` instead. Or if you have a default offset or zone to use for those datetimes that come without offset, you may specify an optional offset and a default offset or zone. – Ole V.V. May 05 '19 at 13:57
  • 1
    Possible duplicate of [DateTimeFormatter to parse all ISO-valid styles of zone-offset](https://stackoverflow.com/questions/55807603/datetimeformatter-to-parse-all-iso-valid-styles-of-zone-offset) – Michael Gantman May 05 '19 at 14:02
  • I don't believe it's an exact duplicate of that question just as it isn't of the one I linked to. It probably *is* a dupe, but if so, we've still to find the right original question. – Ole V.V. May 05 '19 at 14:38
  • 1
    That is an offset-from-UTC on your first input, not a zone. A time zone has a name such as `Africa/Casablanca`, and is much more than a mere number of hours-minutes-seconds. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region. – Basil Bourque May 05 '19 at 21:06
  • Thanks for the clarifying edit! This is what [`DateTimeFormatter.parseBest()`](https://docs.oracle.com/javase/9/docs/api/java/time/format/DateTimeFormatter.html#parseBest-java.lang.CharSequence-java.time.temporal.TemporalQuery...-) is for. I have voted to reopen the question. – Ole V.V. May 06 '19 at 06:41
  • In your code you are trying to parse using `DateTimeFormatter.ISO_DATE` each time, but none of your example strings match that format. It’s not going to work that way. – Ole V.V. May 06 '19 at 06:43
  • 1
    You’re still leaving me confused, though. I understand now that this is for validation, but what are you precise criteria for a valid or an invalid datetime string? – Ole V.V. May 06 '19 at 07:04

1 Answers1

3

Different types

As Ole V.V. commented, your inputs:

  • 2019-05-01T06:55:43+01:00
  • 2019-05-01T06:55

…are two different animals.

The first represents a moment, a specific point on the timeline. The value includes three pieces of information:

  • date
  • time-of-day
  • offset-from-UTC

The second input has only a date and time-of-day. It lacks the context of a time zone or offset-from-UTC. So this value does not represent a moment. It is not a point on the timeline. This value represents potential moments along a range of about 26-27 hours, the range of time zones around the globe. Does the second mean 6 AM in Tokyo? Or Paris, when 6 AM occurs several hours later? Or even more hours later when 6 AM arrives in Québec?

So your data source is confused or broken if it is feeding you an arbitrary mix of these values. I suggest consulting with the publisher of that data to determine their intent, and perhaps educate them about the difference in meaning.

Parsing

for example: 2019-05-01T06:55:43+01:00, 2019-05-01T06:55

To answer your specific question:

Trap for the DateTimeParseException. If thrown when parsing for one class, try parsing with the other class.

Both inputs are in standard ISO 8601 format. The java.time classes use the standard formats by default when parsing/generating strings. So no need to specify formatting patterns.

try {
    OffsetDateTime odt = OffsetDateTime.parse( input ) ;
    …
} catch ( DateTimeParseException e ) {
    LocalDateTime ldt = LocalDateTime.parse( input ) ;
    …
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • *"I suggest consulting with the publisher of that data to determine their intent, and perhaps educate them about the difference in meaning."* – Excellent advice. It is actually the client side which is broken, so they need to fix this. – MC Emperor May 06 '19 at 05:56
  • and if i want to provide the formatter, what should be the formatter. i am getting date, parse the date and use the reverse function using format, and than check equality. i am doing so for input date validation – user1116404 May 06 '19 at 06:32
  • Thanks, could you see what i added in my question? I am trying to do input date validation by using a single formatter – user1116404 May 06 '19 at 07:09
  • @user1116404 As I showed in my Answer’s example code, the way to validate these inputs is by trapping for `DateTimeParseException`. If you try to parse as both types and still get the exception, then you know you have faulty input. There is no point in trying to use a single formatter as you have two different outputs: one is a moment, the other is not. Apparently you have not yet understood the lesson in my Answer. I suggest you spend some time reading the class documentation, the Oracle tutorial on date-time, and search Stack Overflow. – Basil Bourque May 06 '19 at 15:15
  • i got your answer, my question if there is i a formatter which will catch one of them, may be a formatter with optional pattern, meaning the formatter indicates that we may get this data but it is not a mandatory to get this, for example, formatter which tells that we may get millisecond – user1116404 May 07 '19 at 06:06
  • @user1116404 The default formatters for the ISO 8601 formats automatically tolerate an omitted or present fractional second. So, no issue there. That is an entirely different concern than having an offset-from-UTC. – Basil Bourque May 07 '19 at 09:00