今天碰到一個問題,程式要轉換時間的時候找不到時區,第三方程式丟過來的時區資訊是MET( Middle European Time ),找了方法除了寫程式去處理例外、用第三方元件,最可靠的應該是下面這個方法了。
下圖就是找不到時區時會丟出的錯誤:
圖一 |
要做的是自行新增登錄檔,他位於 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\這個資料夾裡面,到這個資料夾下就可以看到很多時區的資訊。
圖二 |
點一個來看,有下面這些登錄值:
圖三 |
仿照他做一個新的,Display、Dlt和Std是描述,是字串值,直接編輯,沒問題。
再來三個MUI開頭的值,是用tzres.dll中的resource檔,後面的數字是resource的key值,目前沒辦法新增,但這個不影響轉換,只影響時區資訊的顯示,
例如:
圖四 |
在cmd中打上指令tzutil /l (列出本機上所有時區資訊),可以看到我新增的兩個時區VIncent time、Vincent
Test Time中面的描述跟上面的Central Europe Standard
Time一樣,就是因為MUI開頭的值,後面dll的字串值用的跟Central Europe Standard
Time相同,好在他不影響轉換的計算,所以沒關係。
resource的key和value可以參考下面這個網站(這win10的,win7以前的要找自己另外找,不過大同小異啦,就是比win10少了一些而已)
圖五 |
typedef struct _REG_TZI_FORMAT { LONG Bias; LONG StandardBias; LONG DaylightBias; SYSTEMTIME StandardDate; SYSTEMTIME DaylightDate; } REG_TZI_FORMAT;typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME;
WORD佔2Byte,SYSTEMTIME總共2*8 = 16Byte,
LONG佔4Byte,所以TZI_FORMAT佔了4*3 + 16*2 = 44 Byte符合上面值共44Byte
計笡可以看這個網頁,各欄位的詳細定義
TIME_ZONE_INFORMATION structure
看起來要計算很麻煩,但其實可以不用計算,因為大部份時區都有,所以直接找一個位於相同時區的,將他的TZI值照著寫進去就可以了。
上面這些東西最初是從這裡來的,也可以直接去看這個網頁
Exploring Windows Time Zones with System.TimeZoneInfo [Josh Free]
最後在圖二中,其實可以看到有些時區還有子資料夾[Dynamic DST],這個應該是記錄歷史的日光節約時間的,有變更都是windows update做的,我的目的只是要現在轉換成功,而且我做的這個,剛好沒有日光節約的間,有日光節約時間轉換也ok,(應該主要是參照TZI這個值來算,是不是歷史的會去套用到這個資料夾下的機碼我就沒有測試了),先不理他…。
沒有留言:
張貼留言