时区之间的转换时间 [英] Converting time between Timezones

查看:171
本文介绍了时区之间的转换时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用TimeZoneInfo.ConvertTime方法从一个到另一个转换时间。

I'm using TimeZoneInfo.ConvertTime method to convert time from one to another.

在转换日期时间1/1/2006上午二时从珀斯到斯里兰卡Jeyawardenepura其转换为2005年1月31日晚上11:30

While converting the Date Time 1/1/2006 2.00 AM from Perth to Sri Jeyawardenepura its converted to 1/31/2005 11.30pm

虽然从斯里兰卡Jeyawardenepura转换的同时背部(2005年1月31日23:30)飞往柏斯其转换为1/1/2006上午03点00分。

While converting the same time back (1/31/2005 11.30pm) from Sri Jeyawardenepura to Perth its converted to 1/1/2006 3.00 AM.

为什么没有在时区转换1小时区别?

Why there is one hour difference in the Time Zone conversion?

推荐答案

哇,这是一个双重打击!我只是偶然发现这篇文章,是不会发布任何东西,因为它是如此的老人和OP没有表现出任何code。但随后的好奇心得到了最好的我,所以我检查出来。

Wow, this is a Double Whammy! I just stumbled across this post and wasn't going to post anything at all since it's so old and the OP didn't show any code. But then curiosity got the best of me so I checked it out.

只需使用.NET BCL:

Using just the .NET BCL:

string tzid1 = "W. Australia Standard Time"; // Perth
TimeZoneInfo tz1 = TimeZoneInfo.FindSystemTimeZoneById(tzid1);

string tzid2 = "Sri Lanka Standard Time"; // Sri Jeyawardenepura
TimeZoneInfo tz2 = TimeZoneInfo.FindSystemTimeZoneById(tzid2);

DateTime dt1 = new DateTime(2006, 1, 1, 2, 0, 0);
Debug.WriteLine(dt1); // 1/1/2006 2:00:00 AM
DateTime dt2 = TimeZoneInfo.ConvertTime(dt1, tz1, tz2);
Debug.WriteLine(dt2); // 12/31/2005 11:30:00 PM
DateTime dt3 = TimeZoneInfo.ConvertTime(dt2, tz2, tz1);
Debug.WriteLine(dt3); // 1/1/2006 3:00:00 AM

果然,有一个OP的描述不符。起初我以为这一定是由于某种DST的问题,所以我检查斯里兰卡斯里兰卡珀斯。虽然无论是在2006年有一个过渡,既不是任何接近它这个日期。不过,我想我应该检查是否使用了的DateTimeOffset ,以避免任何歧义的问题:

Sure enough, there is the discrepancy that the OP described. At first I thought this must be due to some kind of DST issue, so I checked for Sri Lanka and Perth. While both had a transition in 2006, neither were anywhere close to it for this date. Still, I thought I should check using DateTimeOffset to avoid any ambiguity issues:

string tzid1 = "W. Australia Standard Time"; // Perth
TimeZoneInfo tz1 = TimeZoneInfo.FindSystemTimeZoneById(tzid1);

string tzid2 = "Sri Lanka Standard Time"; // Sri Jeyawardenepura
TimeZoneInfo tz2 = TimeZoneInfo.FindSystemTimeZoneById(tzid2);

DateTime dt = new DateTime(2006, 1, 1, 2, 0, 0);
DateTimeOffset dto1 = new DateTimeOffset(dt, tz1.GetUtcOffset(dt));
Debug.WriteLine(dto1);  // 1/1/2006 2:00:00 AM +08:00
DateTimeOffset dto2 = TimeZoneInfo.ConvertTime(dto1, tz2);
Debug.WriteLine(dto2);  // 12/31/2005 11:30:00 PM +05:30
DateTimeOffset dto3 = TimeZoneInfo.ConvertTime(dto2, tz1);
Debug.WriteLine(dto3);  // 1/1/2006 3:00:00 AM +09:00

和它仍然关闭。你可以看到,它认为该目标的时间应该是 +09:00 ,但珀斯没有切换到,直到12月3日2006年。今年1月,显然仍 +08:00

And it's still off. You can see that it thinks the target time should be at +09:00, but Perth didn't switch to that until December 3rd 2006. In January it was clearly still +08:00.

于是我想...... 野田佳彦时间救援!

So then I thought... Noda Time to the rescue!

首先,让我们检查使用相同的Windows .NET基础类库时区。

First let's check using the same Windows .NET BCL time zones.

string tzid1 = "W. Australia Standard Time"; // Perth
DateTimeZone tz1 = DateTimeZoneProviders.Bcl[tzid1];

string tzid2 = "Sri Lanka Standard Time"; // Sri Jeyawardenepura
DateTimeZone tz2 = DateTimeZoneProviders.Bcl[tzid2];

LocalDateTime ldt1 = new LocalDateTime(2006, 1, 1, 2, 0, 0);
ZonedDateTime zdt1 = ldt1.InZoneStrictly(tz1);
Debug.WriteLine(zdt1.ToDateTimeOffset()); // 1/1/2006 2:00:00 AM +08:00
ZonedDateTime zdt2 = zdt1.WithZone(tz2);
Debug.WriteLine(zdt2.ToDateTimeOffset()); // 12/31/2005 11:30:00 PM +05:30
ZonedDateTime zdt3 = zdt1.WithZone(tz1);
Debug.WriteLine(zdt3.ToDateTimeOffset()); // 1/1/2006 2:00:00 AM +08:00

