java.time
Standalone form of month name
DateTimeFormatterBuilder.appendText(TemporalField, Map<Long, String>)
I warmly recommend that you use java.time, the modern Java date and time API (links at the bottom), for your date and time work.
You are trying to parse a date-time string in Ukrainian. We would immediately have expected Java to do this out of the box using uk
or uk-UA
locale. Edit: To my surprise your strings are using what Java considers the standalone form of month names (it seems that I have not understood what the standalone form of a month name means). To specify this form in formatting use LLLL
in the format pattern string rather than MMMM
. Also the name of Friday in your strings is different from the name that Java knows (пʼятниця with an apostrophe, which, as Basil Bourque has already said, comes from CLDR). The solution is, as you already tried, to specify your own names of the days. In java.time this is done through a DateTimeFormatterBuilder
and its two-arg appendText
method. For example:
private static final Map<Long, String> DAY_NAMES = Map.of(1L, "понеділок", 2L, "вівторок",
3L, "середа", 4L, "четвер", 5L, "пятниця", 6L, "субота", 7L, "неділя");
private static final Locale UKRAINIAN = Locale.forLanguageTag("uk-UA");
private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
.appendText(ChronoField.DAY_OF_WEEK, DAY_NAMES)
.appendPattern(" dd LLLL HH:mm uuuu")
.toFormatter(UKRAINIAN);
Now with the formatter in place, parsing is trivial as it should be:
String stringToParse = "понеділок 12 квітень 07:00 2021";
LocalDateTime dateTime = LocalDateTime.parse(stringToParse, FORMATTER);
System.out.println(dateTime);
Output:
2021-04-12T07:00
I find my code much clearer to read than yours, which is what counts for code. There are no funny overrides. There is no insane numbering of the months from 0. Monday is the first day of the week as it is in your question and in Ukraine.
Also java.time performs better validation by default. When your string says that April 12 is a Monday, java.time checks this and would have objected if it had not been the case.
Writing months in dates in Ukrainian (for other readers)
I knew nothing about writing dates in Ukrainian before writing this answer. For curious readers I would like to pass on a couple of observations from my searches.
Two forms of month names seem to be used:
- The nominative, which Java knows as the standalone form, for example січень for January. This form often ends in -ень (-en).
- The genitive, which Java uses as the normal (non-standalone) form, for example січня for January. Possibly “of January” could be used as a translation? This form often ends in -ня (-nya?)
In the Internet I have seen both forms used in dates. I am not very sure, but possibly the trends are: The nominative (standalone) form is used when no day of month is present and sometimes informally when one is; the genitive is used formally when day of month is present.
Links
SimpleDateFormat
andDate
. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead useLocalDateTime
andDateTimeFormatter
, both from java.time, the modern Java date and time API. – EstrenLocale
of Ukrainian (per Google Translate's guess):new Locale.Builder().setLanguage( "uk" ).setRegion( "UA" ).build();
. I get aDateTimeParseException
saying "could not be parsed at index 13" (the month name). I pasted a variation of the month nameКвітень
copied from Google Translate translating "April" to Ukrainian. I verified thatпонеділок
=Monday
= 2021-04-12. If you can see deleted Answers, see mine. Perhaps you can take a stab at it. – HypercorrectionLocale
is in effect when your code runs successfully? – HypercorrectionmyDateFormatSymbols
? – Estren