I'm coding a scheduling app and I'm curious how to handle the following marginal situation concerning the Daylight Saving Time (DST) change:
Say, we're in the time zone where the DST:
Starts on 2014-Mar-9 at 2:00:00 AM (clock is adjusted forward)
Ends on 2014-Nov-2 at 2:00:00 AM (clock is adjusted backward)
Suppose, an end-user scheduled my app for 2014-Nov-2, 2:00:00 AM.
Let's assume that the local date/time now is 2014-Nov-2, 1:59:99 AM.
When should my app fire the schedule -- in 1 second, or in 1 hour and 1 second?
Is there a standard that defines how to deal with this situation?
According to wikipedia the rules for daylight saving time are:
...in spring the clock jumps forward from the last moment of 01:59
standard time to 03:00 DST and that day has 23 hours, whereas in
autumn the clock jumps backward from the last moment of 01:59 DST to
01:00 standard time, repeating that hour, and that day has 25
hours.[37] A digital display of local time does not read 02:00 exactly
at the shift to summertime, but instead jumps from 01:59:59.9 forward
to 03:00:00.0.
So while the time and date is different around the world the rules are similar(ignoring Australia's Lord Howe Island which uses a half-hour shift). The hour that jumps backwards or forwards is not touched but the hour that is jumped to.
So in my opinion you should trigger the schedule in one hour and one second.
If you would trigger it in one second and the user wants to stop the schedule at 3 o'clock it would run for two hours instead of one which appears to be incorrect (2-3 = 1 hour).
I agree about all of the comments that "what you should do" is highly dependent on what your users expect, but I will give my opinion anyway.
If you are scheduling a single event, you should be able to test the date and time the user provided to see if it's either invalid (in the spring DST transition), or ambiguous (in the fall DST transition). In the invalid case, prompt something like "sorry, that time is invalid". In the ambiguous case, prompt something like "did you mean 1:30 PDT (UTC-7) or 1:30 PST (UTC-8)?" and handle the selection accordingly.
But I'll approach your question from the use case of a recurring event, such as a daily alarm clock that fires every day at the same time. What would I expect as the user of an alarm clock?
If I schedule a daily time at 2:00 AM, but in the spring transition the clock goes from 1:59:59 to 3:00:00, I'd expect the alarm to go off right at 3:00:00. I certainly wouldn't want it to go off at 4:00:00 - that would be an extra hour. I also wouldn't want the alarm to not fire at all just because 2:00 didn't technically occur.
If I schedule a daily time at 1:00 AM, but in the fall transition the clock goes from 1:59:59 back to 1:00:00 - as a user of this alarm, I would expect it to go off on the first occurrence (the daylight time) only. Occurring twice would just be annoying.
But here we see how this illustrates needing to know your users expectations. What if I could tell my alarm clock to let me have that extra hour back? "Please Mr. Alarm Clock, I'd like to use my extra DST hour to sleep in late. Wake me up at the second occurrence of 1:00." - Now I haven't personally seen any alarm clocks that work this way, but I think you get my point.
Now maybe you're not working with alarm clocks. Maybe this is a timed wire-transfer or some other time-sensitive item. You should work through the expected logic and see what makes sense for you.
Be aware that DST rules vary drastically by time zone. The world does not do DST all at the same time. Much of it doesn't do it at all.
For additional clarity on DST behavior, see the charts in the DST tag wiki.
Related
We are now in the summer time (UTC+01:00) but I need always winter time whereever I am.
For example now time is 08:05 and winter time is 07:05
I can find whether it is saving time or not by using this function
DateTime.Now.IsDaylightSavingTime()
and here is the delta (1 hour change)
TimeZoneInfo.Local.GetAdjustmentRules()[0].DaylightDelta;
so if I do something like that, is it correct?
var winterTime= DateTime.Now;
if (DateTime.Now.IsDaylightSavingTime())
{
winterTime = DateTime.Now.AddHours(-1 * delta.Hours);
}
or is there another way to do? (without using any 3rd solution)
Edit: The reason why I am asking this is that we are flashing a firmware to a nfc device and some dates in the devices should be in winter time. Thats why our tool should write winter time as paramter to the device.
In case DaylightDelta is not whole hours better use the TimeSpan directly. Also you need to find the rule in GetAdjustmentRules() that matches the current date. GetAdjustmentRules() returns both future and historical rules.
var now = DateTime.Today;
var rule = TimeZoneInfo.Local.GetAdjustmentRules().Where(x => now >= x.DateStart && now <= x.DateEnd).First();
winterTime = DateTime.Now - rule.DaylightDelta;
We are now in the summer time (UTC+01:00) but I need always winter time whereever I am.
...
... The reason why I am asking this is that we are flashing a firmware to a nfc device and some dates in the devices should be in winter time. Thats why our tool should write winter time as paramter to the device.
It sounds like you simply want to obtain the UTC time to set on the device. If so, just use DateTime.UtcNow. There is no need to concern yourself with time zones.
However, if you actually wanted to take the standard time (or winter time) for whatever local time zone you're in (that would seem to be a bit silly because that's not how local times work), but if you really are sure you want that, you can do it without querying adjustment rules. Instead, try this:
DateTime dt = DateTimeOffset.UtcNow.ToOffset(TimeZoneInfo.Local.BaseUtcOffset).DateTime;
This takes the current UTC time, applies the base offset of the local time zone, and then gives you back a DateTime with .Kind == DateTimeKind.Unspecified. The base offset is the offset from UTC that applies during standard time without any adjustment rules applied for DST.
I have some timers that read HH:MM:SS from a table to figure out when to run on a daily basis.
For example:
Timer A needs to run every Monday at 13:00:00
Timer B needs to run every Tuesday at 02:00:00
Timer C needs to run every hour
So in my code I figure out what the current time is and then calculate the milliseconds from DateTime.Now() to the next occurrence of when the timer should run. When the timer's Elapsed event has completed, it recalculates when it is supposed to run next. This created a problem over this weekend due to the time change.
Is there a better way to do this? Would DateTime.UtcNow be a better alternative? Maybe convert the time string in the database to a UTC time and then figure out the difference between DateTime.UtcNow() instead of DateTime.Now()?
You can do several things to solve this problem.
One is to use UTC for all your scheduled jobs. That gives you a robust and predictable system without a lot of complications or testing burden. But the jobs that run at 03:00 on Mondays in the summer will run at 02:00 in the winter. If that's OK, the UTC strategy is a good one.
(Testing timezone switchover use cases is a pain, and if you use UTC for everything your test burden is reduced.)
Another is to get serious with your date arithmetic, and be very careful. C#'s DateTime class does a good job of date arithmetic even on changeover dates.
So, let's say you need to run a process once a week on Sunday at 01:30. That's in the nightmare hour in the USA ... it doesn't happen in the spring changeover, and it happens twice in the fall changeover. But you still want the process to run once.
What you do is this: Keep a "next scheduled time" value. Each time you finish running the job, compute the "next scheduled time" value for the next run. This might work like this:
var today = DateTime.Today.AddDays(7); /* midnight a week from now */
TimeSpan runTime = TimeSpan.Parse("01:30");
var nextRun = today + runTime;
Then, save that nextRun DateTime value. Later on you can figure out how long it is until the next run. This is a good way to do that. There are others.
var msUntilNextRun = (nextRun.Ticks - DateTime.Now.Ticks) / 10000;
If the msUntilNextRun value comes up reasonably small and positive, you can sleep until it's time for the run. If it comes up small and negative, you overslept--run immediately (oversleeping is very common).
Adding the days to the present midnight value, then adding the time to that, then figuring how long to wait, is a way to get a reasonable runtime even on changeover days.
First of all, sorry about my ignorance and my awful english skills, i work to improve them.So here goes my question:
I want use DateTime.Ticks (instead Guid.NewGuid) in order to calculate an identifier and a question is being raised to me. In my current culture we have 2 days on the year when we change the official time: in octuber we add an hour and in april we remove it.
how does it affect to the ticks value? how ticks value is calulated? As far as i understand based on https://msdn.microsoft.com/en-us/library/system.datetime.ticks%28v=vs.110%29.aspx it seems it is not able to be a repeat value because based on the text (...)It does not include the number of ticks that are attributable to leap seconds(...) .
there could be repeated ticks?, (maybe other question would be how long a tick lasts, depends on the computer? )
If i'm not wrong it cant be repeated.
Moreover, Maybe there could be a lot of stuff i misunderstand so i'm really sorry again...
Even without DST changes, you can observe DateTime.Now.Ticks returning the same value multiple times, due to the granularity of the system clock.
But with DST changing, if you use DateTime.Now, you will indeed see the same values repeating for one hour per year. The Ticks property is just "the number of ticks since the DateTime epoch, in whatever kind of value is represented". (A DateTime value can be one of three "kinds" - universal, local, or unspecified. It's all a bit of a mess.)
If you use DateTime.UtcNow you shouldn't see that if your system clock only moves forward... but it's entirely possible for system clocks to be changed, either manually or in an automated way, to correct them for drift. Basically, it's not a good source of uniqueness on its own.
(In terms of the length of a tick - the tick in DateTime is always 100ns. That's not true for Stopwatch, where you need to use the Frequency property to find out how long a tick is, or use the Elapsed property to just find the elapsed time as a TimeSpan.)
I am working on an application that needs to set rules for periods of time. The company has different branches, each branch can set its own rules (i.e a branch starts work at 8.30 am, ends work at 17.30 pm, with 30 minutes pause for lunch; another branch start at 9.00, ends at 19.00 with 1 hour pause...)
So I need to define a class (let's call it WorkingDayDefinition for the moment) where start and end are not actually a DateTime, because they are not referred to any specific day in particular.
At the moment the only option I see in C# is using Timespan for setting a duration from the beginning of the day, so that 8.30 pm would be TimeSpan(8,30,0) to be added to the Day part of whichever day.
Is this a best practice in C#?
I searched for third parties libraries that could help me, but so far my best bet is this one:
http://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET
that is not strictly what I need
You could use Noda Time. It provides a LocalTime (see here):
LocalTime is an immutable struct representing a time of day, with no reference to a particular calendar, time zone or date.
For 8.30 you would do something like:
LocalTime openingAt = new LocalTime(8, 30);
To me TimeSpam seems very suitable for what you want. It holds an interval of time, sometimes between two events, but in your case between the start of the day and the time you start/finish work. There is no reason I can think of not to use it just because the name might suggest this wasn't the original intention of the class. Plus it already integrates well with DateTimes for any time calculations you need to do later on down the road.
I understand that to refer a single point in time DateTimeOffset is better and more reliable way compared to DateTime as it replaces .Kind property by a more convenient thing that is the Offset to UTC.
Does this solve all the issues regarding to storing a single point in Date-Time or are there still some cases that I should be concerned about?
(If there are can you give me examples where DateTimeOffset can't be reliable?)
Thanks
Given a DateTimeOffset, there is never any confusion about what point in time that represents. So they are always reliable.
But there are some cases where a DateTimeOffset alone is still not sufficient. Here's an example of a common situation:
You are in New York, USA on March 10th 2013.
You find out about an event happening at 1:00 AM local time.
You record it as a DateTimeOffset with the value 2013-03-10T01:00:00-05:00.
Later, you find out that you were given incorrect information, the event actually occurred at 3:00 AM.
So you go to edit, and you change the value to 2013-03-10T03:00:00-05:00.
But this would be incorrect. On that particular day, daylight saving time starts, and so 3:00 AM is only one hour later than 1:00 AM. If you just advance the time, without considering that the offset may have changed, then you am referencing the wrong point in time.
It should have been 2013-03-10T03:00:00-04:00.
To overcome this situation, you must also know that the time was recorded in New York. You knew that in the first step, but then it was thrown out when you recorded it. Somewhere else in your application, you must hold on to this fact. Preferably, you would keep a time zone id, so that you could re-calculate the correct offset.
If using the TimeZoneInfo class in your application, then you would want to track the value of the .Id property, along with your DateTimeOffset. For New York, the time zone id would be "Eastern Standard Time". This is a bit confusing, because this same value is used regardless of whether DST is in effect or not. (There is no Windows time zone with an Id of "Eastern Daylight Time"). Also, there is no built-in class or struct that will pair a TimeZoneInfo with a DateTimeOffset. You have to do it yourself.
If you are using Noda Time (which I highly recommend). Then you can take advantage of the IANA time zone id of "America/New_York", and the ZonedDateTime object - which is designed for this exact situation.
You should also refer to DateTime vs DateTimeOffset. You should find the analogy there quite useful.
There are also some cases where DateTimeOffset is not appropriate. Maybe this one is obvious, but it's still worth mentioning.
When you are not refering to a single moment in time, but a relative point on the calendar.
This happens more often than you would think. For example:
In the United States, this year daylight saving time began on March 10th 2013 at 2:00 AM.
But it didn't happen at at the exact same moment. Each time zone has their own local 2:00 AM, so there are actually several different transition points on the instantaneous timeline.
(Aside, but worth mentioning, in Europe, DST ("Summer Time") happens all at once. The transition is based on the same UTC moment for Western, Central, and Eastern European time.)
There are other real-world examples where the same point on the calendar is not the same point in time, yet people tend to think of them as if they were.
Day boundaries ("today", "yesterday", "tomorrow")
Other whole named days ("this Wednesday", "last Friday")
Television Shows ("7PM Tuesday nights")
Telephone Calling Plans ("Free nights and weekends")
Countless others...
In Noda Time, you would use a LocalDateTime for these scenarios. Without Noda Time, you would use a DateTime with .Kind == Unspecified.