時差のある場所の時間差を計算するプログラムを作ってみた
はじめに
ある時刻からある時刻までの時間差、たとえば「午前8時から午後3時までは何時間?」というのを計算するのは簡単で、答えはもちろん7時間となります。ところがこれは同じ地域での話であって世界には時差があり「東京の午前10時からパリの午後4時までは何時間?」を計算するのはあまり簡単ではありません。
筆者はtzdiffというコマンド(Qiitaの記事、Githubのリポジトリ)をメンテンナンスしているのですが、ある勉強会でtzdiffのバージョンアップについて説明したところ、こんなリクエストをもらいました。
「時差のある場所の時間差を知りたいんだけど、飛行機の移動時間とか」
確かに時差のある場所での時間差を求めるプログラムはあまり見たことが無いし、tzdiffのノウハウがあればすぐできそうだったので、実際に作ってみました。
コマンドの内部処理
CLIで作るので、コマンドの引数をどう指定するかを最初に考えます。必要なパラメータは基準地点の時刻とタイムゾーン、対象地点の時刻とタイムゾーンなので、実際にコマンドを使うときに指定しやすいようにそのまま次の順番に指定できるようにしました。
- 基準地点の時刻
- 基準地点のタイムゾーン
- 対象地点の時刻
- 対象地点のタイムゾーン
内部の処理としては引数で与えられた時刻を一旦正規化します。例えば10:30
が指定された場合内部では%FT%R
の形式に変換して日付まで含んだものに変換します。
$ date -d 10:30 +%FT%R
2023-08-15T10:30
この文字列形式を、タイムゾーンを指定してUNIX 時間の秒に変換します。ここでは、東京とブリュッセルの時間差(同じ時刻なので時差)を計算してみます。
$ TZ=Asia/Tokyo date -d 2023-08-15T10:30 +%s
1692063000
$ TZ=Europe/Brussels date -d 2023-08-15T10:30 +%s
1692088200
最後に差を計算して、日時文字列の形にすれば完了です。
1692088200 - 1692063000 = 25200
25200 / 3600 = 7
東京とブリュッセルの時間差は7時間(夏時間)となります。
この例ではLinux環境では標準的なGNU dateコマンドを使っていますが、筆者は普段FreeBSDを使っているため、GNU dateコマンドを前提にはできません。GNU dateでは-d
での指定する文字列を柔軟に処理してくれるのですが、FreeBSDなどのdateコマンドでは少し手間をかける必要があります。
Traveltimeの利用例
コマンド名はtraveltimeとしました。以下はgithub.comへのリンクです。
以下にtraveltimeの利用例をいくつか並べてみました。
東京を16:00に出発してロサンゼルスに10:00に到着する飛行機の飛行時間は次のようになります。
$ traveltime 16:00 Asia/Tokyo 10:00 America/Los_Angeles
10:00 Tokyo -> Los_Angeles
tzdiffと同じように、タイムゾーン名にはコンプリーションが利用できます(というかtzdiffで作ったものをそのまま流用)。
$ traveltime 16:00 Tok 10:00 Los
10:00 Tokyo -> Los_Angeles
時刻は am/pm の形でも指定できます。
$ traveltime 4:00pm Tok 10:00am Los
10:00 Tokyo -> Los_Angeles
翌日以降になる場合は、+1
や +2
を指定します
$ traveltime 11:00 Los 16:00 Tok +1
13:00 Los_Angeles -> Tokyo
ただし翌日については+1
が無くても正しい値になるよう処理しています。
$ traveltime 11:00 Los 16:00 Tok
13:00 Los_Angeles -> Tokyo
実はテストがまだ十分とは言い難いのですが、ここで例に使ったぐらいのパターンであれば問題無く動きます。
おわりに
traveltimeで指定するのは都市名では無くあくまでもタイムゾーンです。例えばアメリカのシアトルやサンフランシスコを直接指定するタイムゾーン名は用意されておらず、タイムゾーン名としてはロサンゼルスを指定することになります。ある都市のタイムゾーン名がわからない場合にtraveltimeを使うのは少々難しいのかもしれません。