日付と時刻をTで繋ぐ表記方法

日付と時刻を両方表現したい場合は2008-05-16T11:25:30+09:00
つまり日付と時刻をTでつなげる。
これが世界的スタンダードとしてISO8601とRFC3339に定められた日付と時刻の表現方法。
有名どころの言語やらデータベースその他ミドルウェアはすべてこれに沿った表記を解釈し入出力できるようになっている。
プログラマのみなさんは覚えておいて損はないというか絶対覚えておいたほうがいい。
日付がスラッシュ区切り(YYYY/MM/DD)だったりするソフトやらライブラリやらが巷に散見されるが、まったくおすすめできない。

http://neta.ywcafe.net/000851.html

というわけで普段使っている言語でどの程度対応しているか調べてみた。
ISO8601とRFC3339があがってるけどW3CDTFも検索キーワードに入れた方が良さそう。
ちなみに、HTTP,SMTP等で使われているのはRFC2822、UNIX系で使われているのはctimeフォーマット
各フォーマットでの2001年2月3日4時5分6秒

ISO8601 RFC3339 W3CDTF 2001-02-03T04:05:06+09:00
RFC2822 Sat, 03 Feb 2001 04:05:06 +0900
ctime Sat Feb 03 04:05:06 JST 2001

PHPの場合

PHP5ではデフォルトで読み込みも出力も対応。
ちなみに'r'を指定するとRFC2822での出力も出来る。

strtotime('2001-02-03T04:05:06+09:00') => 981140706 
date('c',strtotime('2001-02-03T04:05:06+09:00')) => 2001-02-03T04:05:06+09:00
date('r',strtotime('2001-02-03T04:05:06+09:00')) => Sat, 03 Feb 2001 04:05:06 +0900

Rubyの場合

'time'を読み込むと使えるようになる。
parseメソッドだとタイムゾーンも引き継ぐが、専用のiso8601メソッドだとなぜかUTCになってしまう。
そのときはlocaltimeメソッドで変換してやるとなおる。
ちなみにrfc2822またはrfc822メソッドでRFC2822での出力も出来る。

require 'time'
Time.parse('2001-02-03T04:05:06+09:00') => Sat Feb 03 04:05:06 JST 2001
Time.parse('2001-02-03T04:05:06+09:00').iso8601 => "2001-02-03T04:05:06+09:00"
Time.iso8601('2001-02-03T04:05:06+09:00').iso8601 => "2001-02-02T19:05:06Z"
Time.iso8601('2001-02-03T04:05:06+09:00').localtime.iso8601 => "2001-02-03T04:05:06+09:00"
Time.parse('2001-02-03T04:05:06+09:00').rfc2822 => "Sat, 03 Feb 2001 04:05:06 +0900"

Gaucheの場合

srfi-19を読み込むと使えるようになる。
date->stringでは~4というフォーマットが使える。
しかしstring->dateでのテンプレートには使えない。そもそも違うルールなのかもしれないがどう指定するのかわからず。
make-dateのゾーンオフセットは時ではなく秒で与えるので注意。
ちなみに~zはRFC-2822スタイルのタイムゾーンと書いてあるようにタイムゾーンのみ。RFC-2822スタイルで日付全体を出力するものはなさそう。

(use srfi-19)
(string->date "2001-02-03T04:05:06+09:00" "~4") => bad date format string: " >>>~<<< 4"
(date->string (make-date 0 6 5 4 3 2 2001 (* 60 60 9)) "~4") => 2001-02-03T04:05:06+0900
(date->string (make-date 0 6 5 4 3 2 2001 (* 60 60 9)) "~z") => +0900

JavaScriptの場合

読み込みはそもそもハイフン区切りではダメで、スラッシュ区切りにしないと受け付けてくれない。
出力もデフォルトでは出来ない。
prototype.jsはもはや標準装備ということなら、toJSON()を使えばUTC決めうちは出来る。
ただし、toJSON()で得られた結果をevalJSON()にかけても""がはずれるだけでDateオブジェクトには戻らない…。
ちなみに、toUTCString()またはtoGMTString()を使うと、UTC決めうちでRFC2822での出力が出来る。

new Date('2001-02-03T04:05:06+09:00') => Invalid Date
new Date('2001-02-03 04:05:06') => Invalid Date
new Date('2001/02/03 04:05:06') => Sat Feb 03 2001 04:05:06 GMT+0900
new Date('2001/02/03 04:05:06').toJSON() => "2001-02-02T19:05:06Z"
new Date('2001/02/03 04:05:06').toJSON().evalJSON() => 2001-02-02T19:05:06Z
new Date('2001/02/03 04:05:06').toUTCString() => Fri, 02 Feb 2001 19:05:06 GMT

dateコマンドの場合

区切りにTを使うとエラーになるがスペースで区切れば読み込んでくれる。
出力も--rfc-3339=secondsを指定すれば出来る。こっちも区切りはTではなくてスペース。
なお、--rfc-3339=dateで日付だけ、--rfc-3339=nsでナノセカンドまでという指定もある。
ちなみに、-Rまたは--rfc-2822でRFC2822での出力も出来る。

% date -d '2001-02-03T04:05:06+09:00'
date: invalid date `2001-02-03T04:05:06+09:00'
% date -d '2001-02-03 04:05:06+09:00'
2001年  2月  3日 土曜日 04:05:06 JST
% LANG=C date -d '2001-02-03 04:05:06+09:00'
Sat Feb  3 04:05:06 JST 2001
% date --rfc-3339=seconds -d '2001-02-03 04:05:06+09:00'
2001-02-03 04:05:06+09:00
% date -R -d '2001-02-03 04:05:06+09:00'
Sat, 03 Feb 2001 04:05:06 +0900