The hack
String dateWithSpace = "Tue, 12 May";
DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("EEE, d [MMMM][MMM]")
.toFormatter(Locale.ENGLISH);
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("E_d_MMMM", Locale.ENGLISH);
TemporalAccessor parsed = formatter1.parse(dateWithSpace .trim());
String formatted = formatter2.format(parsed);
System.out.println(formatted);
Output:
Tue_12_May
The challenge here is that we cannot represent “Tuesday 12th May” in a LocalDate
. For a LocalDate
we need a year. We cannot just decide on some fixed year for two reasons: (1) Whatever we decide would probably be wrong and hence introduce an error in our program, also when the error would not surface initially; (2) LocalDate
would object to the incorrect day of week if we didn’t have the luck to pick a year where May 12 falls on a Tuesday. And even if we forced it somehow, it would not print Tue
back, but the correct day of week for the year we had picked. There isn’t any other type that holds a day of week, day of month and month without a year either.
The good solution would be to find out which year is correct. Maybe try this year and next year in turn and throw an exception if neither matches?
In the meantime my hack is not to decide on any concrete type but just use the undecided TemporalAccessor
interface.
EDIT: To accept short month names in full (June
, July
and also May
) and three letter abbreviations for longer month names (e.g., Feb
, Dec
), I am using [MMMM][MMM]
: optional full month name followed by optional month abbreviation. So one of them will always match and the other be ignored.
Other examples of input and output:
Wed, 1 July -> Wed_1_July
Thu, 27 Aug -> Thu_27_August
Mon, 8 Feb -> Mon_8_February
On your code
I have some comments, most of them minor:
- You shouldn’t need
parseCaseInsensitive()
for your example string (maybe for other strings you might be getting, I cannot know).
- EDIT: To accept one digit day of month put just one
d
in the format pattern string for parsing. It will still accept two digits too. Further decide whether you want two digits in the output always or only one digit for the first 9 days of the month.
- Prefer
MMM
over LLL
in the format pattern for parsing. LLL
is for when the month is not part of a date (in some languages that makes a difference as to what form of the month name to use).
- For formatting too use
MMM
for month abbreviation, not M/L
.
- Provide a locale for formatting too.