kip

kip

ex_cldr Core Team

Calendrical - over 17 localised calendar implementations and date/time parsing

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

Most Liked

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

ex_cldr Core Team

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

Last Post!

kip

kip

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.

Where Next?

Popular in Announcing Top

tmbb
PhoenixWS - Websockets over Phoenix Channels Source code on Github here: GitHub - tmbb/phoenix_ws: Websockets implemented over Phoenix Ch...
New
mathieuprog
Hello :waving_hand: Allow me to introduce you to Tz, an alternative time zone database support to Tzdata. Why another library? First a...
New
tmbb
I’ve published the first version of my Makeup library. It’s a syntax highlighter for Elixir in the spirit of Pygments, Currently it highl...
New
bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
384 14206 119
New
Eiji
ExApi is a library that I’m developing now and hope release soon This library will allow to: list all apis list all api implementation...
New
sbs
Only 650 LOC, wrote for fun :slight_smile: https://github.com/sunboshan/qrcode
New
Azolo
Hey everyone, I just released WebSockex which is a Elixir WebSocket client. WebSockex strives to work as a OTP special process, be RFC6...
New
mplatts
With HEEX released we decided to start a components library using Tailwind CSS - check it out here: Petal Components. We also have a boi...
New
tfwright
After working on it for a couple of months and using it in production for most of that time, today I’ve released LiveAdmin, a LiveView ba...
New
trisolaran
Hi! :waving_hand: I would like to present LiveSelect, a little library that I wrote to easily add a dynamic selection input to your LV f...
198 10978 107
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42158 114
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39523 209
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31307 143
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New

We're in Beta

About us Mission Statement