jung-hunsoo

jung-hunsoo

DateTime.add/3 is missing

In Elixir, function DateTime.add/3 is missing.

There are Date.add/2, NaiveDateTime.add/3, and Time.add/3. But only DateTime has no add/3 function. Is there any reason? Maybe because of time zone related problem?

As as walkaround, I’ve convert it to Unix time |> shift time, then compare with another.

I think DateTime.add/3 can be achieved by using both DateTime.from_unix/3 and DateTime.to_unix/2. Is there any enhancement for this function?

Marked As Solved

LostKobrakai

LostKobrakai

It’s not about popular or sophisticated, but rather about correctness vs. full of edge-case issues. Elixir does only supply the functionality, where it can ensure correctness. That’s why NaiveDateTime does have more functionality than DateTime. Also NaiveDateTime clearly communicates that it’s a simple form of handling dates, which might be enough for some usecases. But doing DateTimes correctly is not simple as @Qqwy explained above.

As for your question about other languages. Afaik erlang does not supply any datetime calculations at all. JS (Date obj) doesn’t have any add/sub methods as well. Just a lot of setters/getters. For languages, which allow transformation of dates you might want to check how well they work before trying to compare it to elixir not giving you a way to do it correctly as well as incorrectly (for DateTime; NaiveDateTime would be the explicitly incorrect way).

Also Liked

Qqwy

Qqwy

TypeCheck Core Team

@LostKobrakai is completely right.

What do you require the timestamps for?
There are two reasons why the calendar- and timezone-related stuff is not part of the Elixir standard library:

  1. it greatly increases the size of the stdlib, which is a problem in embedded contexts.
  2. Time zone information frequently changes, regardless of stdlib-versions or what the latest compilation-moment has been. Extra libraries like tzdata periodically fetch timezone information from a repository at runtime to ensure that even if a server runs for a long time, its timezone-information remains correct.

It is a common misconception that Unix/POSIX-time is compatible with UTC time, but this is not completely true: POSIX time predates our UTC standard, and counts seconds since 1970-01-01T00:00 , but it will (for backwards compatibility) still pretend that:

  • every day only contains 86400 seconds
  • every year only contains 31536000 seconds (normal year) or 31622400 (leap year).

Many old libraries check if it is one second past midnight by doing time % 86400 == 1. Obviously this horrendously breaks if we would have leap seconds in there. (The alternative, which would be to create and use better algorithms, is impossible with software that is already in use for many years)

So… that is where we stand. Only during leap seconds, POSIX deviates from UTC. The real standard says that once the leap second is over, the POSIX clock should be decremented by one second, although there are other implementations that instead slow down the time ticks on the ‘leap second day’ to ensure time keeps flowing monotonically.

Maybe this is too much of a tangent, but the tl;dr is: DateTime.add does not exist because it is not possible to define it without a lot more information.

LostKobrakai

LostKobrakai

That’s the misconception here. That does not work at all because unix timestamps don’t deal with timezones (e.g. switch from/to daylight-savings-time), it does also not include leapseconds, which DateTime does need to deal with. That’s where elixir currently depends on third party libraries like timex or calendar. Even the database with timezone information (tzdata library) is by now third party.

You might want to read up on some of the articles like this one if you want to know more about the uncomfortable details in handling dates: Falsehoods programmers believe about time: @noahsussman: Infinite Undo

LostKobrakai

LostKobrakai

Changing to fixed values is still vastly different to adding/substracting time from dates. One does only need to validate a datetime on it’s own, while the other does need to make sure the time difference is calculated correctly to the resulting datetime. The latter is certainly more prone to issues like leap-seconds and such things.

But even for just changing parts of a datetime there’re things to consider: e.g. on switch between dst/non-dst you loose one hour once a year. Most often time is moved from 2:00 to 3:00 directly so setting a time 2:15 for that date will result in an invalid datetime. And with the needed knowledge of timezones we’re back to the problems discussed before.

To cite mdn for the javascript Date object here:

Creates a JavaScript Date instance that represents a single moment in time. Date objects are based on a time value that is the number of milliseconds since 1 January 1970 UTC.

So a date object is basically just a big integer value in UTC and therefore prone to all the issues mentioned above. It seems the only support in regards to timezones it has is using the host systems data to convert the UTC time into the timezone of the host. This is no better then using NaiveDateTime in elixir.

Edit:
And to clear out the notion that utc offsets might be all you need: How to save datetimes for future events - (when UTC is not the right answer)

Where Next?

Popular in Questions Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Kagamiiiii
Student & New to elixir. Nice language. I want to convert a english character, e.g. “a”, which is stored in a variable, to it’s asci...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

Other popular topics Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New

We're in Beta

About us Mission Statement