I have done some reading on this and tried to work through examples from other StackOverflow threads but I keep running into an exception when parsing the date/time if I try to specify optional sections.
this is the input. The optional sections are the AM/PM which may not always be in the input, and the timezone which may be 4 characters:
09:10:05.584 AM EST Wed Nov 29 2023
This is the pattern that works for this input, but not other inputs, such as if there is no timezone
hh:mm:ss.SSS a zzz E MMM dd yyyy
If I try to do something like this and create optional patterns I get a parse exception at position 12 in the input, which is just after the milliseconds
hh:mm:ss.SSS[ a [z]zzz ]E MMM dd yyyy
this is the code, currently set to the format that fails:
public static final String TIME_FORMAT = "hh:mm:ss.SSS[ a [z]zzz ]E MMM dd yyyy";
public static String ParseDate(String input, String format) {
String retVal = "";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format, Locale.ENGLISH);
TemporalAccessor ta = formatter.parseBest(input, LocalDateTime::from, LocalDate::from);
retVal = ta.toString();
System.out.println("Parsed date is: "+ retVal);
return retVal;
}
This is a tricky one, because the syntax for an optional section of the DateTimeFormatter
class specifically wants the space between the optional element and its predecessor included within square brackets.
The documentation of the parseBest() method shows an example of a pattern with an optional timezone ID, uuuu-MM-dd HH.mm[ VV]
, where the space between the minute and the timezone ID is included within the optional section.
In your snippet, the first optional was written properly hh:mm:ss.SSS[ a...
(with the space between SSS
and a
included within square brackets), but then the optional part for the timezone name was written a [z]zzz
instead of a[ z]zzz
. In your case, you can either nest the optional sections like so hh:mm:ss.SSS[[ a] zzz] E MMM dd yyyy
, or write them as individual optional sections hh:mm:ss.SSS[ a][ z][ zzz] E MMM dd yyyy
.
Here is a re-written version of your code covering the 4 cases:
public class Main {
public static void main(String[] args) {
parseDate("09:10:05.584 AM EST Wed Nov 29 2023", TIME_FORMAT);
parseDate("09:10:05.584 AM Wed Nov 29 2023", TIME_FORMAT);
parseDate("09:10:05.584 EST Wed Nov 29 2023", TIME_FORMAT);
parseDate("09:10:05.584 Wed Nov 29 2023", TIME_FORMAT);
}
public static final String TIME_FORMAT = "HH:mm:ss.SSS[ a][ z][zzz] E MMM dd yyyy";
public static String parseDate(String input, String format) {
String retVal = "";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format, Locale.ENGLISH);
TemporalAccessor ta = formatter.parseBest(input, LocalDateTime::from, LocalDate::from);
retVal = ta.toString();
System.out.println("Parsed date is: " + retVal);
return retVal;
}
}
You can quickly check the code here at this link: