caslu

caslu

Storing Datetime with timezone in Ecto

Hi everyone :waving_hand:, I know there’s a lot of other questions and discussions about this subject, but most of them were asked a long time ago (more recent ones were in 2019, 2020 or something). Anyway, there’s two problems, a conceptual one and a more technical. But the main question is: How do i store datetimes with timezone information in Ecto nowadays?

I’ll give some context, i have in my app an event schema and i need to store future datetimes, these will be starts_at and ends_at fields, the conceptual problem is: should i really store these dates with timezone information and not in UTC ? For this specific problem i ended up concluding that the correct thing to do is to save the local time with timezone information (something like 2024-05-28 12:00:00.0 Santiago/Chile), but i’m accepting advices and opinions if this is incorrect or there’s a better way. Once i concluded that i’ll save the datetime with timezone information, there’s the other question, how can i do this in Ecto? The ways i’ve searched pointed me to libraries like Timex Ecto and Timex or Calendar and Calecto but all this libraries depends of old Ecto versions and i don’t want to downgrade my Ecto version, just do not looks like the correct approach to downgrade some core lib like that. Therefore i’m quite lost to how to do it at the better way for my scenario, should i implement my own custom Ecto schema type ? What type should i use in Ecto Migration since Ecto provides only :utc_datetime which always will convert to UTC and naive_datetime which does not store tz information, what should i do now?

Marked As Solved Switch mode

LostKobrakai

LostKobrakai

For more concrete advice you can also look at Storing UTC is not a silver bullet | Jon Skeet's coding blog

Though generally I‘d always suggest understanding the problem before looking too deep into possible solutions.

Also Liked

LostKobrakai

LostKobrakai

If you only ever show it to the user and the user cannot change their timezone then this would be fine.

However there‘s commonly the need to also show events of multiple users and different timezones in a sorted order as well. Once you add that to the requirements you suddenly not only need the local wall time, but also a mapping to a shared timeline/timezone (usually UTC). I‘ve a library for storing both in tandem on ecto.

But also consider:

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

To be clear, Postgres itself is completely incapable of storing timezone information in the same column as the date time in question. You have to just use two columns, one that stores the date time in UTC, and another that stores the timezone as a string.

The distinction between the utc and naive types just has to do with whether you are declaring that the value in the database is UTC or not.

dimitarvp

dimitarvp

There are nice explanation and examples here – https://stackoverflow.com/questions/5876218/difference-between-timestamps-with-without-time-zone-in-postgresql

…but long story short, I would not bother at all. In the end Postgres does the shifting between timezones and do you really want one more moving piece? I don’t. You’ll then have to take this into account when loading those from the DB in your app code and that’s prone to ambiguous rules (f.ex. I lost count on how many times I had to convert DateTime to NaiveDateTime in my Elixir work to avoid confusion). For years now, I store all timestamps without timezone and in UTC from all Elixir / Golang / Rust code that I write, and I leave showing the time in local timezones to clients (websites and mobile apps).

And I’ve made friends with frontend devs and sysadmins by never doing any shenanigans with timezones as well. :smiley:


Finally, storing future datetimes can sadly be error-prone; we don’t know when will a timezone change offset or eliminate / add summer time shifting. I forgot where that discussion was here on ElixirForum but I believe @LostKobrakai was in there and I think Ben as well.

Where Next?

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
silverdr
Using Phoenix.LiveView.TagEngine as an EEx.Engine is deprecated! To compile HEEx, use Phoenix.LiveView.TagEngine.compile/2 instead. Sta...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
michallepicki
I am using Oban and occasionally, shortly after a deployment, a handful of jobs can fail because of dependency on other parts of the syst...
New

Other Trending Topics Top

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
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement