Date formatting with special pattern

569 Views Asked by At

I have input date like April 17th, 2024. Date was constructed by google speech to text service.

To format this date into different format I would use next code:

        String input = "April 17th, 2024";
        DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMM d, uuuu" )
                .withLocale( Locale.US );
        ZonedDateTime zdt = ZonedDateTime.parse( input , f );

        LocalDate ld = zdt.toLocalDate();
        DateTimeFormatter fLocalDate = DateTimeFormatter.ofPattern( "dd/MM/uuuu" );
        String output = ld.format( fLocalDate);
        System.out.println(output);

...the issue is that input date should be April 17, 2024 or pattern have to be improved.

Very strict solution is to cut out letters after number.

I would prefer to avoid of adding additional logic and improve date pattern for input data. Exactly with this step I need help (I can't find correct solution in java doc).

So I hope to get formatter correction or confirmation, that java doesn't support standards where date can be 17th, 3rd and so on.

2

There are 2 best solutions below

3
On

Java's date formatters/parsers don't support ordinal numbers.

It doesn't really matter what you prefer, you have to remove the ordinal suffix yourself, before invoking the parser.

It really isn't that bad, e.g.

ZonedDateTime zdt = ZonedDateTime.parse( input.replaceFirst("(?:st|nd|rd|th),", ",") , f );
0
On

it seems that java.time doesn't support ordinal numbers.

a "pattern solution" I can think of, would be one using optional sections (i.e characters between [ and ]): MMMM d['th']['st']['nd']['rd'], yyyy

for example:

jshell> var fmt = DateTimeFormatter.ofPattern("MMMM d['th']['st']['nd']['rd'], yyyy").withLocale(Locale.US)
fmt ==> Text(MonthOfYear)' 'Value(DayOfMonth)['th']['st'] ... earOfEra,4,19,EXCEEDS_PAD)

jshell> LocalDate.parse("April 17th, 2024", fmt)
$63 ==> 2024-04-17

jshell> LocalDate.parse("April 1st, 2024", fmt)
$64 ==> 2024-04-01

jshell> LocalDate.parse("April 3rd, 2024", fmt)
$65 ==> 2024-04-03

jshell> LocalDate.parse("April 4, 2024", fmt)
$66 ==> 2024-04-04

it will reject others characters:

jshell> LocalDate.parse("April 1fo, 2024", fmt)
|  Exception java.time.format.DateTimeParseException: Text 'April 1fo, 2024' could not be parsed at index 7
|        at DateTimeFormatter.parseResolved0 (DateTimeFormatter.java:2046)
|        at DateTimeFormatter.parse (DateTimeFormatter.java:1948)
|        at LocalDate.parse (LocalDate.java:428)
|        at (#68:1)

jshell> LocalDate.parse("April 1baar, 2024", fmt)
|  Exception java.time.format.DateTimeParseException: Text 'April 1baar, 2024' could not be parsed at index 7
|        at DateTimeFormatter.parseResolved0 (DateTimeFormatter.java:2046)
|        at DateTimeFormatter.parse (DateTimeFormatter.java:1948)
|        at LocalDate.parse (LocalDate.java:428)
|        at (#69:1)

but it will accept e.g. April 1th, 2024, even if is not strictly correct:

jshell> LocalDate.parse("April 1th, 2024", fmt)
$67 ==> 2024-04-01

and it will also accept January 3thstndrd, 2024. I don't know if could be a problem:

jshell> LocalDate.parse("January 3thstndrd, 2024", fmt)
$97 ==> 2024-01-03