2013-03-18 135 views
5

我正在開發運行24/7/365全天候GPS設備報告的軟件。部分報告輸出要求我們將存儲的數據庫時間(保留在中央標準時間)轉換爲用戶計時器(任何請求的時區)。當人們每天運行兩次報告時,我們會遇到DST問題,這些報告會在時間更改之前開始並結束。它未能在一個行:轉換DayLight附近的日期時間節省時間?

return TimeZoneInfo.ConvertTime(dateToConvert, DatabaseTime, UserTime); 

dateToConvert是要轉換一個DateTimeDatabaseTimeUserTime都是TimeZoneInfo對象。我沒有做任何棘手或複雜的事情,但靠近DST時間更改的日期時間會引發異常。例如3/10/2013 2:02:11 AM即使它正在從中央時間「轉換」到中央時間。

在DST時間變化附近處理DateTimes的最佳方法是什麼?

+3

這可能更大修的比你想要的,但它可能是更好的儲存所有的日期/格林尼治標準時間(因爲CST經歷了DST的變化,也有規模不連續性是在格林尼治標準時間不在那裏),只有轉換爲顯示目的(以及可能轉換輸入參數)。 – twalberg 2013-03-18 17:23:48

+0

如果我從頭開始,我肯定會這樣做。我喜歡這些數據儘可能中立的想法,我認爲這將是實現這一目標的方式。 – 2013-03-18 17:28:07

+0

只是爲了確認:是否有可能在數據庫中存儲'3/10/2013 2:02:11 AM',因爲它在跳過的小時內? – 2013-03-18 17:31:21

回答

1

轉換應該正常工作,因爲時間不是真正的垃圾,正如漢斯所說,而只是沒有調整(我剛剛發明的一個術語)。 3/10/2013 2:02:11 AM CDT == 3/10/2013 8:02:11 AM UTC == 3/10/2013 3:02:11 AM CDT ......它們都是語義等價的。如果你不相信我,請在timeanddate.com處進行轉換,看看他們是否相等(儘管他們的計算器爲四捨五入到最接近的5分鐘)。無論.NET代碼是否允許這種語義等價,我還沒有嘗試過,因爲我目前不在我的開發箱前面。

更新#1:

運行下面的代碼設置爲CST時區的計算機上:

using System; 

namespace TimeZoneSample 
{ 
    public static class Program 
    { 
     public static void Main() 
     { 
      DateTime t = DateTime.Parse("3/10/2013 2:02:11 AM"); 
      Console.WriteLine(t); 
      Console.WriteLine(t.ToUniversalTime()); 
      Console.WriteLine(t.ToUniversalTime().ToLocalTime()); 
     } 
    } 
} 

我們得到以下控制檯輸出:

3/10/2013 2:02:11 AM 
3/10/2013 8:02:11 AM 
3/10/2013 3:02:11 AM 

證明我原來的解釋是正確的。 狴ERAT demonstrandum

+0

我同意並且完全和你在一起,但.Net的DateTime似乎並沒有這樣工作。 – 2013-03-18 19:07:43

+0

按照您的編輯,如果我暫停調試器,將其插入觀察名單,但是當代碼實際上試圖執行'返回TimeZoneInfo.ConvertTime的作品(dateToConvert.ToUniversalTime()ToLocalTime(),DatabaseTime,UserTime); '我得到一個錯誤,說'DatabaseTime'需要'TimeZoneInfo.Local'。我不知道這是否是我們系統中可以接受的假設。 – 2013-03-18 21:52:17

+0

我和我的團隊交談過。事實證明,自從我們託管自己的服務器以來,這是一個足夠安全的假設。 – 2013-03-18 22:12:16

3

我遇到了這個問題。我通過添加新的GMT時間列來修復它。這使得應用程序可以使用原始數據和任何修補程序與GMT一起工作。然後我改變了應用程序,以便任何夏令時存在問題的代碼都可以訪問這個新列。另外,隨着時間的推移,我重新將用於計算的代碼重新指向這個新列,使顯示器與舊列一起工作。這不是優雅的,但它的工作原理很簡單。

4

你的數據庫中有垃圾,3/10/2013 2:02:11 AM從來不存在。那天凌晨1點59分那天凌晨3點,鐘錶移動了一個小時。 .NET不會忍受那個垃圾日期。

您將需要了解垃圾時間戳記如何在您的dbase中結束。很明顯,將時間從一個時區轉換到另一個時區忽略夏令時規則,比如在一個時間段內活動,而不是在另一個時間活動,這很可能是垃圾的來源。如果你不能修復你的dbase使用UTC,那麼至少在你的代碼中使用它。首先在一個時區前往UTC,然後再返回到另一個時區的當地時間。使用TimeZoneInfo類,ConvertTimeFrom/ToUtc方法。

+0

後端代碼,採用GPS條目並將其推入數據庫都寫在VB6(我討厭它,我不能等到我們把我們的C#的變化),我想,也許我們VB6沒有給予足夠在計算過程中注意DST。 – 2013-03-18 18:16:03

+0

是的,VB6後端很可能不會這樣做。 – 2013-03-18 18:51:24

1

我會按照其他的答案中的一個,如果這是在所有可能的 - 要正確地解決這個問題。如果在秋季過渡期間你的時間不正確,它不會產生異常,它只會隨機關閉一個小時。

有一種解決方法可以讓您擺脫目前的困境。由於這只是在春季的缺失小時內會導致異常,因此您可以捕捉異常並在重複轉換之前添加一小時。

+0

作爲一個快速解決方案,我在過去的半個小時裏一直在玩弄它。 – 2013-03-18 21:04:54