kip

kip

ex_cldr Core Team

Somehow I missed introducing Calendrical, which implements a significant number of the calendars used around the world. Its the spiritual successor to ex_cldr_calendars and friends, but it also several additional calendars like:

New Date, Time, DateTime and Interval string parsers

New in Calendarical version 0.6.0 published today is flexible date/time parsing.

If you’ve got user-typed date/time strings coming in from a form, an import, or a chat command, this should save you some pain.

There’s a single entry point — Calendrical.parse/2 — that figures out what kind of value you typed and dispatches to the right sub-parser:

iex> Calendrical.parse("2026-05-16", locale: :en)
{:ok, ~D[2026-05-16]}
iex> Calendrical.parse "23 May"
{:ok, ~D[2026-05-23]}
iex> Calendrical.parse("14:30", locale: :en)
{:ok, ~T[14:30:00]}
iex> Calendrical.parse("May 16, 2026, 2:30 PM", locale: :en)
{:ok, ~N[2026-05-16 14:30:00]}
iex> Calendrical.parse("May 5, 2026 – May 10, 2026", locale: :en)
{:ok, Date.range(~D[2026-05-05], ~D[2026-05-10])}

Parsing is locale aware

Every parser reads CLDR data, so the same string may parse differently depending on the locale you pass:

iex> Calendrical.Date.parse("3/4/26", locale: :en)
{:ok, ~D[2026-03-04]}
iex> Calendrical.Date.parse("3/4/26", locale: :"en-GB")
{:ok, ~D[2026-04-03]}
iex> Calendrical.Date.parse("16.05.2026", locale: :de)
{:ok, ~D[2026-05-16]}
iex> Calendrical.parse "23 mai", locale: :fr
{:ok, ~D[2026-05-23]}
iex> Calendrical.Time.parse("2:30 PM", locale: :en)
{:ok, ~T[14:30:00]}
iex> Calendrical.Time.parse("14:30", locale: :de)
{:ok, ~T[14:30:00]}

Parsing supports any known calendar

Pass :calendar to interpret input pretty much all of the worlds major calendars — Gregorian, Buddhist, Japanese imperial, Islamic, Hebrew, Persian, ROC, Coptic, Ethiopic, Indian, and more. The returned Date is in that calendar:

iex> Calendrical.Date.parse("2026-05-16", calendar: Calendrical.Hebrew)
{:ok, ~D[5786-09-29 Calendrical.Hebrew]}
iex> Calendrical.Date.parse("民國115年5月16日", locale: :"zh-Hant-TW", calendar: Calendrical.Roc)
{:ok, ~D[0115-05-16 Calendrical.Roc]}
iex> Calendrical.Date.parse("令和6年7月1日", locale: :"ja-JP", calendar: Calendrical.Japanese)
{:ok, ~D[2024-07-01 Calendrical.Japanese]}
iex> Calendrical.Date.parse("١٧ رمضان ١٤٣٥ هـ", locale: :"ar-SA", calendar: Calendrical.Islamic.Civil)
{:ok, ~D[1435-09-17 Calendrical.Islamic.Civil]}
iex> Calendrical.Date.parse("1 ก.ค. 2567", locale: :"th-TH", calendar: Calendrical.Buddhist)
{:ok, ~D[2567-07-01 Calendrical.Buddhist]}

Parsing date ranges

Date ranges follow the same calendar rule — Date.Range works in any calendar, not just Calendar.ISO:

iex> Calendrical.Date.parse_range({"2026-05-05", "2026-05-10"}, calendar: Calendrical.Buddhist])
{:ok, Date.range(~D[2569-05-05 Calendrical.Buddhist], ~D[2569-05-10 Calendrical.Buddhist])}
iex> Calendrical.Date.parse_range("May 5 – May 10, 2026", locale: :en)
{:ok, Date.range(~D[2026-05-05], ~D[2026-05-10])}

That last example also shows CLDR interval-skeleton inheritance — the left endpoint has no year, so it inherits 2026 from the right.

Going directly to the individual parsers

If you already know the shape of your input, skip Calendrical.parse/2 and call the relevant parser directly:

  • Calendrical.Date.parse/2
  • Calendrical.Time.parse/2
  • Calendrical.DateTime.parse/2
  • Calendrical.Date.parse_range/2

Each accepts :locale, :calendar (where applicable), and a few specialised options like :allow_inverted for ranges and :reference_date for two-digit-year pivoting.

Links

Showing Posts 1 to 6

netoum

netoum

Thank you for providing all the Localize libraries. Amazing job, they work great and make the dev life much easier.
Just noticed the GitHub link in the post is not working however the GitHub link in the hex package is working.

kip

kip OP

ex_cldr Core Team

Looks like @AstonJ (thanks!) already beat me to it - the link is correct now.

dbern

dbern

Wonderful! Maybe I can deprecate date_time_parser! It doesn’t support locales very well and I’m glad Calendrical does.

kip

kip OP

ex_cldr Core Team

TL;DR: your lib remains incredibly useful, Calendrical covers a distinct set of requirements - but definitely not all of them.

There are a number of use cases that date_time_parser supports that Calendrical does not and I consider out of scope.

Date/Time Parser Support Why Calendrical doesn’t
Unix epoch / Excel serial numerics (-9999999999, 30134, 62.0, etc.) Out of scope — no locale, calendar, or format pattern involved
Quote/equals CSV wrappers (""=""9/5/2018""") Out of scope — CSV preprocessing, not parsing
Unix date(1) output, year at end (Fri Mar 2 09:01:57 2018) Non-CLDR pattern; would need synthesised fallback
JS Date.toString() (Fri Mar 31 2017 21:41:40 GMT+0000 (UTC)) Non-CLDR pattern; JS-specific
mm:ss.frac time (07:09.3) Non-CLDR; DTP-specific convention
ISO date-only with offset (2017-09-29+00:00) Non-standard ISO 8601 shape
dbern

dbern

Fair enough! And yes it’s all those non-standard formats that I remember being problematic in CSV imports that had a variety of these formats that I made date_time_parser for.

in any case, wonderful job with Calendrical!

kip

kip OP

ex_cldr Core Team

I’ve published Calendrical version 0.11.0 the is primarily about robustness, conformance and code quality. It’s based upon Localize version 0.45.0 also released today and which is also focus on robustness, conformance and code quality.

The changelog contains notes on all of the changes.

I expect Calendrical to be a stable release now and the next release will be a 1.0 candidate release, following Localize around the end of July.

— All posts loaded —

Where Next? Top

Trending in Announcing Top

woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews