Does .NET have the history of time zone changes?How does C# handle historical daylight saving time?Is there a flaw in Windows 7 Timezone rulesDateTime IsDaylightSavingTime() backwards compatibilityConversion from UTC to Timezone time produces different result with 4.0 and 3.5 SP1Getting a specific Time Zone in .net CF 3.5?Daylight saving time and time zone best practicesRussian time zone changesget DateTimeOffset from DateTime (utc) and TimeZoneInfoDjango timezone: feeling a bit confusedReliable time zone library or web service for PythonUTC to local time conversion for previously saved datetimes if rules for timezone changeMySQL - Turkey/Istanbul Daylight Saving Time ChangeConverting datetime (local or utc) to Moscow and Kiev timezone issues depending on DayLight saving timeHow to deal with time zone changes in Django?
Should I practice til I "get it" or until I'm sick of it?
What does a black-and-white Puerto Rican flag signify?
How does mathematics work?
My current job follows "worst practices". How can I talk about my experience in an interview without giving off red flags?
Calculating Fibonacci sequence in several different ways
Found more old paper shares from broken up companies
Are Linux kernel modules a sort of Linux system paged pool?
How old is the Italian word "malandrino"?
Why did computer video outputs go from digital to analog, then back to digital?
If hash functions append the length, why does length extension attack work?
Why can't a country print its own money to spend it only abroad?
Killing a star safely
Counterexample finite intersection property
Is it OK to accept a job opportunity while planning on not taking it?
Caption in landscape table, need help?
Facebook video calling problem in Safari
Acoustic guitar chords' positions vs those of a Bass guitar
Why didn't NASA launch communications relay satellites for the Apollo missions?
Is it ethical to tell my teaching assistant that I like him?
What is the best word describing the nature of expiring in a short amount of time, connoting "losing public attention"?
As a DM of a 4-player group, would it be appropriate for me to run a private 1-on-1 session so that one PC can act secretly?
What is a "staved" town, like in "Staverton"?
How can I deal with someone that wants to kill something that isn't supposed to be killed?
Why is a PhD thesis typically 150 pages?
Does .NET have the history of time zone changes?
How does C# handle historical daylight saving time?Is there a flaw in Windows 7 Timezone rulesDateTime IsDaylightSavingTime() backwards compatibilityConversion from UTC to Timezone time produces different result with 4.0 and 3.5 SP1Getting a specific Time Zone in .net CF 3.5?Daylight saving time and time zone best practicesRussian time zone changesget DateTimeOffset from DateTime (utc) and TimeZoneInfoDjango timezone: feeling a bit confusedReliable time zone library or web service for PythonUTC to local time conversion for previously saved datetimes if rules for timezone changeMySQL - Turkey/Istanbul Daylight Saving Time ChangeConverting datetime (local or utc) to Moscow and Kiev timezone issues depending on DayLight saving timeHow to deal with time zone changes in Django?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
Our government loves to change local time or enable|disable daylight saving time.
MS deployed patch for Russia to take new time change into account.
Now there is the question whether history of the changes exists?
When I get UTC time of the day in 01.01.2000 system should remember that Moscow time zone had +3 UTC. (in summer +4) at that moment.
For 01.01.2012 we had +4 UTC for both winter and summer. And soon we will have +3 UTC.
simple test shows that .NET does not keep records about the changes:
var t = new DateTime(2012,1,1);
// UTC +4 expected
System.Console.WriteLine(t.ToLocalTime());
// UTC +4 expected
t = new DateTime(2012,06,1);
System.Console.WriteLine(t.ToLocalTime());
// UTC +3 expected
t = new DateTime(2000,1,1);
System.Console.WriteLine(t.ToLocalTime());
// UTC +4 expected
t = new DateTime(2000,6,1);
System.Console.WriteLine(t.ToLocalTime());
Does some additional API exist to cope with the problem?
Update:
Have found class TimeZoneInfo and related AdjustmentRule class. Left to test whether customization of TimeZoneInfo.Local
time zone affects DateTime APIs.
Update 2:
Seems like UTC offsets are not stored as history and AdjustmentRule
changes only daylight time during the year.
.net datetime timezone
add a comment |
Our government loves to change local time or enable|disable daylight saving time.
MS deployed patch for Russia to take new time change into account.
Now there is the question whether history of the changes exists?
When I get UTC time of the day in 01.01.2000 system should remember that Moscow time zone had +3 UTC. (in summer +4) at that moment.
For 01.01.2012 we had +4 UTC for both winter and summer. And soon we will have +3 UTC.
simple test shows that .NET does not keep records about the changes:
var t = new DateTime(2012,1,1);
// UTC +4 expected
System.Console.WriteLine(t.ToLocalTime());
// UTC +4 expected
t = new DateTime(2012,06,1);
System.Console.WriteLine(t.ToLocalTime());
// UTC +3 expected
t = new DateTime(2000,1,1);
System.Console.WriteLine(t.ToLocalTime());
// UTC +4 expected
t = new DateTime(2000,6,1);
System.Console.WriteLine(t.ToLocalTime());
Does some additional API exist to cope with the problem?
Update:
Have found class TimeZoneInfo and related AdjustmentRule class. Left to test whether customization of TimeZoneInfo.Local
time zone affects DateTime APIs.
Update 2:
Seems like UTC offsets are not stored as history and AdjustmentRule
changes only daylight time during the year.
.net datetime timezone
Take a look atDateTimeOffset
. If you can capture the timezone offset as you capture the data you will be in better shape to display it and calculate against it.
– Ian Mercer
Oct 2 '14 at 18:18
add a comment |
Our government loves to change local time or enable|disable daylight saving time.
MS deployed patch for Russia to take new time change into account.
Now there is the question whether history of the changes exists?
When I get UTC time of the day in 01.01.2000 system should remember that Moscow time zone had +3 UTC. (in summer +4) at that moment.
For 01.01.2012 we had +4 UTC for both winter and summer. And soon we will have +3 UTC.
simple test shows that .NET does not keep records about the changes:
var t = new DateTime(2012,1,1);
// UTC +4 expected
System.Console.WriteLine(t.ToLocalTime());
// UTC +4 expected
t = new DateTime(2012,06,1);
System.Console.WriteLine(t.ToLocalTime());
// UTC +3 expected
t = new DateTime(2000,1,1);
System.Console.WriteLine(t.ToLocalTime());
// UTC +4 expected
t = new DateTime(2000,6,1);
System.Console.WriteLine(t.ToLocalTime());
Does some additional API exist to cope with the problem?
Update:
Have found class TimeZoneInfo and related AdjustmentRule class. Left to test whether customization of TimeZoneInfo.Local
time zone affects DateTime APIs.
Update 2:
Seems like UTC offsets are not stored as history and AdjustmentRule
changes only daylight time during the year.
.net datetime timezone
Our government loves to change local time or enable|disable daylight saving time.
MS deployed patch for Russia to take new time change into account.
Now there is the question whether history of the changes exists?
When I get UTC time of the day in 01.01.2000 system should remember that Moscow time zone had +3 UTC. (in summer +4) at that moment.
For 01.01.2012 we had +4 UTC for both winter and summer. And soon we will have +3 UTC.
simple test shows that .NET does not keep records about the changes:
var t = new DateTime(2012,1,1);
// UTC +4 expected
System.Console.WriteLine(t.ToLocalTime());
// UTC +4 expected
t = new DateTime(2012,06,1);
System.Console.WriteLine(t.ToLocalTime());
// UTC +3 expected
t = new DateTime(2000,1,1);
System.Console.WriteLine(t.ToLocalTime());
// UTC +4 expected
t = new DateTime(2000,6,1);
System.Console.WriteLine(t.ToLocalTime());
Does some additional API exist to cope with the problem?
Update:
Have found class TimeZoneInfo and related AdjustmentRule class. Left to test whether customization of TimeZoneInfo.Local
time zone affects DateTime APIs.
Update 2:
Seems like UTC offsets are not stored as history and AdjustmentRule
changes only daylight time during the year.
.net datetime timezone
.net datetime timezone
edited Oct 2 '14 at 8:14
Pavel Voronin
asked Oct 2 '14 at 7:38
Pavel VoroninPavel Voronin
7,6055 gold badges44 silver badges91 bronze badges
7,6055 gold badges44 silver badges91 bronze badges
Take a look atDateTimeOffset
. If you can capture the timezone offset as you capture the data you will be in better shape to display it and calculate against it.
– Ian Mercer
Oct 2 '14 at 18:18
add a comment |
Take a look atDateTimeOffset
. If you can capture the timezone offset as you capture the data you will be in better shape to display it and calculate against it.
– Ian Mercer
Oct 2 '14 at 18:18
Take a look at
DateTimeOffset
. If you can capture the timezone offset as you capture the data you will be in better shape to display it and calculate against it.– Ian Mercer
Oct 2 '14 at 18:18
Take a look at
DateTimeOffset
. If you can capture the timezone offset as you capture the data you will be in better shape to display it and calculate against it.– Ian Mercer
Oct 2 '14 at 18:18
add a comment |
3 Answers
3
active
oldest
votes
.NET tracks some history, but it is not always accurate. You've stumbled upon one of the inaccuracies.
.NET imports all of it's time zone information from Windows via the registry, as described here and here. If you look in the registry at HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionTime ZonesRussian Standard TimeDynamic DST
you'll find that it only tracks information from 2010 forward for this time zone. Testing dates in year 2000 is not going to work well, as it will fall back to the earliest rule available (2010).
Base UTC offset information is tracked in the registry, but not in the AdjustmentRule
class that .NET imports it into. If you check the adjustment rules for this time zone, you'll find that 2012 and 2013 are not imported at all:
var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
foreach (var rule in tz.GetAdjustmentRules())
Console.WriteLine("0:d - 1:d", rule.DateStart, rule.DateEnd);
OUTPUT:
1/1/0001 - 12/31/2010
1/1/2011 - 12/31/2011
1/1/2014 - 12/31/2014
Even though they exist in the Windows registry, 2012 and 2013 are not imported because they have no daylight saving time adjustments.
This creates a problem when the base offset changes - like it has for this time zone. Since it is currently +3, and the two year where it was +4 were not imported, then it will look like it was +3 for those missing years.
There is no good solution for this using TimeZoneInfo
. Even if you try to create your own custom time zones, you'll have trouble fitting this kind of change into the data structures available.
Fortunately, there is another option. You can use standard IANA time zones, via the Noda Time library.
The following code uses Noda Time to match what you wrote in your original code:
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
Console.WriteLine(Instant.FromUtc(2012, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2012, 6, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 6, 1, 0, 0).InZone(tz).LocalDateTime);
If your local time zone is not already set for Moscow, you can change the first line to:
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
OUTPUT:
1/1/2012 4:00:00 AM
6/1/2012 4:00:00 AM
1/1/2000 3:00:00 AM
6/1/2000 4:00:00 AM
Update
The problem described above of AdjustmentRule
not tracking base offset changes was described in Microsoft Support article KB3012229, and subsequently fixed in .NET Framework 4.6 and also in .NET Core.
In the reference sources, one can see that AdjustmentRule
now keeps a m_baseUtcOffsetDelta
field. While this field is not exposed via a public property, it does factor in to the calculations, and it does reflect in serialization if you use the FromSerializedString
and ToSerializedString
methods (if anyone actually uses those).
Something has changed a couple of days ago. Now 2012 and 2013 are imported. At least in .NET 4.5.2 (Win8.1, Win10) 1/1/0001 - 12/31/2010 1/1/2011 - 12/31/2011 1/1/2012 - 12/31/2012 1/1/2013 - 12/31/2013 1/1/2014 - 12/31/2014 But where is the data for 2015 and 2016?
– Pavel Voronin
Mar 2 '16 at 9:26
The last Russia change in 2014 dropped daylight saving time, so there are no adjustment rules for 2015 and later because there are no adjustments; the offset is fixed. The last offset of the last rule in the list should always apply from that time forward.
– Matt Johnson
Mar 2 '16 at 17:50
Also, though you're targeting 4.5.2, I'll guess you have 4.6 installed on the box so it's using the fix for KB3012229 that was implemented in 4.6 (the KB still needs to be updated to reflect that). The side effect is that you now see transition rules for 2012 and 2013 because it's now tracking base-offset changes correctly.
– Matt Johnson
Mar 2 '16 at 17:51
1
Lastly, be aware that there are new time zone changes coming to Russia this month. The Russian government has still not finalized all of them, and provided a very short notice effective date (grrr...). That means it's uncertain to whether they'll be a Windows update or hotfix in time to get in front of it, as Microsoft must wait for the government to make up their mind.
– Matt Johnson
Mar 2 '16 at 17:53
I added an update to the answer describing the changes. Thanks.
– Matt Johnson
Mar 2 '16 at 18:00
add a comment |
you can try NodaTime,
http://nodatime.org/
better explanation of what is does
http://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html
Noda Time - Yes, but link-only answers are discouraged on Stack Overflow.
– Matt Johnson
Oct 2 '14 at 19:07
add a comment |
Historical time zone data is very complex and filled with many examples of small exceptions that apply in specific geographical regions that today have no easy way of being described. Not only are the offsets changing, but so are the regions to which they are applied.
There is a project to model the history of this data from around the world here:
- http://www.iana.org/time-zones
- http://en.wikipedia.org/wiki/Tz_database
.NET doesn't support what you want out of the box. Making a general solution to the problem will be very difficult, however if you only need it over a small set of regions, then you should be able to populate this yourself using the TimeZoneInfo
class, the documentation for which states:
The members of the TimeZoneInfo class support the following operations:
- Creating a new time zone that is not already defined by the operating system
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26156260%2fdoes-net-have-the-history-of-time-zone-changes%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
.NET tracks some history, but it is not always accurate. You've stumbled upon one of the inaccuracies.
.NET imports all of it's time zone information from Windows via the registry, as described here and here. If you look in the registry at HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionTime ZonesRussian Standard TimeDynamic DST
you'll find that it only tracks information from 2010 forward for this time zone. Testing dates in year 2000 is not going to work well, as it will fall back to the earliest rule available (2010).
Base UTC offset information is tracked in the registry, but not in the AdjustmentRule
class that .NET imports it into. If you check the adjustment rules for this time zone, you'll find that 2012 and 2013 are not imported at all:
var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
foreach (var rule in tz.GetAdjustmentRules())
Console.WriteLine("0:d - 1:d", rule.DateStart, rule.DateEnd);
OUTPUT:
1/1/0001 - 12/31/2010
1/1/2011 - 12/31/2011
1/1/2014 - 12/31/2014
Even though they exist in the Windows registry, 2012 and 2013 are not imported because they have no daylight saving time adjustments.
This creates a problem when the base offset changes - like it has for this time zone. Since it is currently +3, and the two year where it was +4 were not imported, then it will look like it was +3 for those missing years.
There is no good solution for this using TimeZoneInfo
. Even if you try to create your own custom time zones, you'll have trouble fitting this kind of change into the data structures available.
Fortunately, there is another option. You can use standard IANA time zones, via the Noda Time library.
The following code uses Noda Time to match what you wrote in your original code:
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
Console.WriteLine(Instant.FromUtc(2012, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2012, 6, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 6, 1, 0, 0).InZone(tz).LocalDateTime);
If your local time zone is not already set for Moscow, you can change the first line to:
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
OUTPUT:
1/1/2012 4:00:00 AM
6/1/2012 4:00:00 AM
1/1/2000 3:00:00 AM
6/1/2000 4:00:00 AM
Update
The problem described above of AdjustmentRule
not tracking base offset changes was described in Microsoft Support article KB3012229, and subsequently fixed in .NET Framework 4.6 and also in .NET Core.
In the reference sources, one can see that AdjustmentRule
now keeps a m_baseUtcOffsetDelta
field. While this field is not exposed via a public property, it does factor in to the calculations, and it does reflect in serialization if you use the FromSerializedString
and ToSerializedString
methods (if anyone actually uses those).
Something has changed a couple of days ago. Now 2012 and 2013 are imported. At least in .NET 4.5.2 (Win8.1, Win10) 1/1/0001 - 12/31/2010 1/1/2011 - 12/31/2011 1/1/2012 - 12/31/2012 1/1/2013 - 12/31/2013 1/1/2014 - 12/31/2014 But where is the data for 2015 and 2016?
– Pavel Voronin
Mar 2 '16 at 9:26
The last Russia change in 2014 dropped daylight saving time, so there are no adjustment rules for 2015 and later because there are no adjustments; the offset is fixed. The last offset of the last rule in the list should always apply from that time forward.
– Matt Johnson
Mar 2 '16 at 17:50
Also, though you're targeting 4.5.2, I'll guess you have 4.6 installed on the box so it's using the fix for KB3012229 that was implemented in 4.6 (the KB still needs to be updated to reflect that). The side effect is that you now see transition rules for 2012 and 2013 because it's now tracking base-offset changes correctly.
– Matt Johnson
Mar 2 '16 at 17:51
1
Lastly, be aware that there are new time zone changes coming to Russia this month. The Russian government has still not finalized all of them, and provided a very short notice effective date (grrr...). That means it's uncertain to whether they'll be a Windows update or hotfix in time to get in front of it, as Microsoft must wait for the government to make up their mind.
– Matt Johnson
Mar 2 '16 at 17:53
I added an update to the answer describing the changes. Thanks.
– Matt Johnson
Mar 2 '16 at 18:00
add a comment |
.NET tracks some history, but it is not always accurate. You've stumbled upon one of the inaccuracies.
.NET imports all of it's time zone information from Windows via the registry, as described here and here. If you look in the registry at HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionTime ZonesRussian Standard TimeDynamic DST
you'll find that it only tracks information from 2010 forward for this time zone. Testing dates in year 2000 is not going to work well, as it will fall back to the earliest rule available (2010).
Base UTC offset information is tracked in the registry, but not in the AdjustmentRule
class that .NET imports it into. If you check the adjustment rules for this time zone, you'll find that 2012 and 2013 are not imported at all:
var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
foreach (var rule in tz.GetAdjustmentRules())
Console.WriteLine("0:d - 1:d", rule.DateStart, rule.DateEnd);
OUTPUT:
1/1/0001 - 12/31/2010
1/1/2011 - 12/31/2011
1/1/2014 - 12/31/2014
Even though they exist in the Windows registry, 2012 and 2013 are not imported because they have no daylight saving time adjustments.
This creates a problem when the base offset changes - like it has for this time zone. Since it is currently +3, and the two year where it was +4 were not imported, then it will look like it was +3 for those missing years.
There is no good solution for this using TimeZoneInfo
. Even if you try to create your own custom time zones, you'll have trouble fitting this kind of change into the data structures available.
Fortunately, there is another option. You can use standard IANA time zones, via the Noda Time library.
The following code uses Noda Time to match what you wrote in your original code:
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
Console.WriteLine(Instant.FromUtc(2012, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2012, 6, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 6, 1, 0, 0).InZone(tz).LocalDateTime);
If your local time zone is not already set for Moscow, you can change the first line to:
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
OUTPUT:
1/1/2012 4:00:00 AM
6/1/2012 4:00:00 AM
1/1/2000 3:00:00 AM
6/1/2000 4:00:00 AM
Update
The problem described above of AdjustmentRule
not tracking base offset changes was described in Microsoft Support article KB3012229, and subsequently fixed in .NET Framework 4.6 and also in .NET Core.
In the reference sources, one can see that AdjustmentRule
now keeps a m_baseUtcOffsetDelta
field. While this field is not exposed via a public property, it does factor in to the calculations, and it does reflect in serialization if you use the FromSerializedString
and ToSerializedString
methods (if anyone actually uses those).
Something has changed a couple of days ago. Now 2012 and 2013 are imported. At least in .NET 4.5.2 (Win8.1, Win10) 1/1/0001 - 12/31/2010 1/1/2011 - 12/31/2011 1/1/2012 - 12/31/2012 1/1/2013 - 12/31/2013 1/1/2014 - 12/31/2014 But where is the data for 2015 and 2016?
– Pavel Voronin
Mar 2 '16 at 9:26
The last Russia change in 2014 dropped daylight saving time, so there are no adjustment rules for 2015 and later because there are no adjustments; the offset is fixed. The last offset of the last rule in the list should always apply from that time forward.
– Matt Johnson
Mar 2 '16 at 17:50
Also, though you're targeting 4.5.2, I'll guess you have 4.6 installed on the box so it's using the fix for KB3012229 that was implemented in 4.6 (the KB still needs to be updated to reflect that). The side effect is that you now see transition rules for 2012 and 2013 because it's now tracking base-offset changes correctly.
– Matt Johnson
Mar 2 '16 at 17:51
1
Lastly, be aware that there are new time zone changes coming to Russia this month. The Russian government has still not finalized all of them, and provided a very short notice effective date (grrr...). That means it's uncertain to whether they'll be a Windows update or hotfix in time to get in front of it, as Microsoft must wait for the government to make up their mind.
– Matt Johnson
Mar 2 '16 at 17:53
I added an update to the answer describing the changes. Thanks.
– Matt Johnson
Mar 2 '16 at 18:00
add a comment |
.NET tracks some history, but it is not always accurate. You've stumbled upon one of the inaccuracies.
.NET imports all of it's time zone information from Windows via the registry, as described here and here. If you look in the registry at HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionTime ZonesRussian Standard TimeDynamic DST
you'll find that it only tracks information from 2010 forward for this time zone. Testing dates in year 2000 is not going to work well, as it will fall back to the earliest rule available (2010).
Base UTC offset information is tracked in the registry, but not in the AdjustmentRule
class that .NET imports it into. If you check the adjustment rules for this time zone, you'll find that 2012 and 2013 are not imported at all:
var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
foreach (var rule in tz.GetAdjustmentRules())
Console.WriteLine("0:d - 1:d", rule.DateStart, rule.DateEnd);
OUTPUT:
1/1/0001 - 12/31/2010
1/1/2011 - 12/31/2011
1/1/2014 - 12/31/2014
Even though they exist in the Windows registry, 2012 and 2013 are not imported because they have no daylight saving time adjustments.
This creates a problem when the base offset changes - like it has for this time zone. Since it is currently +3, and the two year where it was +4 were not imported, then it will look like it was +3 for those missing years.
There is no good solution for this using TimeZoneInfo
. Even if you try to create your own custom time zones, you'll have trouble fitting this kind of change into the data structures available.
Fortunately, there is another option. You can use standard IANA time zones, via the Noda Time library.
The following code uses Noda Time to match what you wrote in your original code:
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
Console.WriteLine(Instant.FromUtc(2012, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2012, 6, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 6, 1, 0, 0).InZone(tz).LocalDateTime);
If your local time zone is not already set for Moscow, you can change the first line to:
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
OUTPUT:
1/1/2012 4:00:00 AM
6/1/2012 4:00:00 AM
1/1/2000 3:00:00 AM
6/1/2000 4:00:00 AM
Update
The problem described above of AdjustmentRule
not tracking base offset changes was described in Microsoft Support article KB3012229, and subsequently fixed in .NET Framework 4.6 and also in .NET Core.
In the reference sources, one can see that AdjustmentRule
now keeps a m_baseUtcOffsetDelta
field. While this field is not exposed via a public property, it does factor in to the calculations, and it does reflect in serialization if you use the FromSerializedString
and ToSerializedString
methods (if anyone actually uses those).
.NET tracks some history, but it is not always accurate. You've stumbled upon one of the inaccuracies.
.NET imports all of it's time zone information from Windows via the registry, as described here and here. If you look in the registry at HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionTime ZonesRussian Standard TimeDynamic DST
you'll find that it only tracks information from 2010 forward for this time zone. Testing dates in year 2000 is not going to work well, as it will fall back to the earliest rule available (2010).
Base UTC offset information is tracked in the registry, but not in the AdjustmentRule
class that .NET imports it into. If you check the adjustment rules for this time zone, you'll find that 2012 and 2013 are not imported at all:
var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
foreach (var rule in tz.GetAdjustmentRules())
Console.WriteLine("0:d - 1:d", rule.DateStart, rule.DateEnd);
OUTPUT:
1/1/0001 - 12/31/2010
1/1/2011 - 12/31/2011
1/1/2014 - 12/31/2014
Even though they exist in the Windows registry, 2012 and 2013 are not imported because they have no daylight saving time adjustments.
This creates a problem when the base offset changes - like it has for this time zone. Since it is currently +3, and the two year where it was +4 were not imported, then it will look like it was +3 for those missing years.
There is no good solution for this using TimeZoneInfo
. Even if you try to create your own custom time zones, you'll have trouble fitting this kind of change into the data structures available.
Fortunately, there is another option. You can use standard IANA time zones, via the Noda Time library.
The following code uses Noda Time to match what you wrote in your original code:
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
Console.WriteLine(Instant.FromUtc(2012, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2012, 6, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 6, 1, 0, 0).InZone(tz).LocalDateTime);
If your local time zone is not already set for Moscow, you can change the first line to:
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
OUTPUT:
1/1/2012 4:00:00 AM
6/1/2012 4:00:00 AM
1/1/2000 3:00:00 AM
6/1/2000 4:00:00 AM
Update
The problem described above of AdjustmentRule
not tracking base offset changes was described in Microsoft Support article KB3012229, and subsequently fixed in .NET Framework 4.6 and also in .NET Core.
In the reference sources, one can see that AdjustmentRule
now keeps a m_baseUtcOffsetDelta
field. While this field is not exposed via a public property, it does factor in to the calculations, and it does reflect in serialization if you use the FromSerializedString
and ToSerializedString
methods (if anyone actually uses those).
edited Mar 2 '16 at 18:00
answered Oct 2 '14 at 18:11
Matt JohnsonMatt Johnson
150k47 gold badges300 silver badges424 bronze badges
150k47 gold badges300 silver badges424 bronze badges
Something has changed a couple of days ago. Now 2012 and 2013 are imported. At least in .NET 4.5.2 (Win8.1, Win10) 1/1/0001 - 12/31/2010 1/1/2011 - 12/31/2011 1/1/2012 - 12/31/2012 1/1/2013 - 12/31/2013 1/1/2014 - 12/31/2014 But where is the data for 2015 and 2016?
– Pavel Voronin
Mar 2 '16 at 9:26
The last Russia change in 2014 dropped daylight saving time, so there are no adjustment rules for 2015 and later because there are no adjustments; the offset is fixed. The last offset of the last rule in the list should always apply from that time forward.
– Matt Johnson
Mar 2 '16 at 17:50
Also, though you're targeting 4.5.2, I'll guess you have 4.6 installed on the box so it's using the fix for KB3012229 that was implemented in 4.6 (the KB still needs to be updated to reflect that). The side effect is that you now see transition rules for 2012 and 2013 because it's now tracking base-offset changes correctly.
– Matt Johnson
Mar 2 '16 at 17:51
1
Lastly, be aware that there are new time zone changes coming to Russia this month. The Russian government has still not finalized all of them, and provided a very short notice effective date (grrr...). That means it's uncertain to whether they'll be a Windows update or hotfix in time to get in front of it, as Microsoft must wait for the government to make up their mind.
– Matt Johnson
Mar 2 '16 at 17:53
I added an update to the answer describing the changes. Thanks.
– Matt Johnson
Mar 2 '16 at 18:00
add a comment |
Something has changed a couple of days ago. Now 2012 and 2013 are imported. At least in .NET 4.5.2 (Win8.1, Win10) 1/1/0001 - 12/31/2010 1/1/2011 - 12/31/2011 1/1/2012 - 12/31/2012 1/1/2013 - 12/31/2013 1/1/2014 - 12/31/2014 But where is the data for 2015 and 2016?
– Pavel Voronin
Mar 2 '16 at 9:26
The last Russia change in 2014 dropped daylight saving time, so there are no adjustment rules for 2015 and later because there are no adjustments; the offset is fixed. The last offset of the last rule in the list should always apply from that time forward.
– Matt Johnson
Mar 2 '16 at 17:50
Also, though you're targeting 4.5.2, I'll guess you have 4.6 installed on the box so it's using the fix for KB3012229 that was implemented in 4.6 (the KB still needs to be updated to reflect that). The side effect is that you now see transition rules for 2012 and 2013 because it's now tracking base-offset changes correctly.
– Matt Johnson
Mar 2 '16 at 17:51
1
Lastly, be aware that there are new time zone changes coming to Russia this month. The Russian government has still not finalized all of them, and provided a very short notice effective date (grrr...). That means it's uncertain to whether they'll be a Windows update or hotfix in time to get in front of it, as Microsoft must wait for the government to make up their mind.
– Matt Johnson
Mar 2 '16 at 17:53
I added an update to the answer describing the changes. Thanks.
– Matt Johnson
Mar 2 '16 at 18:00
Something has changed a couple of days ago. Now 2012 and 2013 are imported. At least in .NET 4.5.2 (Win8.1, Win10) 1/1/0001 - 12/31/2010 1/1/2011 - 12/31/2011 1/1/2012 - 12/31/2012 1/1/2013 - 12/31/2013 1/1/2014 - 12/31/2014 But where is the data for 2015 and 2016?
– Pavel Voronin
Mar 2 '16 at 9:26
Something has changed a couple of days ago. Now 2012 and 2013 are imported. At least in .NET 4.5.2 (Win8.1, Win10) 1/1/0001 - 12/31/2010 1/1/2011 - 12/31/2011 1/1/2012 - 12/31/2012 1/1/2013 - 12/31/2013 1/1/2014 - 12/31/2014 But where is the data for 2015 and 2016?
– Pavel Voronin
Mar 2 '16 at 9:26
The last Russia change in 2014 dropped daylight saving time, so there are no adjustment rules for 2015 and later because there are no adjustments; the offset is fixed. The last offset of the last rule in the list should always apply from that time forward.
– Matt Johnson
Mar 2 '16 at 17:50
The last Russia change in 2014 dropped daylight saving time, so there are no adjustment rules for 2015 and later because there are no adjustments; the offset is fixed. The last offset of the last rule in the list should always apply from that time forward.
– Matt Johnson
Mar 2 '16 at 17:50
Also, though you're targeting 4.5.2, I'll guess you have 4.6 installed on the box so it's using the fix for KB3012229 that was implemented in 4.6 (the KB still needs to be updated to reflect that). The side effect is that you now see transition rules for 2012 and 2013 because it's now tracking base-offset changes correctly.
– Matt Johnson
Mar 2 '16 at 17:51
Also, though you're targeting 4.5.2, I'll guess you have 4.6 installed on the box so it's using the fix for KB3012229 that was implemented in 4.6 (the KB still needs to be updated to reflect that). The side effect is that you now see transition rules for 2012 and 2013 because it's now tracking base-offset changes correctly.
– Matt Johnson
Mar 2 '16 at 17:51
1
1
Lastly, be aware that there are new time zone changes coming to Russia this month. The Russian government has still not finalized all of them, and provided a very short notice effective date (grrr...). That means it's uncertain to whether they'll be a Windows update or hotfix in time to get in front of it, as Microsoft must wait for the government to make up their mind.
– Matt Johnson
Mar 2 '16 at 17:53
Lastly, be aware that there are new time zone changes coming to Russia this month. The Russian government has still not finalized all of them, and provided a very short notice effective date (grrr...). That means it's uncertain to whether they'll be a Windows update or hotfix in time to get in front of it, as Microsoft must wait for the government to make up their mind.
– Matt Johnson
Mar 2 '16 at 17:53
I added an update to the answer describing the changes. Thanks.
– Matt Johnson
Mar 2 '16 at 18:00
I added an update to the answer describing the changes. Thanks.
– Matt Johnson
Mar 2 '16 at 18:00
add a comment |
you can try NodaTime,
http://nodatime.org/
better explanation of what is does
http://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html
Noda Time - Yes, but link-only answers are discouraged on Stack Overflow.
– Matt Johnson
Oct 2 '14 at 19:07
add a comment |
you can try NodaTime,
http://nodatime.org/
better explanation of what is does
http://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html
Noda Time - Yes, but link-only answers are discouraged on Stack Overflow.
– Matt Johnson
Oct 2 '14 at 19:07
add a comment |
you can try NodaTime,
http://nodatime.org/
better explanation of what is does
http://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html
you can try NodaTime,
http://nodatime.org/
better explanation of what is does
http://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html
answered Oct 2 '14 at 8:19
dariogriffodariogriffo
2,88912 silver badges24 bronze badges
2,88912 silver badges24 bronze badges
Noda Time - Yes, but link-only answers are discouraged on Stack Overflow.
– Matt Johnson
Oct 2 '14 at 19:07
add a comment |
Noda Time - Yes, but link-only answers are discouraged on Stack Overflow.
– Matt Johnson
Oct 2 '14 at 19:07
Noda Time - Yes, but link-only answers are discouraged on Stack Overflow.
– Matt Johnson
Oct 2 '14 at 19:07
Noda Time - Yes, but link-only answers are discouraged on Stack Overflow.
– Matt Johnson
Oct 2 '14 at 19:07
add a comment |
Historical time zone data is very complex and filled with many examples of small exceptions that apply in specific geographical regions that today have no easy way of being described. Not only are the offsets changing, but so are the regions to which they are applied.
There is a project to model the history of this data from around the world here:
- http://www.iana.org/time-zones
- http://en.wikipedia.org/wiki/Tz_database
.NET doesn't support what you want out of the box. Making a general solution to the problem will be very difficult, however if you only need it over a small set of regions, then you should be able to populate this yourself using the TimeZoneInfo
class, the documentation for which states:
The members of the TimeZoneInfo class support the following operations:
- Creating a new time zone that is not already defined by the operating system
add a comment |
Historical time zone data is very complex and filled with many examples of small exceptions that apply in specific geographical regions that today have no easy way of being described. Not only are the offsets changing, but so are the regions to which they are applied.
There is a project to model the history of this data from around the world here:
- http://www.iana.org/time-zones
- http://en.wikipedia.org/wiki/Tz_database
.NET doesn't support what you want out of the box. Making a general solution to the problem will be very difficult, however if you only need it over a small set of regions, then you should be able to populate this yourself using the TimeZoneInfo
class, the documentation for which states:
The members of the TimeZoneInfo class support the following operations:
- Creating a new time zone that is not already defined by the operating system
add a comment |
Historical time zone data is very complex and filled with many examples of small exceptions that apply in specific geographical regions that today have no easy way of being described. Not only are the offsets changing, but so are the regions to which they are applied.
There is a project to model the history of this data from around the world here:
- http://www.iana.org/time-zones
- http://en.wikipedia.org/wiki/Tz_database
.NET doesn't support what you want out of the box. Making a general solution to the problem will be very difficult, however if you only need it over a small set of regions, then you should be able to populate this yourself using the TimeZoneInfo
class, the documentation for which states:
The members of the TimeZoneInfo class support the following operations:
- Creating a new time zone that is not already defined by the operating system
Historical time zone data is very complex and filled with many examples of small exceptions that apply in specific geographical regions that today have no easy way of being described. Not only are the offsets changing, but so are the regions to which they are applied.
There is a project to model the history of this data from around the world here:
- http://www.iana.org/time-zones
- http://en.wikipedia.org/wiki/Tz_database
.NET doesn't support what you want out of the box. Making a general solution to the problem will be very difficult, however if you only need it over a small set of regions, then you should be able to populate this yourself using the TimeZoneInfo
class, the documentation for which states:
The members of the TimeZoneInfo class support the following operations:
- Creating a new time zone that is not already defined by the operating system
answered Oct 2 '14 at 8:25
Drew NoakesDrew Noakes
197k124 gold badges542 silver badges636 bronze badges
197k124 gold badges542 silver badges636 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26156260%2fdoes-net-have-the-history-of-time-zone-changes%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Take a look at
DateTimeOffset
. If you can capture the timezone offset as you capture the data you will be in better shape to display it and calculate against it.– Ian Mercer
Oct 2 '14 at 18:18