在Python的Flask架構中使用日期和時間的教程

來源:互聯網
上載者:User
時間戳記的問題

我們的微博應用的一個忽略了很久的問題就是日間和日期的顯示。

直到現在,我們在我們的User和Post對象中使用Python它自己的方式來渲染時間對象,但這並不是一個好的解決方案。

考慮下這樣的例子。我正在寫這篇文章,此時正是12月31號下午3:54。我的時區是PST(或者你們更習慣的:UTC-8)。 在Python解譯器中運行,我得到下面輸出:

>>> from datetime import datetime>>> now = datetime.now()>>> print now2012-12-31 15:54:42.915204>>> now = datetime.utcnow()>>> print now2012-12-31 23:55:13.635874

在我所在的地方,now()方法返回了正確的時間,但是now()調用返回的時間是UTC單位。


那麼,使用哪個更好呢?

如果我們用now(),所有資料庫裡的時間戳記將會與伺服器啟動並執行當地時間一致,這將會產生一些問題。

比如,如果有一天,我們需要將伺服器放到別的地方(不在一個時區),那麼在重啟伺服器之前,資料庫裡的時間都需要更新到與新地點保持一致。

還會有更為重要的問題。不同時區的使用者將會很難知道什麼時候發送郵件,如果使用者看到的是PST時區的時間,他們就很難知道郵件是什麼時候發送的,這就需要使用者根據這個時間做相應的調整。


很顯然這不是一個好的選擇,這也是我們為什麼在建立資料庫時就使用UTC時區儲存時間戳記。

在標準化時間戳記為UTC時,解決了行動服務器的問題。但是他不能解決第二個問題,資料和時間在世界上不同地方使用UTC展現給使用者。

假設一個使用者在PST時區下午3點發送了一封郵件,這封郵件立刻顯示在他面前,上面寫著11:00pm,或者更具體點(23:00)。

我寫這個文章的目的也就是讓我們的使用者不再因為資料和時間的顯示而困惑。

使用具體的時間戳記

通常的解決方案是,每一個使用者都從UTC轉化到當地的時間。這就需要我們動態變化,從而使資料庫的UTC與之保持一致。

但是我們怎麼知道使用者在哪呢?

許多網站都有一個設定版面設定他們的時區。這就需要我們添加一個新的頁面,並在表單上提供下拉框讓使用者選擇時區,使用者第一次登入的時候需要設定時區,並把它作為註冊的一部分。


這是一個正常的解決方案,但是這對於使用者來說有點累贅,使用者需要輸入一條他們已經在作業系統中配置過的資訊。所以如果我們能抓取到使用者電腦裡設定的時區那解決問題會變得更有效率。

出於安全因素,瀏覽器不允許我們進入使用者作業系統擷取資訊。即使它允許,我們也得知道在Windows,Linux,Mac,iOS,Android中從哪兒能獲得到時區,這還不包括其他非主流作業系統。

在瀏覽器中得到使用者的時區,然後通過標準的Javascript API擷取到。在Web 2.0世界中使用者允許Javascript執行(很少有網站不使用Javascript),所以通過Javascript擷取使用者時區是可行的。


我們用Javascript有兩種方式配置可用的時區:

老派的做法:當使用者第一次登入伺服器時讓瀏覽器以某種方式發送時區資訊給我們。這個可以通過Ajax調用,或者更簡單的通過meta refresh tag來實現。一旦伺服器知道了時區資訊,它就能儲存它在使用者session中,然後調整所有頁面的時間顯示。
新派的做法:不改變伺服器端的任何東西,但仍然會發送UTC時間戳記到用戶端瀏覽器。轉換UTC到本地時間的工作通過Javascript在用戶端執行。

兩種方法都是有效,但第二種更有優勢一點。瀏覽器能依照系統本地配置最好滴完成時間轉換。像上午/下午 vs 24小時制,日/月/年 vs 月/日/年 還有其他各種文化的格式,這些格式都是瀏覽器可訪問的,但伺服器就不一定了。

如果這些還不夠,那新派的做法還有一個更大的優勢,而且別人已經為我們做了這件事(moment.js要登場了)!

moment.js簡介

Moment.js 是一個小、免費、開源的Javascript庫,它將日期和事件提升到另一個等級。它提供了能想象到的所有的時間日期格式,下面就是一些。

要在我們的應用中使用moment.js就需要在我們的模板檔案中寫那麼一丟丟的Javascript代碼。我們先來通過ISO 8601 時間來建立一個moment對象。例如:通過上面Python例子的UTC時間來建立一個moment對象,就像這樣:

moment("2012-12-31T23:55:13 Z")

一旦對象被建立,它就可以被轉化成各種各樣格式類型的string。例如,將一個灰常冗長的時間顯示轉換為本地系統的時間:

moment("2012-12-31T23:55:13 Z").format('LLLL');

下面就是轉換以後的時間顯示:

Tuesday, January 1 2013 7:55 AM


這兒有更多的例子將同樣的時間戳記轉化為不同的格式:

這個類庫對轉化選項的支援不止這些。除了format()之外,它還提供了fromNow()和calendar()這些更友好的時間戳記轉化方法:

注意上面所有的例子中伺服器轉換相同的UTC時間,而你自己的本地瀏覽器則會轉換不同的時間。

最後我們補上漏掉的一點Javascript小技巧,在頁面中顯而易見的是,代碼實際上由moment返回了string類型。最簡單的完成方式是用Javascript的document.write方法:


通過使用Javascript的document.write是灰常簡單和直接的方式來產生一部分HTML代碼,然而需要注意的是這種方式有一些限制。最需要主義的一點就是document.write方法只能在document被載入時使用,當document載入完成後,它便不能修改document了。這個限制的結果就是當通過 Ajax 來載入資料時這種解決方案就失效了。

整合moment.js

這兒我們需要做一點點事把moment.js添加到我們的微部落格中.

首先,我們需要下載moment.min.js這個庫到/app/static/js這個檔案夾中,這樣它就可以作為靜態檔案為用戶端服務。

然後我們在我們的模板檔案(fileapp/templates/base.html)中添加這個庫(moment.min.js)的引用:



現在我們可以在模板檔案中添加" % (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()")

注意這兒的render方法沒有直接返回一個string類型而是返回一個由我們的模板引擎Jinja2提供的Markup對象。這麼做的原因是Jinja2預設會轉義所有string,舉例來說,我們的

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.