PHP

日付時刻関連で使われる書式の調査

More than 3 years have passed since last update.

以下も併せてお読みください。


日付時刻の入力書式

以下の関数やメソッドで使われます。

書式について詳しく知りたい場合はサポートする日付と時刻の書式を参照してください。特に相対的な書式の注意事項には目を通しておくべきです。

ここではマニュアルを見ても分かりづらいであろう「変更される部分」「変更されない部分」を明らかにし、また具体例を中心にピックアップしていきたいと思います。


  • タイムゾーンはphp.iniで既定された値に従います。ここでは現在のタイムゾーンがUTCまたは+00:00に既定されていると仮定します。

  • 書式中にタイムゾーンが含まれていた場合、それに従います。


  • DateTimeZoneオブジェクトによりタイムゾーンが指定された場合、それに従います。

  • 書式中のタイムゾーンとDateTimeZoneオブジェクトが同時に競合した場合、書式中のタイムゾーンが優先されます。

  • 表中の*は現在値が使用されることを意味します。


絶対指定

指定対象






タイムゾーン
書式
注記

時刻
*
*
*
23
00
00
*
23:00:00

23.00.00

23:00:00.0000000


  • PHP5.3以降限定

  • マイクロ秒7桁以下

23.00.00.0000000

T23:00:00

230000
6桁

11 pm

11:00 PM

11.00 P.M.

年月日
2015
01
02
00
00
00
*
2015-01-02
年は4桁

15-1-2
非推奨

2-1-2015
年は4桁

2.1.2015
年は4桁

2.1.15
非推奨

2015/01/02
年は4桁

2015-1-2
年は4桁

1/2/2015
年は4桁

1/2/15
非推奨

2 January 2015

2 January 15
非推奨

January 2 2015

January 2 15
非推奨

2nd January 2015

2 Jan 2015

2-Jan 2015

2-Jan-2015

年月
2015
01
01
00
00
00
*
2015-01
年は4桁

January 2015
2015 January
Jan 2015
Jan-2015

月日
*
01
02
00
00
00
*
01/02

2 January

January 2

2nd January

2 Jan

2-Jan

Jan 2

Jan-2


2015
*
*
*
*
*
*
2015
4桁


*
01
*
00
00
00
*
January

Jan

年月日, 時刻
2015
02
03
23
03
04
*
2015-02-03 23:03:04
年は4桁

2015-02-03T23:03:04

年, 週番号, 曜日番号
2015
02
03
00
00
00
*
2015-W06-2


  • 年は4桁, 週は2桁, 曜日は1桁


  • 月曜日を1日曜日を7として番号付けをし, 月曜日を週の開始とする


  • 01前日として動作する

2015W062

年, 週番号
2015
02
01
00
00
00
*
2015-W06

2015W06

年, 通算日
2015
02
03
00
00
00
*
2015.034
年は4桁, 通算日は3桁

2015034

タイムスタンプ
2015
02
03
23
03
04
UTC
@1422972184



  • DateTime::modifyで使うとタイムゾーン再設定が行われないバグがある


  • DateTime::setTimestampは整数を扱うため32ビット環境では2038年問題が発生するが、こちらは文字列で渡すためそれを回避することが出来る

タイムゾーン
(数値)

*
*
*
*
*
*
+09:00
+0900


  • 時刻に影響を及ぼさない


  • DateTime::modifyでは無視される


  • GMTは大文字

+09:00
GMT+09:00


相対指定

意味






タイムゾーン
書式
注記

現在
*
*
*
*
*
*
*
now
コンストラクタの規定値

時刻を00:00:00
*
*
*
00
00
00
*
today

midnight

時刻を12:00:00
*
*
*
12
00
00
*
today

時刻を前日の00:00:00
*
*
-1
00
00
00
*
yesterday

時刻を翌日の00:00:00
*
*
+1
00
00
00
*
tomorrow

時刻を18時15分前に
*
*
*
17
45
00
*
front of 18
タイムゾーン記述と併用すると12時間ずれるバグがある

front of 6 pm

時刻を18時15分後に
*
*
*
18
15
00
*
back of 18

back of 6 pm

時刻を1分前に
*
*
*
*
-1
*
*
-1 min

-1 mins

-1 minutes

1 min ago

previous mins

first min ago

日付を2週間後に
*
*
+14
*
*
*
*
+2 week

+2 weeks

2 weeks

next weeks next week

second weeks

weeksは必ず複数形
(序数詞+週単位のケースが特例)

日付を月の初日に
*
*
1
*
*
*
*
first day of

ofに月を続けると自然言語風らしくなる

