2

I am developing using Java 8 a function that must handle the conversion from String to LocalDateTime of the following dates:

  • 2019-06-20 12:18:07.207 +0000 UTC
  • 2019-06-20 12:18:07.20 +0000 UTC
  • 2019-06-20 12:18:07.2 +0000 UTC
  • 2019-06-20 12:18:07 +0000 UTC

The strings are produced from an external library that I cannot change.

Following the suggestions given in the SO answer Optional parts in SimpleDateFormat, I tried using the optional formatting offered by the type DateTimeFormatter, using the characters [ and ]. I tried the following patterns:

  • yyyy-MM-dd HH:mm:ss[.S[S[S]]] Z z
  • yyyy-MM-dd HH:mm:ss[.S[S][S]] Z z

However, neither of them works.

Any suggestion?

riccardo.cardin
  • 7,325
  • 3
  • 51
  • 93

2 Answers2

5

You can build the pattern using DateTimeFormatterBuilder and reuse ISO_LOCAL_DATE and ISO_LOCAL_TIME constants:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral(" ")
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendPattern("[ Z z]")
            .toFormatter();

    ZonedDateTime dt = ZonedDateTime.parse(date, formatter);

The trick is that DateTimeFormatter.ISO_LOCAL_TIME handles the different number of digit used to represent milliseconds its own. From DateTimeFormatter.ISO_LOCAL_TIME JavaDoc:

This returns an immutable formatter capable of formatting and parsing the ISO-8601 extended local time format. The format consists of:
[..]
One to nine digits for the nano-of-second. As many digits will be output as required.

riccardo.cardin
  • 7,325
  • 3
  • 51
  • 93
Jaywalker
  • 3,009
  • 3
  • 29
  • 42
2

I think it is better to use a DateTimeFormatterBuilder for that purpose. For the optional parts just use one of the follwing methods :

  1. OptionalStart() & OptionalEnd()
  2. Append your whole optional pattern with appendOptional()

Here is an example :

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(""
    + "[yyyy-MM-dd HH:mm:ss.SSS Z z]"
    + "[yyyy-MM-dd HH:mm:ss.SS Z z]"
    + "[yyyy-MM-dd HH:mm:ss.S Z z]"
    + "[yyyy-MM-dd HH:mm:ss Z z]"
);

Also, you can create a dtf for each optional and append them with appendOptional() and the the DateTimeFormatterBuilder

for example :

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendValue(HOUR_OF_DAY,2)
    .optionalStart()
    .appendValue(MINUTE_OF_HOUR,2)
    .optionalEnd()
    .optionalStart()
    .appendValue(SECOND_OF_MINUTE,2)
    .optionalEnd();
    .toFormatter();

This code is not tested but try to build your optional pattern each time in a start/end optional blocks.

Hassam Abdelillah
  • 2,146
  • 3
  • 15
  • 33