Nic Lin's Blog

喜歡在地上打滾的 Rails Developer

Rails 要用 Time.zone.now 還是 Time.now

我自己主觀喜歡用 Time.zone.now

原因

  1. 在 Rails best practice 裡有提到
  2. 把時區的設定放在 application layer 而不是機器上
  • Time.now 抓的是機器時間
  • Time.zone.now 抓的是 Rails 下設定的 config.time_zone 時區

如果機器沒設定好,不管是 development / production 又或是多機器的部分,就有可能顯示不一樣。

而時間的格式應該仰賴在 application layer, 這樣更容易保持一致性

可以在本機測試以下範例

  1. config/application.rb 中的時區替換為 config.time_zone = 'Europe/Istanbul'
  2. 啟動 Rails console
  3. 輸入 Time.now / Time.zone.now 查看
# 我已經改為非 asia 時區,但他抓的是我機器上的時區
pry(main)> Time.now
=> 2019-06-26 14:24:08 +0800

# 下面這個應該才是對的
pry(main)> Time.zone.now
=> Wed, 26 Jun 2019 09:24:05 +03 +03:00

但是寫進 database 時都是會轉 UTC,其實你不管用 Time.now / Time.zone.now 其實都可以。

如果你機器上設定的時區和 Rails 裡一樣,那麼這兩個方法其實出來的結果是一致的。

那為什麼還是推薦用 Time.zone.now ?

舉個例子,也許不會發生,但可以想想

如果機器有很多台,可能某一台在當初開的時候沒設定好時區。

那麼在 database 寫入時,不用擔心,不會有事,不管 zone 是什麼,都會寫入當下時間並轉為 UTC,因為 db 不負責記錄 zone。

但是顯示的部分,可能就會有雷。

比方說

A 機器被設錯了,是歐洲時區。 B 機器是對的,是亞洲時區。

你有一個頁面是透過 load balance 進來,所以用戶有可能連到 A 也有可能是 B

你有頁面的邏輯是顯示現在的時間 + 30.mintues。

可以想一下 A 和 B 機器分別在頁面上顯示的結果

  • Time.now + 30.mintues
  • Time.zone.now + 30.mintues

定然是不一樣的吧?

所以如果你不想區分,model 寫 Time.now而 View / API output 寫 Time.zone.now

那我認為就統一寫 Time.zone.now 並把 Rails 時區設定好,大家就更方便做事囉。

參考資源

comments powered by Disqus