2012-03-01 36 views
18

我的本地时区为(UTC + 10:00)堪培拉,墨尔本,悉尼日期时间 - 斯特兰奇夏令行为

周六31-MAR-2012 15:59 UTC =太阳01-APR-2012 + 02:59 11:00
周六31-MAR-2012 16:00 UTC =太阳01-APR-2012 02:00 +10:00

夏令结束在凌晨3点第一个星期天到4月和钟风回1小时。

考虑下面的代码....

DateTime dt1 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal); 

DateTime dt2 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal).AddMinutes(1); 
DateTime dt3 = DateTime.Parse("31-Mar-2012 16:00", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal); 

Console.WriteLine("{0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1); 
Console.WriteLine("{0:yyyy-MMM-dd HH:mm:ss.ffff K} ({1}) = {2:yyyy-MMM-dd HH:mm:ss.ffff K} ({3})", dt2, dt2.Kind, dt3, dt3.Kind); 
Console.WriteLine("{0} : {1} : {2}", dt1.ToUniversalTime().Hour, dt2.ToUniversalTime().Hour, dt3.ToUniversalTime().Hour); 

我得到以下输出

2012-APR-01 02:59:00.0000 +11:00
2012-APR-01 03 :00:00.0000 10:00(本地)= 2012-APR-01 02:00:00.0000 10:00(本地)
15:17:16

添加1分钟至原始日期时间使本地时间3AM,但也将偏移设置为+10小时。 向UTC日期添加1分钟并正确解析,将本地时间设置为+10 UTC偏移量的上午2点。

DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc); 

DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).AddMinutes(1); 
DateTime dt3 = new DateTime(2012, 03, 31, 16, 0, 0, DateTimeKind.Utc); 

DateTime dt1 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); 

DateTime dt2 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal).AddMinutes(1); 
DateTime dt3 = DateTime.Parse("31-Mar-2012 16:00", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); 

重复给出

2012-MAR-31 15:59:00.0000ž
2012-MAR-31 16:00:00.0000ž (Utc)= 2012-Mar-31 16:00:00.0000 Z(Utc)
15:16:16

预期

DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime(); 

DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime().AddMinutes(1); 
DateTime dt3 = new DateTime(2012, 03, 31, 16, 0, 0, DateTimeKind.Utc).ToLocalTime(); 

再次重复给原

2012-APR-01 02:59:00.0000 +11:00
2012-APR-01 03:00: 00.0000 +10:00(当地时间)= 2012-APR-01 02:00:00.0000 +10:00(当地时间)
15:17:16

任何人都可以解释一下吗?

猥亵如果我用的TimeZoneInfo从UTC到澳大利亚东部标准时间,我得到了正确的时间进行转换,但我失去的DateTime实例作为DateTime.Kind == DateTimeKind.Unspecified

偏移信息= =突出显示的其他场景

这只是简单的时间跨度添加,从夏令时结束前1分钟开始,以UTC不明确的日期开始。

DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc); 
DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime(); 

