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.
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.
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).
DateTimeFormatter is a replacement for the old SimpleDateFormat that is thread-safe and provides additional functionality.
My own practice:
T
by default.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 ).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With