Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with 'optional' T in ISO-8601 timestamp in Java 8 / JSR 310 / threeten.org ?

In Java 8 time / JSR 310 / threeten.org backport ...

Q: How do I parse ISO-8601 timestamps with either a 'T' or a space ' ' between the date portion and the time portion?

ISO-8601 format for timestamps specifies the literal 'T' to separate the date specification from the time specification:

2015-05-12T15:42:00.123

Many applications generate timestamps in this format with a space ' ' char instead of 'T'. References indicate that ISO-8601 allows this by mutual agreement.

2015-05-12 15:42:00.123

Because I am ingesting data from multiple sources I want to allow either the 'T' or the space ' '.

I observe that the pattern string allows one to specify optional components, but I do not see any way to specify a "choice" in a pattern string ...

Q: Is there any way to make a "choose-exactly-one-of-the-following" in a JSR 310 pattern string?

I was able to get this to work by constructing a DateTimeFormatter with two optional patterns:

DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
    .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    .optionalStart().appendPattern("yyyy-MM-dd HH:mm:ss.SSS").optionalEnd()
    .toFormatter();

Seeing optionalStart() and optionalEnd() led me to:

DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
    .appendPattern("[yyyy-MM-dd HH:mm:ss.SSS][yyyy-MM-dd'T'HH:mm:ss.SSS]")
    .toFormatter();

However, I am not confident that this is the correct way to deal with this situation ...

Q: What is the best-practice solution to handle multiple DateTime patterns?

Thanks in advance.

like image 789
Michael Howard Avatar asked May 12 '15 20:05

Michael Howard


People also ask

What is the T in ISO 8601?

Note that the "T" appears literally in the string, to indicate the beginning of the time element, as specified in ISO 8601. This profile does not specify how many digits may be used to represent the decimal fraction of a second.

How do I format a date in ISO 8601?

ISO 8601 represents date and time by starting with the year, followed by the month, the day, the hour, the minutes, seconds and milliseconds. For example, 2020-07-10 15:00:00.000, represents the 10th of July 2020 at 3 p.m. (in local time as there is no time zone offset specified—more on that below).

What can I use instead of SimpleDateFormat?

DateTimeFormatter is a replacement for the old SimpleDateFormat that is thread-safe and provides additional functionality.


1 Answers

Cleanse Your Input Data

My own practice:

  • Include the T by default.
  • Clean the input data before calling java.time (or Joda-Time).

When accepting text from outside my own code, I never trust such external inputs. Heck, I don’t even trust my own internal inputs. I always put such data through a cleaner. As part of that cleaning I replace any SPACE character in any expected ISO 8601 string with a T.

String datetimeInput = input.replace( " ", "T" ) ;

I also make a habit of calling the Google Guava library to trim whitespace from the input string. See this Answer for details.

And check for NULL, non-printing, and other inappropriate characters. Those non-printables make for nasty bugs.

Only after that do I call the date-time libraries ( Joda-Time or java.time ).

Trap Parsing Exception

Also, you should use a try-catch to trap for the parsing exception to more gracefully handle when the date-time input string fails to meet your expectations.

  • java.time: DateTimeParseException
  • Joda-Time: IllegalArgumentException
like image 91
Basil Bourque Avatar answered Nov 13 '22 05:11

Basil Bourque