2009年12月30日 星期三

時區

小東西,不起眼,影響卻深遠
定義在POSIX 1003.1 section 8.3的TZ環境變數格式
格式有兩種
 1. :數個字元
  第一個字元為冒號時,之後的字串是看系統定義的
 2. std offset dst offset, rule
  當第一個字元不是冒號的情況,另一個規則表示方法為
  stdoffset[dst[offset][,start[/time],end[/time]]]
  上方表示法的中括號表示可省略。
  std:
    標準時間的時區縮寫,標準時間+偏移時間差是最基本的格式。
  dst:
    日光節約時間(Daylight Saving Time)的時區縮寫,若省略
    不寫表示不設定日光節約時間。如果有但是沒有接偏移時間
    差,則會以標準時間提早一小時的時間去設定。
  std和dst為一個3個字元以上,{TZNAME_MAX}個字元以下的
    字串。TZNAME_MAX應該是個環境變數。
  offset:
    和UTC(Coordinated Universal Time)的時間差,代表這個
    時區要加offset個小時才是UTC時間。
    格式:小時[:分鐘[:秒]]
       分和秒的欄位可省略,小時的欄位則是介於0-24之內的
       十進位數字(沒有限制位元數),分和秒為介於0-59的
       十進位數字,例如:8:30:12。offset前可以有+/-號,
       +號(可省略)表示是格林威治經線(本初子午線)的西邊
       ,-號則正好相反。
    註:這個offset和目前用的GMT+8這種格式所代表的意義正好
      相反。以台灣時區為例,台灣時區的時間為GMT的時間+8
      ,但是TZ的表示方法為CST-8,即目前的時區縮寫為CST
      ,而這個時區的本地時間減8個小時就是格林威治時間
      (GMT+0和UTC0是一樣的)。
  rule:
    用來表示哪一天開始使用日光節約時間,哪一天停用並回復標
    準時間。
    字串格式:
      date[/time],date[/time]
      date:
        表示方法有三種
        n:
         僅數字,大小介於0~365,可以用來表示有366天
         的閏年(2月29應該是第60天)
        Jn:
         第一個字元為J,之後接一個1~365的數字,無法表
         示閏年的情況,即02/28為J59,03/01一定為J60
        Mm.n.d:
         第一個字元為M,之後接的字串為m(1~12)月的
         第n(1~5)個星期d(0:星期天~6),第5個星期
         代表最後一個星期d出現的那個星期(有可能是第
         五個或是第四個), 第一個星期就代表星期d第一
         個出現的那個星期。
      time:
        time的格式和offset一樣,除了沒有+/-之外。預設的
        情況,當沒有time的欄位時,是指02:00:00

 註:目前我所知道的,真正會影響本地時間的變數為offset,std或dst
   只是提供一個時區的縮寫,網路上搜尋有人將TZ環境變數設定成
   GMT-8也是可以的,反而GMT+8怎麼樣都得不到正確的本地時間
   ,正確的說法應該是POSIX定義的TZ的格式和常用的GMT+offset
   是不同的,設定成GMT-8雖然可以取得正確的台灣時區時間,但
   是,當在linux上執行date時就可以發現出來的結果顯示時區是
   GMT,設定成CST-8則為CST。若執行date -u,就會顯示減去8
   個小時的UTC時間,而時區顯示GMT(或UTC),故推測時區縮
   寫並不會真的影響系統的本地端時間。

 註:TZ是個環境變數,在linux上用來設定時區的方式我所知道的歸納
   起來有兩種,一種是透過設定TZ環境變數
   (export TZ=......),一種是使用/etc/localtime建立連結到
   zoneinfo的目錄,在嵌入式系統的話,似乎使用前者比較容易作
   到,相關的機制仍不熟悉,暫時擱著,至於各個時區的縮寫,
   網路上可查,不多敘述

 註:時區設定的影響,在我目前使用的C language影響就是gmtime()
   和localtime()最明顯,開發中的嵌入式系統想使用TZ環境變數來
   作,但一些背景服務在TZ環境變數修改後並不會跟著更新,
   apache和MySQL是目前碰到比較棘手的問題,得重新寫設定檔,
   並且重新啟動服務,好死不死,MySQL重run會搞出更多問題。
後記:安裝作業系統時,時區的選擇擺哪麼前面不是沒有原因的