日付を月の末日に
*
*
特殊
*
*
*
*
last day of

日付を月の2番目の木曜日に
*
*
特殊
00
00
00
*
second Thursday of

日付を月の最後の水曜日に
*
*
特殊
00
00
00
*
last Wednesday of

(今日を含む)
次の木曜日
*
*
特殊
00
00
00
*
Thursday

(今日を含まない)
次の火曜日
*
*
特殊
00
00
00
*
next Tuesday

(月曜を始まりとする)
来週の月曜日
*
*
特殊
00
00
00
*
Monday next week

(月曜を始まりとする)
先週の日曜日
*
*
特殊
00
00
00
*
Sunday previous week

タイムゾーン(名称)Asia/Tokyo
*
*
*
+9
*
*
Asia/Tokyo
Asia/Tokyo


  • 時刻に影響を及ぼす


  • DateTime::modifyでは無視される


日付時刻の入力書式定義のための書式

以下のメソッドで使われます。

コンストラクタをそのまま使う際に問題であった解釈の曖昧性を、自分で書式定義することにより解消出来る有用なメソッドです。マニュアルに十分な説明があるので、具体例の紹介は割愛します。


日付時刻の出力書式

以下の関数やメソッドで使われます。

マニュアルに十分な説明があるので、具体例の紹介は割愛します。


時間の入力書式

以下のメソッドで使われます。この書式は他とは大きく見た目が異なりますが、非常にシンプルなので理解に困ることは無いでしょう。

マニュアルに十分な説明があるので、P <*Y><*M><*D|*W> T <*H><*I><*S>の形に従う通常の書式に関する具体例の紹介は簡便に済ませます。但し、このオブジェクトにはマニュアルに記載されていない隠しプロパティが存在しており、それはDateInterval::createFromDateStringを利用して生成することによってのみ設定することが可能なものです。

PHPバージョン
隠しプロパティを直接書き換えようとしたときの挙動

HHVM

__set()メソッドがコールされ、Undefined property として例外が投げられる

5.3.27以降
5.4.17以降
5.5.0以降
全て 0 が設定される

5.3.26以前
5.4.16以前
意図通りの値が設定される

上記のとおりPHP言語の開発者サイドから「触るんじゃねーぞ!」みたいな圧力を受けている気がするので、もし可能なバージョンであったとしても自分で書き換えるのはやめておいたほうが良さそうです。


マニュアルに記載されているプロパティ


y m d h i s

書式
y
m
d
h
i
s

P2D
0
0
2
0
0
0

P2W
0
0
14
0
0
0

PT2S
0
0
0
0
0
2

P6YT5M
6
0
0
0
5
0

この方法で直接負の値を設定することは出来ません。設定するには以下の何れかを採用してください。


オブジェクト生成後に個別にプロパティを設定する

$interval = new \DateInterval('P0D');

$interval->i = -1;
$interval->s = -30;


DateInterval::createFromDateStringを利用してオブジェクトを生成する

$interval = \DateInterval::createFromDateString('-1 min -30 sec');



invert

0または1の値を取る、正負を逆転させるフラグです。以下のメソッドで結果が負になる演算を行った時、負の値をプロパティに代入する代わりにこのフラグがセットされた上で正の値が使われます。

これを手動で有効にすれば負の値を設定したときと同じ効果が得られます。


DateTimeImmutable::addでの利用

// 正を負に反転させたものを加算する

$interval = new \DateInterval('P1D');
$interval->invert = 1;
$date = (new \DateTimeImmutable('2015-03-05'))->add($interval);
echo $date->format('Y-m-d') . PHP_EOL; // 2015-03-04

// 負を正に反転させたものを加算する
$interval = \DateInterval::createFromDateString('-1 day');
$interval->invert = 1;
$date = (new \DateTimeImmutable('2015-03-05'))->add($interval);
echo $date->format('Y-m-d') . PHP_EOL; // 2015-03-06


但し、このフラグを正しく扱えるのは以下の加減算に直接関わるメソッドに限られます。


DateInterval::createFromDateString経由では単に負の値が設定されるだけで、このフラグには影響を及ぼさない

$interval = \DateInterval::createFromDateString('-1 day');

var_dump($interval->d); // int(-1)
var_dump($interval->invert); // int(0)


DatePeriodは負の間隔・invertフラグともに正しく取り扱えない

$a = new \DateTime('2015-02-15');

$b = new \DateTime('2015-02-20');
$negative_interval = \DateInterval::createFromDateString('-1 day');
$inverted_interval = new \DateInterval('P1D');
$inverted_interval->invert = 1;
$inverted_negative_interval = \DateInterval::createFromDateString('-1 day');
$inverted_negative_interval->invert = 1;