嘿,这似乎是它固定的,不是吗?如果是的话,这将意味着,这个问题的不是的使用Windows时区数据,因为野田时代的BCL提供程序使用完全相同的数据。所以一定有什么东西在 TimeZoneInfo.ConvertTime 实际上有缺陷的。有的Whammy#1

Hey, that seems like it fixed it, right? If so, that would mean that the problem isn't with the Windows time zone data, because Noda Time's BCL provider uses the exact same data. So there must be something actually defective in TimeZoneInfo.ConvertTime. There's Whammy #1.

所以,只是为了检查,这​​一切都很好,好,让我们尝试同样的事情IANA TZDB数据。据了解更准确毕竟:

So just to check that it's all good and well, let's try the same thing with IANA TZDB data. It's known to be more accurate after all:

string tzid1 = "Australia/Perth";
DateTimeZone tz1 = DateTimeZoneProviders.Tzdb[tzid1];

string tzid2 = "Asia/Colombo"; // Sri Jeyawardenepura
DateTimeZone tz2 = DateTimeZoneProviders.Tzdb[tzid2];

LocalDateTime ldt1 = new LocalDateTime(2006, 1, 1, 2, 0, 0);
ZonedDateTime zdt1 = ldt1.InZoneStrictly(tz1);
Debug.WriteLine(zdt1.ToDateTimeOffset()); // 1/1/2006 2:00:00 AM +08:00
ZonedDateTime zdt2 = zdt1.WithZone(tz2);
Debug.WriteLine(zdt2.ToDateTimeOffset()); // 1/1/2006 12:00:00 AM +06:00
ZonedDateTime zdt3 = zdt1.WithZone(tz1);
Debug.WriteLine(zdt3.ToDateTimeOffset()); // 1/1/2006 2:00:00 AM +08:00

在那里,我的朋友,是的Whammy#2 。请注意,中间的时间是使用 +06:00 偏移?我认为这是错误的,但是当我检查一次这里事实出了TZDB数据是正确的。斯里兰卡的的在 +06:00 在那个时候。它没有切换到 +05:30 至四月

And there, my friends, is Whammy #2. Notice that the middle time is using a +06:00 offset? I thought this was in error, but when I checked once more here it turns out that the TZDB data is correct. Sri Lanka was at +06:00 at that time. It didn't switch to +05:30 until April.

因此​​,要回顾一下Whammys:

So to recap the Whammys:

  • 在Windows TimeZoneInfo.ConvertTime 功能似乎是有缺陷的。
  • 在Windows时区的数据为斯里兰卡标准时间区不正确。
  • The Windows TimeZoneInfo.ConvertTime function appears to be flawed.
  • The Windows Time Zone data for the "Sri Lanka Standard Time" zone is incorrect.

所有最好只用野田的时间和TZDB永远!

感谢乔恩斯基特帮助确定的第一个问题是与方式的W澳大利亚标准时间区由PTED是除$ P $ 的TimeZoneInfo 类。

Thanks to Jon Skeet for helping identify that the first problem is with the way that the "W. Australia Standard Time" zone is being interpreted by the TimeZoneInfo class.

我挖的的深入.NET Framework的参考源$ C ​​$ C,我相信这是发生在私人静态方法 TimeZoneInfo.GetIsDaylightSavingsFromUtc 。我相信,他们没有考虑到DST并不总是启动和停止在同一日历年。

I dug much deeper into the .NET Framework reference source code, and I believe this is happening in the private static method TimeZoneInfo.GetIsDaylightSavingsFromUtc. I believe that they are not taking into account that DST doesn't always start and stop in the same calendar year.

在这种情况下,他们申请了2006年的调整规则与2005年,得到一个 endTime的 的2005年1月2日的startTime 2005年12月4日。他们试图调和这应该是在2006年(由不正确地加入了一年),但他们并不认为数据是相反的顺序。

In this case, they are applying the 2006 adjustment rule with the 2005 year, and getting an endTime of 1/2/2005 before the startTime of 12/4/2005. They do attempt to reconcile that this should be in 2006 (by incorrectly adding a year), but they don't consider that data is in reversed order.

此问题可能会显示为开始新的DST在冬季(如澳大利亚),任何时区,并会以这种或那种形式的任何时间出现的过渡规则的改变 - 它在2006年做了

This problem will probably show up for any time zones that start their DST in the winter (such as Australia), and it will show up in one form or another any time the transition rule changes - which it did in 2006.

我提出的一个问题<一href="https://connect.microsoft.com/VisualStudio/feedback/details/800191/timezoneinfo-is-incorrectly-applying-dst-rules-for-zones-in-the-southern-hemisphere">on微软连接这里。

我所说的二次打击只是因为历史数据,斯里兰卡不会在Windows时区的注册表项存在。

The "second whammy" I mentioned is just because the historical data for Sri Lanka doesn't exist in the Windows time zone registry keys.

这篇关于时区之间的转换时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