不知道大家有沒有發現,在我們學習flask的過程中,post的timestamp字段添加時間時一直用的是datetime.utcnow()來獲取時間,但是它獲取的時間跟本地時間不一樣,下面我們來測試一下:
In[2]: from datetime import datetime
In[3]: now=datetime.now()
In[4]: print 'now:',now
now: 2016-11-04 09:45:31.896000
In[5]: utcnow=datetime.utcnow()
In[6]: print 'utcnow:',utcnow
utcnow: 2016-11-04 01:45:54.845000
我們將會看到utcnow獲取的時間和now獲取到的我們的本地時間不一樣。但是為什么我們用utcnow獲取時間而不是now直接獲取當地時間呢?試想一下有一天我們想把服務器遷移到不同時區的地方,那么所有數據庫中的時間戳必須修改成當地的正確時間在服務器重啟之前。但是這還有一個更重要的問題。對於不同時區的用戶很難清楚知道 blog 的發布時間因為他們看到的是在 PST 時區的時間。他們需要提前知道服務器的時區是 PST 才能做出適當的調整。顯然,這不是一個好的選擇,這是為什么開始使用我們的數據庫的時候,我們決定我們總是以 UTC 時區存儲時間戳。盡管用 UCT 時區標准化了時間戳解決了遷移服務器的問題。但是它解決不了第二個問題,日期和時間在世界上的任何地方都會以 UTC 形式呈獻給用戶。下面我們就來解決一下如何把utc時間轉換為當地市區的時間。
一、介紹moment.js
moment.js 是一個小型的,自由的,開源的 Javascript 庫,它能夠渲染日期和時間。它提供了富有想象的格式化選項。為了在我們應用程序中使用 moment.js,我們需要在模板中寫一點 Javascript。我們可以構建一個moment對象,moment對象一旦被構建之后它可以渲染各種格式的字符串
注:在所有的例子中,服務器渲染相同的 UTC 時間,在自己的網頁瀏覽器中執行不同的渲染。我們現在缺少的就是讓 moment 返回的字符串在頁面上可見。實現這個最簡單的方式就是 Javascript 的 document.write 函數:<script>document.write(moment("2012-12-31T23:55:13 Z").format('LLLL'));</script>
二、整合moment.js
(1)把下載下來的 moment.min.js 放入到 /static/js 文件夾,這樣它就能作為一個靜態文件提供給客戶端。
(2)在我們的基礎模板中添加對這個庫的引用(文件 templates/base.html):
<script src="/static/js/moment.min.js"></script>
(3)創建一個 moment.js 封裝,我們能在模版中調用這個封裝。這會節省不少時間如果我們必須修改時間戳渲染代碼,因為我們已經把它放在一個地方。(momentjs.py)
from jinja2 import Markup class momentjs(object): def __init__(self, timestamp): self.timestamp = timestamp def render(self, format): return Markup("<script>\ndocument.write(moment(\"%s\").%s);\n</script>" % (self.timestamp.strftime("%Y-%m-%dT%H:%M:%S Z"), format)) def format(self, fmt): return self.render("format(\"%s\")" % fmt) def calendar(self): return self.render("calendar()") def fromNow(self): return self.render("fromNow()")
注:ender 方法並不直接返回字符串而是把它放入了 Jinja2 提供的 Markup 對象中。原因是 Jinja2 默認情況下會自動轉義,例如,我們的 <script> 標簽是不可能到達到客戶端,因為轉義成 <script>。把字符串包裹在 Markup 對象里就是告訴 Jinja2 這個字符串是不需要轉義的。
(4)將封裝的類與jinja2綁定(microblog.py)
from momentjs import momentjs
app.jinja_env.globals['momentjs'] = momentjs
上面的代碼就是告訴 Jinja2 導入我們的類作為所有模板的一個全局變量。
(5)修改模板(user.html)
{% if user.last_seen %}<p><em>Last seen: {{momentjs(user.last_seen).calendar()}}</em></p>{% endif %}
(6)修改模板(post.html)
<table> <tr valign="top"> <td><img src="{{post.author.avatars()}}" style="width: 50px;height: 50px"></td><td><i>{{post.author.nickname}} says:</i><br>{{post.body}}<br>{{ momentjs(post.timestamp).fromNow() }}</td> </tr> </table>