// 全て array(0) { }
var_dump(iterator_to_array(new \DatePeriod($b, $negative_interval, $a)));
var_dump(iterator_to_array(new \DatePeriod($b, $inverted_interval, $a)));
var_dump(iterator_to_array(new \DatePeriod($b, $inverted_negative_interval, $a)));

// 全てメモリーリーク
var_dump(iterator_to_array(new \DatePeriod($a, $negative_interval, $b)));
var_dump(iterator_to_array(new \DatePeriod($a, $inverted_interval, $b)));
var_dump(iterator_to_array(new \DatePeriod($a, $inverted_negative_interval, $b)));


一貫性ガン無視な実装ですが、これもまたPHPならではの趣と言えるでしょう。


days

総日数を表します。以下のメソッドで演算を行った時にのみ設定される特別なプロパティとされます。


DateTime::diffで差を求める

$a = new \DateTime('2015-02-15');

$b = new \DateTime('2014-02-15');
$interval = $a->diff($b);
var_dump($interval->invert); // int(1)
var_dump($interval->y); // int(1)
var_dump($interval->m); // int(0)
var_dump($interval->d); // int(0)
var_dump($interval->days); // int(365)


マニュアルに記載されていないプロパティ


first_last_day_of

日数が月ごとに再計算されるかどうかを示すフラグです。

do_adjust_special_early関数によって処理されます。

first_last_day_of
意味
書式例

1
今月の初日
first day of

2
翌月の末日
last day of next month


weekday weekday_behavior have_weekday_relative

曜日を扱うフラグです。

do_adjust_relative関数によって処理されます。

weekday
weekday_behavior
have_weekday_relative
意味
書式

3
1
1

(今日を含む)
次の木曜日
Wednesday

2
1
1

(今日を含まない)
次の火曜日
next Tuesday

1
2
1

(月曜を始まりとする)
今週の月曜日
Monday this week

0
2
1

(月曜を始まりとする)
先週の日曜日
Sunday previous week


special_type special_amount have_special_relative

特別な処理を行うフラグです。have_weekday_relative と複合しているものもあります。

do_adjust_special関数によって処理されます。

special_type
special_amount
have_special_relative
意味
書式

1
2
1
2日間隔の平日
second weekday

2
0
1
今月の2番目の木曜日
second Thursday of

3
0
1
今月の最後の水曜日
last Wednesday of


時間の出力書式

以下のメソッドで使われます。この書式は他とはやや見た目が異なりますが、非常にシンプルなので理解に困ることは無いでしょう。PHPを含むさまざまな言語で利用されているprintfの書式に類似した形式です。

マニュアルに十分な説明があるので、具体例の紹介は割愛します。但し1点だけ注意があります。


自分でプロパティを設定すると、書式「%R%d」「%r%d」に従う出力が、マイナス2つが連なるものになり得る

$date = new \DateInterval('P0D');

$date->d = -1;
$date->invert = 1;
echo $date->format('%R%d') . PHP_EOL; // --1
echo $date->format('%r%d') . PHP_EOL; // --1


期間の入力書式

以下のメソッドで使われます。

3種類の引数の渡し方がありますが、このうち3番目の、以下に示される$isostrとして利用されます。

public DatePeriod::__construct ( string $isostr [, int $options ] )

ISO8601に従うとありますが、実際には更に以下の制約が付きます。


日付日時に対する制約


  • 日付と時刻を両方含む必要があり、デリミタとしてTが必要である。

  • タイムゾーンはUTC固定であり、それを意味するZがサフィックスとして必要である。


反復回数に対する制約


  • 回数にはプレフィックス R が必要である。


全体としての制約

以下の何れかのフォーマットに従う必要がある。


  • 開始日時/反復間隔/終了日時

  • 開始日時/終了日時/反復間隔

  • 開始日時/反復間隔/反復回数

  • 反復回数/開始日時/反復間隔


有効な例 (終了日時を採用)

$period = new \DatePeriod('2015-01-01T00:00:00Z/P1D/2016-01-01T00:00:00Z');

var_dump(count(iterator_to_array($period))); // int(365)


有効な例 (反復回数を採用)

$period = new \DatePeriod('2015-01-01T00:00:00Z/P1D/R364');

var_dump(count(iterator_to_array($period))); // int(365)

実際、3つの引数に分けて渡すこともできるので、無理に厳しい制約に従いつつ引数を1つにしなくても特に問題はないでしょう。