Parse a date with given locale
genmeblog opened this issue · 5 comments
I want to parse a date for given string "Jan 1 2010". Since my locale is PL, (dt/local-date "MMM d yyyy" "Jan 1 2010") doesn't work. What works is: (dt/local-date "MMM d yyyy" "sty 1 2010")
Is there any way to add locale for formatter?
This code works for me:
(dt/local-date (-> (java.time.format.DateTimeFormatterBuilder.)
(.appendPattern "MMM d yyyy")
(.toFormatter java.util.Locale/ENGLISH)) "Jan 1 2010")
The Java DateTimeFormatter* APIs are pretty extensive and I have no plans of Clojurifying them. I think constructing a formatter via Java interop and passing it through should be an acceptable choice.
I'll close the issue unless you're willing to contribute design ideas/implementation.
Ideas? Sure! Maybe just add another key to formatter, ie :locale with value accepted by java.util.Locale.
And it could be called (formatter "MMM d yyyy" {:locale "en"}. Do you accept PR for that?
That's an OK idea. However, I don't like its ad-hoc-ness. There are various withLocale/withZone/... customization methods on DateTimeFormatter which should be covered by the Clojure-ified version of the API. Otherwise the user will often get frustrated. For example:
; modify locale and zone - have to revert to Java interop. Arrrgh!
(-> (formatter "MMM d yyyy" {:locale "en"}) (.withZone my-tz))My thinking is - the Clojure API should cover a certain set of functionality in a consistent way, e.g. all with methods customizable via a map of {:locale .., :time-zone ...}. Another option is to haveDateTimeFormatter/Builder adopt the same properties mechanism already adopted for the DateTime entities or make the API fully data-driven. What do you think?
I opt for configuration map. I would implement two additional options: locale and time-zone.
Locale can be Locale object itself, String (language) or sequence of strings (language, country, variant). Optionally: as keyword, list of common locales as keywords obtained from (java.util.Locale/getAvailableLocales)
ZoneId is can be built from String.
This makes sense. The DateTimeFormatter JavaDoc mentions the following options:
The withLocale method returns a new formatter that overrides the locale. The locale affects some aspects of formatting and parsing. For example, the ofLocalizedDate provides a formatter that uses the locale specific date format.
The withChronology method returns a new formatter that overrides the chronology. If overridden, the date-time value is converted to the chronology before formatting. During parsing the date-time value is converted to the chronology before it is returned.
The withZone method returns a new formatter that overrides the zone. If overridden, the date-time value is converted to a ZonedDateTime with the requested ZoneId before formatting. During parsing the ZoneId is applied before the value is returned.
The withDecimalStyle method returns a new formatter that overrides the DecimalStyle. The DecimalStyle symbols are used for formatting and parsing.
I'd implement them all with sensible conversion defaults as you described for the :locale option. :decimal-style and :chronology can accept raw java objects.