Firebaseを利用したアプリを作るときの時間の扱いは?

Firebaseを利用したアプリを作るときの時間の扱いは?

2020年10月30日


Firebaseを利用したアプリを作るときの時間の扱いは?

皆さんはWebサービスやWebアプリを作るときに時間の扱いはどうしていますか? Webサイトは世界中からアクセスできるので時間を扱う場合は工夫する必要があります。

例えば、ブログを投稿した時間などの場合は、余り気にならないと思います。 しかし、オンラインのサービスの予約をした場合などはどうでしょうか?

きちんと時間を管理しないと行き違いが起きる可能性があります。

時間の扱い方

日本だけで生活しているとあまり気にならない方も多いと思います。 しかし、オンラインで予約システムを作ったりする場合やメッセージをやり取りする場合は結構気を使っています。アメリカ国内でも東海岸のニューヨークと西海岸のサンフランシスコでは別の時間です。Webで時間を扱う場合いくつかのパターンがあります。

WebWebブラウザは端末の設定時間が基本

フロントエンドのコードの場合、プログラムはWebブラウザで動作しているので、通常はWebブラウザを介して端末(PCやスマホ)で設定されている時間を取得しています。 殆どの場合は、その人がいる地域の時刻に設定されているので、実際に使用していても「違和感」はない場合が殆どです。

サーバー側の時刻はUTCが基本

一方でバックエンドのサービスなど、サーバー側は通常はUTC(Coordinated Universal Time:協定世界時)を使うのが普通です。理由は簡単で、サーバー側では世界中の色々な地域からアクセスされるため、共通の時刻を使わないと色々な不具合が起きるためです。 当然、バックエンドで利用するデータベースでもUTCを使うのが普通です。

UTCの時刻は基本的には、グリニッジ標準時(GMT)と同じ時刻として認識されています。色々調べると厳密には同じ時刻ではないようですが、実用上は同じ時刻とみなしても余り問題はないように思います。なので、UTCは経度0度のイギリスのロンドンの時刻が基準になっているとみなして実用上は良いことになります。

コンピュータの世界ではUNIXタイムが標準

コンピュータの世界では、UNIX時刻という概念を使って時刻を扱うことが一般的です。 UTC自国で1970年1月1日午前0時0分0秒からの経過秒数で時刻を扱っています。よくタイムスタンプという概念であらわされているのがこの時刻です。

WebサービスやWebアプリで使う時間は?

予約システムや、メールやメッセージの送信時間、ログインした時間など正確な時間管理が必要な場合は、UNIXタイムをベースにしたタイムスタンプを使うのが一般的です。

Javascriptではタイムスタンプは以下のような記述で取得できます。

const timestamp = Date.now() / 1000;

「Date.now()」は、ミリ秒(msec)の値を返すため、1000で割る必要があります。

const timestamp = new Date().getTime() / 1000;

でも同じ結果が得られます。小数点以下を切り捨てて整数として扱いたい場合には

const timestamp = Math.floor(Date.now()/1000);

と書けば小数点以下を切り捨てて整数にしてくれます。

JavascriptやTypescriptで扱う場合はこのタイムスタンプを使うと正確な時間を扱うことができます。タイムスタンプから「Date」オブジェクトを作る場合は

const date = new Date(timestampe * 1000)で作ることができます。

この値を使えば、例えばデータベースのデータの最終更新時なども記録することができます。

Firebaseでは?

Firebaseのデータベースではタイムスタンプの独自の型を用意しています。

firebase.firestore.Timestamp

という型が用意されていて、Firebase Cloud Firestoreのドキュメントのフィールドの値としても保存することが可能です。

const fbTimestamp = firebase.firestore.FieldValue.serverTimestamp();

と記述すると、Firebaseが独自に作っているタイムスタンプを取得できます。

この型を使うと便利なのは、Firebaseコンソールで見たときに、タイムスタンプの数字ではなく、日付と時刻に変換された形で見ることができるので通所のタイムスタンプを直接保存するり使いやすくなっています。

通常のタイムスタンプの場合単純な整数値なので見ただけではどの時刻を指しているか見当がつかないので便利です。

Firebaseを利用する場合の時間管理は?

では、Javascriptで標準的にサポートされているタイムスタンプとFirebaseのタイムスタンプのどちらを使えばよいかという話になりますよね?

これは使い分ける必要があります。

Firebase関連の処理のみで時刻を扱う場合は、Firebaseが用意した型を使う方が便利な場合が当然多くなります。ところが、Firebaseと直接関係ないモジュールでデータの処理をする場合、Firebaseの型の場合、Firebaseのモジュール内のメソッドを使わないと扱いが不便なので、その場合は、一般的なタイムスタンプに変換するか、別にJavascript標準のタイムスタンプを使った方が処理がしやすくなります

データベースに入れる値はFirebaseのタイムスタンプの方が便利な場合が多いので、Firebaseのタイムスタンプを取得して、データベースからデータを読み出す際に、「toMillis()」で通常の数値のタイムスタンプに変換したデータにすると便利な場合が多いようです。

まとめ

普段は余り気にすることがない時刻ですが、WebサービスやWebアプリで時刻を扱う場合きちんと管理することがトラブルや問題を最小限にするコツです。

特に気を付けるケースは

  • 処理の実行時刻(メッセージの送信日時や処理時刻、データベースへの登録・更新時刻)
  • 予約などの時刻

です。

また、扱う時刻も

  • フロントエンドでは端末(PCやスマホ)の設定時刻
  • サーバー側ではUTC

が基本です。ブラウザーで「Date」オブジェクトを扱う場合、特に意図的にUTCの時刻を扱わない限り基本は端末の時刻で処理されます。

const date = new Date();
console.log(date.toString());

では、端末に設定されているタイムゾーンの時刻が表示されます。 UTCの時刻を表示したい場合は明示的に

const date = new Date();
console.log(date.toUTCString());

のように記述する必要があります。

時刻にまつわる障害やトラブルは意外に多いものです。 Firebaseでは、扱いやすい時刻の型を用意して時刻を扱いやすくできるように工夫しています!

Copyright(c) 2017-2020 by Silicon Valley Super Ware, all rights reserved.

コメント

このブログの人気の投稿

ユーザーインターフェースの設計

足し算以外もできるようにする

改良版足し算プログラム