自訂、新增windows時區

  • 148
  • 0
  • 2020-12-18

程式要轉換時間找不到時區,第三方api回傳的時區資訊是 MET( Middle European Time ), ,找了方法除了寫程式去處理例外、用第三方元件,最可靠的應該是自己新增登錄檔了。

之前碰到的,程式要轉換時間找不到時區,第三方api回傳的時區資訊是 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少了一些而已)
http://windows10dll.nirsoft.net/tzres_dll.html

真正會影響計算的值是TZI,他的值和資料結構如下:

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這個值來算,是不是歷史的會去套用到這個資料夾下的機碼我就沒有測試了),先不理他…。

打完收功!