日付と時刻の正しい表現方法

日付を表現したい場合は YYYY-MM-DD たとえば
2008-05-16

時刻を表現したい場合は hh:mm:ss たとえば
11:25:30

日本時間であることをわかりやすく明記したい場合は
11:25:30+09:00
もちろんグリニッジ標準時からの時差がプラス9時間、の意。 (「JST」と書けとかUTCならZだとかそういう細かい話は省略。)

日付と時刻を両方表現したい場合は
2008-05-16T11:25:30+09:00
つまり日付と時刻をTでつなげる。

これが世界的スタンダードとしてISO8601とRFC3339に定められた日付と時刻の表現方法。 有名どころの言語やらデータベースその他ミドルウェアはすべてこれに沿った表記を解釈し入出力できるようになっている。 プログラマのみなさんは覚えておいて損はないというか絶対覚えておいたほうがいい。 できればプログラマに発注する側の人間も覚えておきましょう。

日付がスラッシュ区切り(YYYY/MM/DD)だったりするソフトやらライブラリやらが巷に散見されるが、まったくおすすめできない。実は筆者がいまそういうコードを使う羽目になっているのだが、使いづらいのなんのって。。。

日付と時刻という、どう書いてもよさそうな超基本的データフォーマットであっても、きちんとスタンダードに沿うことが、ソフトを使いやすく&使われやすくするための第一歩だ。

see also:

追記:

日付と時刻をTで結ぶ方式は普及していない[文系大学的IT系の悲哀]という記事が出ている。 経験則というものは人それぞれなのでそれはそれでかまわないが、「PostgreSQLはYYYY-MM-DDTHH:MM:SS 形式を考慮してない」といった明らかに誤った認識はpgsqlファンとしてはつっこまざるをえない。

ものはついでなので、いくつか例を挙げて説明を加えておこう。

2008-05-16T13:45:23 よりも 2008-05-16 13:45:23 のほうが読みやすくね?

同意である。人間の眼の観点から言うとそう。 しかしここではどっちかいうとコンピュータ視点であり、かつできればの範囲で人間にもわかりやすく、というのが主眼であることをご理解いただきたく。

それから、日付と時刻をTでつなぐということ云々よりも、 年月日は/じゃなくて-でつなぐものだ、ということを知らなかった人のほうが多いんじゃないかと思われる。

なお、「T」なんてよくわかんねーからやだ、と言っている人のブログのrssフィードには <pubdate>2008-05-16T13:45:23</pubdate>とあったりすることを忘れてはならない。あなたもお世話になっているのだ。

JavaScriptはiso8601形式の日付を理解できない

そうなんですよ。なんでそんなことになったのやら。忘れてたとしか思えん。

var timestamp = Date.parse('2008-05-16T11:25:30+09:00');
window.alert(new Date(timestamp));
ってやってもうまく動いてくれない。
var timestamp = Date.parse('2008/05/16 23:59:59"');
window.alert(new Date(timestamp));
ならOK。

でもそれじゃ不便だよねってことで、 [JSAN] Date.W3CDTF - ISO-8601日時フォーマット対応JavaScriptクラスなんてのを作ってる人もいる。 筆者もお世話になってる。

なお、ECMAScript(JavaScriptの仕様の土台?というべきか)の次のバージョンではiso8601形式がサポートされることになっている。

http://www.ecmascript.org/es4/spec/overview.pdf より抜粋

The Date class has been upgraded in several ways. Chiefly, there are methods for producing and consuming ISO-8601 format time strings, and Date instances keep track of their age with nanosecond precision and can be used as low-cost high-precision timers.

EcmaScriptバージョン4を搭載するブラウザが普及するのって何年後よ?とかいう野暮はいわない方向で。

perlの場合

とりあえずHTTP::Date使ってみた。

$ cat test.pl
#!/usr/bin/perl
use HTTP::Date;
my $t = HTTP::Date::str2time('2008-05-16T08:23:45+09:00');
print HTTP::Date::time2iso($t)."\n";

$ perl test.pl
2008-05-16 08:23:45
こんな感じ。入力は対応しているが出力の際は「T」は無いらしい。残念。 HTTP::Date - date conversion routines - search.cpan.orgを参照のこと。

PHPの場合

$ cat test.php
<?php
echo date('c',strtotime('2008-05-13T02:45:23+09:00'));
?>

$ php test.php
2008-05-13T02:45:23+09:00
こんな感じで入力も出力も可能。なお、 PHP: strtotime - Manualには、対応しているフォーマットとしてなぜかGNU tarコマンドのマニュアルの一部にリンクが張られており、そこにはISO8601フォーマットに関する言及は無い。しかし見てのとおり動き的にはちゃんと対応している。これは「ソースは書かれているがマニュアルの更新は滞っている」というOSSにありがちなパターンの典型である。

M$製品の場合:

Ms-Officeの寡占状態にあるデスクトップのビジネスアプリ市場において標準への準拠なんてされるわけがない(笑)。当然、ExcelやAccessでは2008-05-16T08:23:45+09:00なんてのは入力しても期待通りには動かない。

が、oracleやらmysqlやらpostgresqlに押されっぱなしのサーバー市場においてはMSは標準という錦の御旗に従順である。

ISO 8601 形式 - SQL Server 2005 Books Online (2007 年 9 月)

Microsoft SQL Server 2005 では、ISO 8601 形式を使用して日付と時刻のデータを指定できます。 形式は次のようになります。
yyyy-mm-ddThh:mm:ss[.mmm]

PostgreSQLの場合

testdb=> select cast('2008-05-13T12:04:56+09:00' as timestamp with time zone);
      timestamptz       
------------------------
 2008-05-13 12:04:56+09
(1 row)
ちゃんとTIMSETAMP型にキャストできる。

mysqlの場合

mysql> select cast('2008-02-03T04:23:45+09:00' as datetime);
+-----------------------------------------------+
| cast('2008-02-03T04:23:45+09:00' as datetime) |
+-----------------------------------------------+
| 2008-02-03 04:23:45                           | 
+-----------------------------------------------+
1 row in set, 1 warning (0.00 sec)

こうしてみると、YYYY-MM-DDThh:mm:ss+09:00の形式の入力には対応しているものの出力には対応していないケースが多いようだ。残念。まあ入力さえできれば出力はどうにでもなるものなのでいいのかな。

トラックバックURL

このエントリーのトラックバックURL:
http://www.ywcafe.net/mt/mt-tb.cgi/841

コメントする

(初めてのコメントの時は、コメントが表示されるためにこのブログのオーナーの承認が必要になることがあります。承認されるまでコメントは表示されませんのでしばらくお待ちください)


画像の中に見える文字を入力してください。