I have flight arrival time and the flight departure time. I have to check if the flight time falls in the daylight saving transition (Equinox Transition). If the hour is forward I need to add an hour in flight time else if the hour is reverted I need to deduct an hour from flight time.
In TimeZoneInfo class we do have IsDaylightSavingTime but it only says either if the time is in Daylight saving or not.
I need to check that my timespan is either effected by DayLight Saving Transition or not.
Update1: The transition is observed in March and November but the date changes every year so I can't hard code any date. I need to get the specific date of the year at which the EQUINOX will occur.
Update2: Datetime is local not UTC, as the flight arrival and departure are from the same airport.
Data:
Flight Departure Time : 19 March 2019 23:00
Flight Arrival Time : 20 March 2019 08:00
Flight Time : 7 Hours but due to EQUINOX its 8 Hours as the hour was forward at
20 March 2019 05:58
The GetAdjustmentRules provide you the info you are looking for:
Provides information about a time zone adjustment, such as the transition to and from daylight saving time.
Example of the output of the sample code in the above link:
W. Europe Standard Time Adjustment rules
Start Date: Monday, January 01, 0001
End Date: Friday, December 31, 9999
Time Change: 1:00 hours
Annual Start: The Last Sunday of March at 2:00 AM
Annual End: The Last Sunday of October at 3:00 AM
Also the IsInvalidTime say you if the specific value is invalid due to daylight transition.
You can convert it to a valid DateTime by using:
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById(id);
if (timeZone.IsInvalidTime(dateTime))
dateTime = TimeZoneInfo.ConvertTime(dateTime.ToUniversalTime(), timeZone);
Finally, my suggestion is to store and evaluate DateTime as UTC in order to avoid ambiguity. You can convert it to local time for GUI purpose only.
EDIT: here is there an example of how to use GetAdjustmentRules.
Related
I am trying to get the offset hours of a particular time for EST timezone like this
var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
est.GetUtcOffset(new DateTime(2020, 3, 9)).Hours;
This works fine and returns me -4, which is right for 9th March 2020 because the daylight saving changes on 8th March 2020 02:00:00, but when I try to run the same code for date 8th March 2020 02:00:00, it returns me -5, while my understanding is that from 2am of 8th march it should start returning me -4.
To get the -4, I have to run it for 3am, that is one hour after the daylight changing.
But why is it so? Why do I have to add one hour to make daylight change take effect?
From the Remarks section of the TimeZoneInfo.GetUtcOffset docs:
... If dateTime is ambiguous, or if the converted time is ambiguous, this method interprets the ambiguous time as a standard time. If dateTime is invalid, this method returns a TimeSpan object that reflects the difference between UTC and the time zone's standard time.
The datetime 2020-03-08 02:00:00, is invalid in the US Eastern time zone, because the clocks advance from 01:59:59 to 03:00:00 on that day. Thus, the GetUtcOffset uses its described behavior of returning the standard time offset. You can detect this if you first call TimeZoneInfo.IsInvalidTime.
You might want to also use other methods from TimeZoneInfo to apply specific behavior. For example, it's commonly desired in appointment scheduling scenarios to use the behavior I presented in the ToDateTimeOffset extension method in this other answer.
I'm using the Noda Time libarary (v 2.0.3) for date time handling in a .net core project. However; I'm having some issues converting an instant to a CET date-time.
I'm fairly new to Noda Time, possibly using it wrong (is not CET tz-db entry referring to CET at all)?
Example code
// get current system instant
var systemInstant = SystemClock.Instance.GetCurrentInstant();
// get oslo zoneddatetime from instant
var osloDateTime = systemInstant.InZone(DateTimeZoneProviders.Tzdb["Europe/Oslo"]);
// get CET(?) zoneddatetime from instant
var cetDateTime = systemInstant.InZone(DateTimeZoneProviders.Tzdb["CET"]);
// output
Debug.WriteLine(osloDateTime.ToString());
Debug.WriteLine(cetDateTime.ToString());
The output from the example code above gives me:
2017-06-16T22:28:16 Europe/Oslo (+02)
2017-06-16T22:28:16 CET (+02)
Acutally I was expecting the CET zoned time to be 21:28:16 (UTC+1) and not 22:28:16 (UTC+2). UTC+1 is also what the Time and date website displaying.
The Zone line of the europe file in the IANA time zone database contains this single line for the CET zone ID:
Zone CET 1:00 C-Eur CE%sT
Then the end recurrence of the C-Eur rule is this pair of lines:
Rule C-Eur 1981 max - Mar lastSun 2:00s 1:00 S
Rule C-Eur 1996 max - Oct lastSun 2:00s 0 -
So it goes into UTC+2 at 2am on the last Sunday of March each year, and back to UTC+1 at 2am on the last Sunday of October each year.
Note that the "abbreviation" in the CET time zone will vary between "CET" and "CEST" - and that may be what's misleading you. But Noda Time is following the definition of the ID "CET" as per the IANA database.
This is just another reason to avoid using the abbreviations, and instead to use full zone IDs such as Europe/Oslo which are unambiguous. I would suggest avoid trying to use the concept of "a CET date-time" entirely.
If you look at the result of DateTimeZoneProviders.Tzdb["CET"], it has a minimum offset of +1 and a maximum offset of +2, so I think it is refering to the actual central European timezone (including the Central European Summer Time [CEST]).
As the date you selected falls into the summer time range, it is UTC+2.
If you try the following you get UTC+1 for CET:
Instant.FromDateTimeUtc(new DateTime(2017, 01, 01, 12, 0, 0, DateTimeKind.Utc)).InZone(DateTimeZoneProviders.Tzdb["CET"]
I cannot understand or find any information that could explain why there are two different time component output (12p.m and 11 a.m) for the following. Can somebody please explain.
DateTime d1 = new DateTime(2015, 05, 15).ToUniversalTime();
DateTime d2 = new DateTime(2015, 02, 02).ToUniversalTime();
Console.WriteLine(d1.ToString()); //OUTPUTS - 1/05/2015 12:00:00 p.m.
Console.WriteLine(d2.ToString()); //OUTPUTS - 1/02/2015 11:00:00 a.m.
The ToUniveralTime method converts from the local time zone where the code is running, to UTC.
Since time zones can change their offsets from UTC at different times of the year, the value can easily be different between two different dates - especially since one date is in the winter, and the other is in the summer, due to daylight saving time.
See also, the DST tag wiki, and "time zone != offset" in the timezone tag wiki.
so I know the function DateTimeOffset.Now.Offset returns the offset from UTC and from wikipedia it states that GMT and UTC are the same. Therefore I would guess that DateTimeOffset.Now.Offset.ToString() would always return 00:00:00 if your timezone is (UTC) London. Am I correct in thinking this or would it return 01:00:00 when in daylight savings time?
DateTimeOffset.Now.Offset.ToString() would always return 00:00:00 if
your timezone is UTC.
Right. From documentation of DateTimeOffset.Offset property;
The difference between the current DateTimeOffset object's time value
and Coordinated Universal Time (UTC).
As you can see, it is normal to get 00:00:00 since London is UTC±00:00 which is what we are expected.
Am I correct in thinking this or would it return 01:00:00 when in
daylight savings time?
Exactly. From Wikipedia page of Daylight saving time;
Typically, users of DST adjust clocks forward one hour near the start
of spring and adjust them backward in the autumn to "normal" or
regular time.
By the way, you can't change your offset value with creating a Datetime which it is in your daylight saving time. OffSet value can be change only with changing your time zone manually or with daylight saving time. Your DateTimeOffset still has the same offset value even if you create it when times that daylight saving time.
Yes, UTC and GMT are the same. Just "GMT" term are not using most of computer science community.
I encountered what may be a leap year in .NET's DateTime handling, specifically ToLocalTime(). Here's some code which reproduces the problem (I'm in the Pacific time zone):
DateTime dtStartLocal = DateTime.Parse("2009-02-28T23:00:00.0-08:00");
DateTime dtEndLocal = dtStartLocal.AddYears(3);
DateTime dtStartUtc = dtStartLocal.ToUniversalTime();
DateTime dtEndUtc = dtStartUtc.AddYears(3);
DateTime dtEndLocal2 = dtEndUtc.ToLocalTime();
DateTime dtStartLocal2 = dtStartUtc.ToLocalTime();
Console.WriteLine("START: 1={0}, 2={0}", dtStartLocal, dtStartLocal2);
Console.WriteLine("END : 1={0}, 2={1}", dtEndLocal, dtEndLocal2);
Console.ReadLine();
The output is:
START: 1=2/28/2009 11:00:00 PM, 2=2/28/2009 11:00:00 PM
END : 1=2/28/2012 11:00:00 PM, 2=2/29/2012 11:00:00 PM
Notice the variable which I did ToUniversalTime().AddYears(3).ToLocalTime() is different than just AddYears(3), it's one day ahead.
Has anyone encountered this? If this is expected, can someone explain the logic behind it?
NOTE: Yes, the best approach is to work entirely in UTC and not flip flop between them. This isn't something which is effecting me, but a peculiarity I encountered. Essentially I misunderstood how AddYears() worked and now I can see why it's doing what it's doing (see my selected answer below).
I think that this is working correctly.
DateTime dtStartUtc = dtStartLocal.ToUniversalTime();
PST is UTC-8. Therefore, this converts the time to March 1, 2009, 07:00:00.
DateTime dtEndUtc = dtStartUtc.AddYears(3);
This adds three years to the previous time, putting it at March 1, 2012, 07:00:00.
DateTime dtEndLocal2 = dtEndUtc.ToLocalTime();
This converts the end time back to PST, which would be February 29, 2012, 11:00:00.
I'd say this is just a side affect of converting between local and UTC time.
Print the timezone/correction factor. When you do the .ToUniversialTime() it essentially adds the 8 hours from your original time ("-08:00"), which would put it at 11:00 the next day starting from 23:00 hours February 28th. So when you add 3 years to it, it's the 11:00 AM on the 29th. Had you done 2 years, it would have been March 1st, it has nothing to do with the leap year.
This behaviour isn't incorrect, as far as I can tell. When you convert the local time to UTC it effectively pushes it into the next day; March 1st. When you add three years, it stays as March 1st. Convert it back to local time and it rolls back to the previous day, which because 2012 is a leap year, is February 29th.