Console.WriteLine("Original in UTC  : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1); 
Console.WriteLine("Original in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.ToLocalTime()); 
Console.WriteLine("+ 1 Minute in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.AddMinutes(1).ToLocalTime()); 
Console.WriteLine("+ 1 Minute in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.AddMinutes(1)); 
Console.WriteLine("====================================================="); 
Console.WriteLine("Original in UTC  : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.ToUniversalTime()); 
Console.WriteLine("Original in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2); 
Console.WriteLine("+ 1 Minute in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.AddMinutes(1)); 
Console.WriteLine("+ 1 Minute in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.AddMinutes(1).ToUniversalTime()); 

给出了UTC

原文:2012-MAR-31十五点59分00秒。0000ž
原件本地:2012-APR-01 02:59:00.0000 11:00
+ 1分钟在本地:2012-APR-01 :00:00.0000 10:00
+ 1在一分钟UTC:2012-MAR-31 :00:00.0000ž

============================= ========================

原创于UTC:2012年3月31日15:59:00.0000 Z
原创地区:2012 -Apr-01 02:59:00.0000 +11:00
+ 1分钟i ñ地方:2012-APR-01 :00:00.0000 +10:00
+ 1分钟UTC:2012-MAR-31 :00:00.0000ž

+0

日期时间不“养”的本地偏差。我只是显示当时有效的抵消。由于dt2始终处于本地时间,因此当前时刻的视图是“真实的”。 您应该使用的DateTimeOffset,如果你想随身携带的“适用”抵消http://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx – IDisposable 2012-03-02 01:42:57

+0

......如果这是真的,那么我本来可以预期在上一场景中dt2的第三个结果是03:00:00 +11:00,但它知道DST已经完成。它正确地切换到了+10:00,但并没有消除小时。 的DateTimeOffset显示的时间为03:00:00 +11:00,这不适用于我的本地时区。 – 2012-03-02 02:22:48

+0

没有,它知道你说的这是3:00为2012/4/1,所以在那一刻偏移量是+10:00 – IDisposable 2012-03-02 03:38:43

回答

29

我相信这个问题是在条款进行转换。

你解析假设通用时间,但后来暗中转换为“本地”种 - 与2点59分59秒的值。当你要求“本地”值增加一分钟时,只需在本地值上增加一分钟,而不考虑时区。然后,当您打印偏移量时,系统正在尝试计算当地时间凌晨3点的偏移量,即+10。

那么有效,你已经有了:

  • 解析步骤1:把字符串作为通用(15:59 UTC)
  • 解析第2步:将结果转换到本地(2:59地方)
  • 增加:在本地时间,没有适用的时区值(3:00本地)
  • 格式第1步:偏移要求,所以制定出什么当地时间映射到(17:00 UTC)
  • 格式的步骤2:计算偏移作为本地和univ之间的差异ersal(+10)

是的,这一切都有点痛苦 -​​,这是我写Noda Time,那里有不同的类型“在一个区域的日期/时间”与“本地日期的主要原因/时间“(或”当地日期“或”当地时间“),并且您在任何一点使用它都很明显。

我不清楚你实际想要在这里实现什么 - 如果你可以更具体一点,我可以告诉你你会在野田时间做什么,虽然可能有一些固有的含糊之处(从本地日期/次“分区”日期/时间可以有0,1或2个结果)。

编辑:如果目的只是要记住的时区,以及即时,野田时间你想要ZonedDateTime,像这样:

using System; 
using NodaTime; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var zone = DateTimeZone.ForId("Australia/Melbourne"); 
     ZonedDateTime start = Instant.FromUtc(2012, 3, 31, 15, 59, 0) 
            .InZone(zone); 
     ZonedDateTime end = start + Duration.FromMinutes(1); 

     Console.WriteLine("{0} ({1})", start.LocalDateTime, start.Offset); 
     Console.WriteLine("{0} ({1})", end.LocalDateTime, end.Offset); 
    } 
} 

参见calendar arithmetic音符一些更多的信息,对这个。

+0

我看到您的帖子博客,并且正在编写一些关于夏时制的单元测试以验证Noda Time DST处理,但是当我从DateTime中看到这些结果时卡住了。struct – 2012-03-02 00:50:29

+0

将此答案标记为正确,因为各种讨论都强调了非DateTime算术-UTC日期时间在.NET中基本上被打破。解决这个问题的唯一方法是包装或替换DateTime – 2012-03-04 21:39:35

0

我处理这个问题的方法是把日期时间的有点像浮标 - 他们需要进行特殊处理,当你操纵他们,当你他们展示给用户,相较于。我用一个小图书馆我写来包装他们:

https://github.com/b9chris/TimeZoneInfoLib.Net

而且总是把他们当作UTC +的TimeZoneInfo。通过这种方式,您可以完成通常所做的所有典型数学运算,仅对UTC进行UTC操作,并且只在处理本地日期时间时才能以最佳格式向用户显示它们。这种结构的另一个好处是你可以更准确地向用户显示一个干净的时区,而不是每次都在TimeZoneInfo类中进行搜索。