日期時間字串與epoch的轉換
日期時間字串轉換成epoch
date-parse函式可以將字串轉換成秒數,這個功能相當方便。
> (setq e (date-parse "20140720 06:29" "%Y%m%d %H:%M"))
1405837740
注意
1. 06:29也可以是6:29, 加不加0都可以, 這很方便。:)
2. date-parse 接受的時間字串引數要小心時區
像本例中的沒有指明時區的就會被預設為UTC時區
3. 獲取到的秒數是epoch的值, 沒有包含時區的偏移,也是UTC時間的秒數。必須明確,epoch只有一個時區,就是UTC。
將epoch轉換成日期時間字串
這時候需要使用date函式。把上面得到的epoch:1405837740再轉回去看看
注意:
date函式接收的引數是UTC的epoch
但是返回的卻是當前時區的日期時間字串
> (date e)
"Sun Jul 20 14:29:00 2014"
這裡14:29比06:29多個8個小時,就是因為我們處於GMT+8時區。結果是正確的,只不過轉換成了不同的時區。
offset引數
date函式是先將秒數轉換成本地時區的時間,然後再看有沒有offset引數。offset引數可以幫助轉換成其他時區。
由於GMT+8 比 UTC多8小時,所以轉換到UTC需要減去8小時,因此offset引數如下
> (date 1405837740 (- (* 8 60)))
"Sun Jul 20 06:29:00 2014"
用線上站點做了對比, 結果正確.
date-parse獲得指定時區時間的epoch
前面說過時間日期字串裡也是可以表達時區的, 據說是%z或者 %Z來格式化,但是沒找到具體的例子。
如果沒有指定時區,date-parse會認為這個日期時間字串表示的是UTC時區。但是如果實際上這個字串表示的是中國時間,GMT+8呢?
比如:"Sun Jul 20 14:29:00 2014" 裡面沒有包含時區格式,但是我們知道這是北京時間。所以需要對轉換後的epoch做額外處理。下面是處理步驟:
1. date-parse函式認為這是UTC日期時間字串,轉換成epoch,記為x
2. 實際上日期時間字串表示的是GMT+8時區,如果轉換成epoch,應該記為y, y會比x小8小時。
為什麼y比x小?
解釋:一個epoch對應24個時區的日期時間字串,這是1:24的對應關係。反過來,來自24個時區的相同的值的日期時間字串對應的是24個epoch,時間越早的時區,epoch值越小。
所以需要將x減去8小時。下面的函式提供了一個引數time-offset,內部會減去它。
;; @str-date the date time value of specific time zone
;; @time-offset the offset seconds
;; @return nil if str-date is wrong
(define (datetime-str-to-epoch str-date date-format time-offset)
(let (epoch-seconds 0)
(setq epoch-seconds (catch (date-parse str-date date-format)))
(if epoch-seconds
(- epoch-seconds time-offset)
nil
)
)
)
每次先當作UTC時間字串轉換成epoch秒數,然後減去offset對應的秒數,獲得相同時間字串的實際時區對應的epoch。
下面是一個例子,利用(date)轉換回當前時區做驗證。
> (datetime-str-to-epoch "20140720 7:29" "%Y%m%d %H:%M" (* 8 3600))
1405812540
> (date 1405812540)
"Sun Jul 20 07:29:00 2014"