2012-03-01 33 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類中進行搜索。