C
C#16mo ago
Kiel

❔ Accounting for Daylight Savings Time skips at runtime

My Discord bot I am developing has a reminder system which utilizes https://github.com/robbell/nChronic.Core for natural date/time parsing - allowing a user to specify a reminder for tomorrow at noon. As not everyone lives in the same timezone, users can configure their timezone via a command, where the user inputs their approximate TZDB equivalent (see image). The bot also supports repeating reminders, IE a reminder where a user can be reminded hourly, daily, or weekly at the same interval of time - IE, a reminder to do something at 10PM daily. As I just learned this past weekend with the time changing, this system has a flaw, where anyone whose region observes DST will have reminders become off by an hour once it begins or ends. My current system involves storing the user's offset from UTC as a TimeSpan for parsing purposes, and then storing reminders as DateTimeOffset relative to UTC regardless of their timezone (because Npgsql's EFCore thing seems to only support UTC offset?). Is there any way to account for this behavior? Especially since it's not something observed worldwide, and even in America, it's apparently on the way out and some regions don't even follow it
10 Replies
Kiel
Kiel16mo ago
I noticed because I have a daily reminder for 10PM, which went off at 11PM today, and I realized it was because of the time change.
jcotton42
jcotton4216mo ago
for your own sanity, I suggest switching to NodaTime, which has support for actual time zones https://nodatime.org/3.1.x/userguide/type-choices npgsql has support for it https://www.npgsql.org/efcore/mapping/nodatime.html
Kiel
Kiel16mo ago
I'm actually using NodaTime for the timezone parsing, that's where I'm getting the TZDB info from Unless I'm wrong, this still doesn't seem to account for DST switchovers, unless you're telling me nodatime is somehow aware of these at runtime and can account for it (if it matters, the way I "expire" things like reminders is by sorting them by which one's expiry date is lowest)
jcotton42
jcotton4216mo ago
oh wait hm you might be right
Kiel
Kiel16mo ago
I'm really not familiar with NodaTime, I actually tried using it instead of the BCL stuff for this exact stuff originally since I was actually storing their timezone as a TZDB string (IE America/Chicago instead of a TimeSpan, but I was either a) getting tripped up on some of the conversion methods to/from BCL types, or b) came across an issue I couldn't solve using NodaTime. This was...a month or so ago so I honestly don't remember
jcotton42
jcotton4216mo ago
you've now nerdsniped me kek think it would work if you stored a LocalTime (which is a time of day with no timezone) plus a time zone ID in a separate column...
Kiel
Kiel16mo ago
i'll have to probably do some testing before I mess around with my db entities...not even sure how to test it. maybe just have a LocalDateTime of just before the changeover, convert it to a ZonedDateTime, then repeat the process after the changeover, and see if the difference is correct?
Kiel
Kiel16mo ago
You might be onto something. Here's my findings:
var currentTimeZone = DateTimeZoneProviders.Bcl.GetSystemDefault();

// DST changeover: Sun, Mar 12, 2023 2:00 AM
var beforeChangeOver = new LocalDateTime(2023, 3, 12, 01, 55);
var beforeZdt = beforeChangeOver.InZoneLeniently(currentTimeZone);
var afterChangeOver = new LocalDateTime(2023, 3, 12, 02, 05);
var afterZdt = afterChangeOver.InZoneLeniently(currentTimeZone);

return Response($"Before: {beforeZdt}\nAfter: {afterZdt}");
var currentTimeZone = DateTimeZoneProviders.Bcl.GetSystemDefault();

// DST changeover: Sun, Mar 12, 2023 2:00 AM
var beforeChangeOver = new LocalDateTime(2023, 3, 12, 01, 55);
var beforeZdt = beforeChangeOver.InZoneLeniently(currentTimeZone);
var afterChangeOver = new LocalDateTime(2023, 3, 12, 02, 05);
var afterZdt = afterChangeOver.InZoneLeniently(currentTimeZone);

return Response($"Before: {beforeZdt}\nAfter: {afterZdt}");
Kiel
Kiel16mo ago
it jumps from 1:55 to 3:05 AM, indicating it was "aware" of the changeover at 2AM @jcotton42 sorry, meant to ping reply, but discord broke the message sending thonk2 it would probably make the most sense to store the user's TimeZoneInfo in the db and then store reminder expiry as a LocalDateTime (UTC), then convert to a ZonedDateTime on the fly assuming the npgsql thingy supports those two, i'll look into it tomorrow
Accord
Accord16mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts
✅ I need to put an invalid choice in my programI need to make the program repeat if they did not input a valid response of yes or no❔ My project runs successfully but doesn't load ( works fine when I run it without debugging )my project was working fine but suddenly whenever I run it it keeps loading without showing anythingOnly assignment, call, increment, decrement, await, and new object expressions can be used as a statim a noob and why cant i make my console make a beep sound? I didnt understand the error msg❔ multiple Async responsesSo im trying to use async for the first time, i am making a few api requests one after the other, thInvoke Event on boolean set in systemclassI have my own TcpClient class that inherits TcpClient and I wanna invoke an event when one of the bo❔ How to properly handle exceptions between API controller and service layer?I'm creating an API and I'm having trouble figuring out how to properly catch errors between my serv❔ Question regarding Pipe[Reader/Writer].Complete(Exception) (System.IO.Pipelines)If you put in an exception, where does it come back out exactly? Where does the exception get handle❔ How would I call a method created as a top level statement outside of the initial file?I have Program.cs with a method that is a static int, ```static int Example()``` and have tried to c❔ Visual Studio Build doesn't run on other computerSo I made a Visual Studio program for a client that has a bunch of dll when built, however, when i s❔ ASP.net Web shop , cart . customersI am developing shop ASP.net CORE but i am not sure how to make the buttons and "cart " , and cu