今天才意識到 timezone 的處理是有那麼一點麻煩, 存放、顯示要怎麼做之類的, 之前都沒處理過這類的問題, 不過也只能先解決問題, 之後有空在來深入研究 timezone。
這兩三天在用 appengine 寫 twitter/plurk 備份的東西, 而 twitter 跟 plurk api 吐的訊息時間分別是 UTC +0000 跟 GMT, 不過剛剛網路上查了一下, 基本上、簡單來說 UTC = GMT, hmm 細節之後再來研究。所以說 twitter 或 plurk 的推訊時間都是用 UTF +0000, 不過這兩個的處理方式比較起來, twitter 簡單多了。
twitter api 的每則推訊都會有 user 的資料, 而 user 的資料當中 utc_offset 直接帶秒數, 例如我在台灣就是 28800 秒, 也就是 8 個小時, 所以就可以用以下的程式碼來把推訊的時間修正為準確, 符合 user 當地的時間
from datetime import datetime, timedelta
fmt = '%a %b %d %H:%M:%S +0000 %Y'
created_at = datetime.strptime(message['created_at'], fmt)
utc_offset = int(message['user']['utc_offset'])
local_time = created_at + timedelta(seconds=utc_offset)
twitter 時間處理滿簡單的, 直接用回傳資料的 utc_offset 然後用 timedelta 處理即可, 即使 utc_offset 是負值也沒問題。 相對之下 Plurk 那邊可以讀到是 timezone, 如: “Asia/Taipei” 這組字串, 顯然麻煩了些。
網路上找了一下, 似乎用 pytz 就可以很方便處理。 以下為 透過 pytz 用來為 plurk 處理本地時間的方式。
from datetime import datetime
from pytz import timezone
fmt = '%a, %d %b %Y %H:%M:%S GMT'
created_at = datetime.strptime(message['posted'], fmt)
user_timezone = timezone("Asia/Taipei")
local_time = created_at + user_timezone.utcoffset(created_at)
使用 pytz 真的滿方便就可以處理掉 timezone 的 time offset 問題, 不過問題來了, pytz 的 zoneinfo 就有 600 個檔案了, 然而 app engine 好像上限是 1000 個檔案, 整個吃掉一半以上。 不過似乎有 zipimport 的方式可以把檔案先壓縮在丟上去, 所以 google 幾個方式之後, 最後找到這個方式最簡單, 不過文件沒寫太清楚, 所以在這邊記錄一下。
ok, 結果討人厭的事情又來了, pytz 現在放在 launchpad 阿 … 誰裝 bazar 阿 XD 不過幸好在 pypi 可以直接抓檔案。
首先就是抓 tz_helper 跟 pytz 回來, 然後把 pytz 解開後, 找到 zoneinfo 然後把它 zip 起來, 接著就可以把 zoneinfo 目錄刪了, 最後把這三個檔案放在 app 的根目錄就好了, 像是
/app.yaml
/index.yaml
/main.py
...
/tz_helper.py
/pytz
/zoneinfo.zip
之後使用的時候直接 import tz_helper 的 timezone 來用即可。
其實現在 SNS 的時間大多都直接採用 3 hours ago 之類的方式來顯示時間, 我想最主要的原因就是, 這樣可以很容易因應世界各地使用者不同時區的問題, 而不是直接顯示這個日期。 誰知道我今天兩個方式都要有, 分別像是下面兩張圖的方式呈現, 所以就得處理 time offset 的問題。 總不能我在 5 月 5 號早上七點的推訊仍舊被記到 5 月 4 號。 而存放成台灣時間, 結果用 UTC +0000 去做 minutes ago, 顯示出來都是 0 minutes ago。
日期

times ago
