mudasobwa
This question is more about semantics. Adding a :day to the DateTime instance changes the time value, which might be slightly confusing.
iex(1)> DateTime.new!(~D[2024-04-06], ~T[23:59:00], "Australia/Sydney")
...(1)> |> IO.inspect()
...(1)> |> DateTime.add(1, :day)
#DateTime<2024-04-06 23:59:00+11:00 AEDT Australia/Sydney>
#DateTime<2024-04-07 22:59:00+10:00 AEST Australia/Sydney>
Yes, adding the exact number of seconds (86_400) multiplied by the number of days results in this, but DateTime(dt, 5, :day) usually means the developer wants to get the very same hh:mm:ss time back.
Consider a ToDoApp (huh) example. If I am after producing a Stream of recurring events, I am surely to expect it won’t change the Time part alongside with a DST change.
I discovered this when people complained about Tempus.Slots.Stream.recurrent/3 is broken in an aforementioned way. I fixed it by reassuring Time part to stay intact in the produced stream elements, but it looks like a hack and I am positive, DateTime.add(…, …, :day) should not corrupt the Time anyway.
Thought?
Trending in Discussions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixir-ls
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
LostKobrakai
This is called out in the docs as the intended behaviour.
If you want a continuous stream of datetimes at the same hour you can use a date and
Date.addand turn those dates into datetimes with a time. Though you might run into invalid/duplicate datetimes this way if a date+time combination is in a DST change switch.zachallaun
The docs for the new
DateTime.shift/3landing in 1.17 addresses this specifically and offers a suggestion usingNaiveDateTime. It looks like this works:Edit to note that the above isn’t using anything in 1.17 and was copied from a 1.16 REPL.
mudasobwa
Thanks @LostKobrakai, @zachallaun,
I know how to overcome it. Also, I know this behaviour is intended. I started this topic with “This question is more about semantics,” and that’s what all this is about.
I find it extremely confusing that adding an integer number of days to the instance of
DateTimeresults in the change ofhourfield in the struct. If that’s only me, I am good. But I am positive if you stop a hundred persons on the street to ask “now it’s Saturday, 3PM. This night there will be a DST shift. What would be the result of adding exactly one day to now?”—99 if not 100 of them would answer 3PM.Please note, that the above does not apply to adding hours, let alone seconds.
LostKobrakai
The laymans opinion doesn’t really help in a domain full of real life footguns a layman is usually not aware of. As mentioned you cannot add a day to a datetime while keeping the hour value the same without it being able to produce invalid datetimes.
DateTime.addcannot fail though or adding:day(together with hour and minute) as a unit would’ve been a BC breaking change. Personally I probably would’ve even skipped:dayfor exactly this discussion.If you still want to attempt this you simply need to do it using APIs of DateTime, which can return you errors around those invalid datetimes and decide for a way to handle those for your specific usecase.
E.g. the following naive datetime is invalid, as it is never observed, even though the day before and after do have an observed datetime at 02:30:00. So there needs to be a decision made if the invalid one is skipped, shifted to the last observed datetime before or the next after. Similar thing happens when shifting the other direction where a naive datetime would be observed twice, once with DST offset and once without.
mudasobwa
That I’d strongly appreciate, but once we already have it, we might be more adaptive to laymans’ opinion
Look, we already round days down to the nearest valid date when shifting by month in
1.17. The API is already not generic. We are already treating “add 1 month” in layman’s terms. What would be wrong with treating “add 1 day” in the very same manner? Once it’s documented it’s ok, that’s what you were saying in the first comment, right?Fwiw, I’d share why it made me upset. While working on
Tempus, which is a library to represent time slots, I dug a lot, and the most inspiring wastempolibrary by @kip, which is great, but my goal was slightly different. I was more after infinite streams of intervals, and their interop, like joins, intersections, etc. I needed a way to tell if this infinite slot stream covers that particular time. That’s why the algebra I’ve chosen is slightly different (although similar.) Still, I wanted the clients to face as few quirks of the interval mess as possible.And the aforementioned “add several days” was literally the only thing I was not ready to (and I was ready to enter a hell, trust me.) Anyway.
al2o3cr
YMMV: 40 out of 100 of them would also tell you that DST helps solar panels make more power, because there’s “more sun”.
To @LostKobrakai’s example, only a developer would tell you “there’s no such time as
one day after 2:30AM Saturday morningif the Sunday is the DST switchover”mudasobwa
With all due respect, that’s not what
DateTimetells us. It happily adds one day, and that’s what bugs me, because I believe it does it wrong.LostKobrakai
DateTime.shiftcould make that decision, sure. ButDateTime.addadds a certain (and fixed per amount/unit) amount of seconds to the supplied DateTime. That’s a different task. The issue is that it allows for:daywith a constant of 86400 seconds when days are not always that long. That’s also the reason why:week,:month,:yearweren’t added toDateTime.add, but handled into the newDateTime.shift.mudasobwa
Sure. On the other hand, even
add(…, …, :second)might suffer the same disease when next to the leap second, so it’s all cumbersome.LostKobrakai
Not modeling leapseconds doesn‘t leave you in a state where you miss a (naive) datetime or run into it twice though - which is what happens if you don‘t handle the dst change complexities.