XE には DateUtils.TTimeZone クラスが新設されており、これを用いるとタイムゾーンを考慮した日付の計算が楽になる。
シチュエーションとしては…そうだな、例えば DOM 操作を行う際に JavaScript の getTime() 相当のものが必要となったとする。さぁ、どうやって実装しようか?ちなみにgetTime() は "1970/01/01 00:00:00:000 からのミリ秒数を返す関数" だ。
DateUtils.DateTimeToUnix() を使う?惜しい。DateTimeToUnix() は "1970/01/01 00:00:00 からの秒数を返す関数" だ。確かにこれを 1,000 倍すればいいのだろうが、当然下 3 桁が 0 になってしまい getTime() を正確に再現したものとは言えない…そもそもタイムゾーンが考慮されないしね。
そこで DateUtils.TTimeZone クラスだ。
uses ..., DateUtils;
function JS_GetTime(ADate: TDateTime): Int64; begin result := MilliSecondsBetween(TTimeZone.Local.ToLocalTime(EncodeDate(1970, 1, 1)), ADate); end;
XE 以降ならこのようにして JavaScript の getTime() 相当の関数が作れる。ヘルプにもあるように、TTimeZone クラスはインスタンス化せずに "TTimeZone.Local.ほにゃらら()" のようにして使う。
当然の事だが、この関数はタイムゾーンを考慮している。これを日本国内で実行すると、"1970/01/01 09:00 (JST)" からの経過ミリ秒を返す (つまり UTC での経過ミリ秒)。日付時刻型に "9 時間足す" という処理は難しくないが、その "9 時間の差を求める" のは XE より以前の Delphi では少し面倒だ。
Note:
具体的な "UTC とローカル時刻との時差を求める方法" は、
Mr.XRAY 氏のサイトの "816_ファイルのプロパティ" 内に UTCTimeDateTimeOffset() という関数の実装がある。
タイムゾーンを考慮しないのであれば、
uses ..., Dateutils;
function Local_GetTime(ADate: TDateTime): Int64; begin result := MilliSecondsBetween(EncodeDate(1970, 1, 1), ADate); end;
単純にこれでいいのだが、Web 関係だと大抵タイムゾーンが絡んでくるので注意が必要だ。DateUtils 名前空間には TTimeZone クラス以外にも便利な関数が揃っているので、XE ユーザ以外の方も一度 ヘルプを精査してみる事をオススメする。
See Also:
[System.DateUtils.TTimeZone (DocWiki)]
http://docwiki.embarcadero.com/Libraries/ja/System.DateUtils.TTimeZone
[816_ファイルのプロパティ (Mr.XRAY)]
http://mrxray.on.coocan.jp/Delphi/plSamples/816_FilePropety.htm
|