当前位置: 首页 > 知识库问答 >
问题:

在时区之间转换时间

养聪
2023-03-14

当将同一时间从Sri Jeyawardenepura转换回珀斯时(1/31/2005 11:30 PM),它转换到1/1/2006 3:00 AM。

时区换算为什么会有一个小时的差?

共有1个答案

屠兴旺
2023-03-14

哇,真是祸不单行!我只是偶然发现了这篇文章,并不打算发表任何东西,因为它是如此古老和操作没有显示任何代码。但后来好奇心占了我的上风所以我去查了一下。

仅使用.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进行检查,以避免任何歧义问题:

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
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时区数据,因为Noda time的BCL提供程序使用的是完全相同的数据。所以timezoneinfo.converttime中肯定有什么实际缺陷。有一号祸害。

因此,为了检查它是否都是好的,让我们用IANA TZDB数据来尝试同样的事情。它毕竟更准确:

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

我的朋友们,这就是第二个祸害。注意中间时间使用+06:00偏移量?我以为这是错误的,但当我再次检查这里,它发现TZDB数据是正确的。斯里兰卡当时处于+06:00。直到4月份才切换到+05:30

    null

在本例中,他们将2006调整规则应用于2005年,并在12/4/2005starttime之前获得1/2/2005endtime。他们确实试图核对这应该是在2006年(通过错误地加上一年),但他们并不认为数据的顺序是颠倒的。

这个问题可能会出现在任何在冬季开始DST的时区(比如澳大利亚),并且它会以一种或另一种形式出现在过渡规则发生变化时--2006年就发生了这种变化。

我在这里提出了一个关于Microsoft Connect的问题。

 类似资料:
  • 我不想使用 库,因为我正在处理的项目需要文书工作来引入依赖项。如果我能在没有第三方库的情况下实现这一目标,我会更高兴。 我很难在CET和UTC之间转换日期,因为日期是夏时制。这与我预期的相差一个小时: CET比UTC提前一小时,夏季提前2小时。因此,我预计中欧在盛夏的10点30分将达到协调世界时的8点30分。 功能是: 我使用两个时区信息对象:

  • 如果给出一个UTC的日期(比方说),考虑到DST是否可以转换成不同的时区? 我很感兴趣的是,如果JS可以在没有时区列表和它们的偏移量的情况下实现这个功能。 多谢了。

  • 我有一个日期。它是如何存储在数据库中的。我正在使用并调用此函数。 在这里,我知道我的

  • 问题内容: 解决的问题 外部设备正在计算并发送非标准的2小时轮班时间戳,这使我非常困惑,并启动了该线程。时区 不会影响自己的时间戳 ,时区仅在以人类可读形式进行转换时适用。 我在UTC时区有时间戳记(距离unix纪元的秒数​​),没有DST(夏令时)。 我想要使​​用DST的“欧洲/布拉格”时区中的时间戳(距Unix纪元的秒数​​)。 我曾经以为unix时间戳不受时区限制,时区仅影响将时间戳转换为

  • 问题内容: 我知道这个主题已被殴打致死,但在搜寻了这个问题几个小时之后,我不得不问。 我的问题:根据客户端应用程序(iphone)的当前时区对服务器上的日期进行计算。客户端应用程序以秒为单位告诉服务器,其时区距GMT的距离。然后,我想使用此信息对服务器中的日期进行计算。服务器上的日期都存储为UTC时间。 因此,在将UTC日期对象转换为该本地时区之后,我想获取其HOUR。 我目前的尝试: 变量小时和

  • 我想将时间戳转换为。 这是我到目前为止已经实现的,但是它给了我错误的月份 任何帮助将不胜感激。