1. 程式人生 > >日期時間字串與epoch的轉換

日期時間字串與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"