日付と時刻
Nette には日付と時刻を扱うクラスが 2 つあります。Nette\Utils\DateTimeImmutable(不変。推奨)と Nette\Utils\DateTime(可変)です。どちらも PHP のネイティブクラスを継承しているので、ネイティブのメソッドはすべてそのまま使え、そこに同じ 2 つの改善が加わります。
ひとつめは、厳格であることです。PHP は 0000-00-00(-0001-11-30
に変換されます)や 2024-02-31(2024-03-02
に変換されます)のような不正な日付を黙って受け入れますが、これらのクラスは代わりに例外を投げます。
ふたつめは、夏時間(DST)の切り替え時の振る舞いを直すことです。ネイティブの PHP
では、相対的な時間を足すと(たとえば
+100 minutes)、より短い期間を足した場合(たとえば +50 minutes)よりも早い時刻になってしまう
ことがあります。これらのクラスは計算が直感どおりに働き、+100 minutes が常に
+50 minutes より大きくなるようにします。
インストール:
composer require nette/utils
不変か可変か
DateTimeImmutable クラスはバージョン 4.1.5
から使え、こちらが推奨される選択肢です。変更を行うメソッドはすべて、もとのオブジェクトを変える代わりに新しいインスタンスを返すので、保存したり関数に渡したりしたオブジェクトが思いがけず変わることはありません。
use Nette\Utils\DateTimeImmutable;
$date = new DateTimeImmutable('2024-02-26');
$next = $date->modify('+1 day');
echo $date; // 2024-02-26 00:00:00 (変わらない)
echo $next; // 2024-02-27 00:00:00 (新しいオブジェクト)
DateTime
は可変で、同じ呼び出しがオブジェクトをその場で変えます。非推奨ではありませんが、新しいコードでは不変の版が好まれます。
use Nette\Utils\DateTime;
$date = new DateTime('2024-02-26');
$date->modify('+1 day');
echo $date; // 2024-02-27 00:00:00 (もとのオブジェクトが変わった)
どちらのクラスもネイティブのものを継承しているので、format()、getTimestamp()、add()、sub()、diff()、setTimezone()、比較演算子など、すでに知っているメソッドをそのまま使えます。DateTimeImmutable
では、変更を行うメソッドはすべて新しいインスタンスを返します。このページの以降では、Nette
が上乗せしている部分だけを説明します。特に断りがなければ、どちらのクラスでも同じように働きます。
オブジェクトの生成
static from (string|int|\DateTimeInterface|null $time): static
文字列、UNIX タイムスタンプ、あるいはほかの DateTimeInterface
オブジェクトからオブジェクトを作ります。null
は現在の時刻を意味します。日付と時刻が正しくない場合は例外を投げます。
DateTimeImmutable::from(1_138_013_640); // UNIX タイムスタンプから。既定のタイムゾーンを使います
DateTimeImmutable::from('1994-02-26 04:15:32'); // 文字列から
DateTimeImmutable::from('1994-02-26'); // 日付から。時刻は 00:00:00 になります
DateTimeImmutable::from(null); // 現在の日付と時刻
static fromParts (int $year, int $month, int $day, int $hour=0, int $minute=0, float $second=0.0): static
個々の部分からオブジェクトを作ります。日付と時刻が正しくない場合は例外を投げます。
DateTimeImmutable::fromParts(1994, 2, 26, 4, 15, 32);
static createFromFormat (string $format, string $datetime, string|\DateTimeZone|null $timezone=null): static|false
ネイティブの DateTime::createFromFormat を拡張し、タイムゾーンを文字列で指定できるようにします。
DateTimeImmutable::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');
厳格な検証
不正な日付や時刻が黙って調整されることは決してなく、常に例外が投げられます。これはオブジェクトを作ったり変えたりするすべての方法、つまりコンストラクタ、from()、fromParts()、そして
setDate() と setTime() メソッドに当てはまります。
new DateTimeImmutable('2024-02-31'); // 例外(2 月に 31 日はない)
DateTimeImmutable::fromParts(2024, 2, 31); // 例外
$date->setDate(2024, 2, 31); // 例外
$date->setTime(25, 0); // 例外(25 時は存在しない)
文字列への出力と JSON
__toString() は Y-m-d H:i:s
の形式で日付と時刻を返すので、オブジェクトをそのまま出力したり連結したりできます。
echo $date; // '2017-02-03 04:15:32'
どちらのクラスも JsonSerializable を実装し、JavaScript でよく使われる ISO 8601
形式にシリアライズされます。
echo json_encode($date); // '"2017-02-03T04:15:32+01:00"'
DateTime の追加機能
可変の DateTime
には、可変のオブジェクトにだけ意味のあるメンバーがいくつかあり、それらは
DateTimeImmutable には含まれません。
その from()
メソッドは、小さな数値を現在時刻からの秒数のオフセットとしても扱います。不変の版はこの近道を意図的に持たず、そこでは数値は常に文字どおりのタイムスタンプです。
DateTime::from(42); // 現在時刻の 42 秒後
modifyClone(string $modify=''): static
は変更したコピーを返し、もとのオブジェクトはそのままにします。可変のオブジェクトで、不変の版なら
modify() がただで与えてくれるものを提供します。
$original = DateTime::from('2017-02-03');
$clone = $original->modifyClone('+1 day');
$original->format('Y-m-d'); // '2017-02-03' (変わらない)
$clone->format('Y-m-d'); // '2017-02-04'
DateTime::relativeToSeconds(string $relativeTime): int
は相対時間の文字列を秒に変換します。
DateTime::relativeToSeconds('1 minute'); // 60
DateTime::relativeToSeconds('-1 hour'); // -3600
最後に、DateTime は秒単位の長さを表す定数
MINUTE、HOUR、DAY、WEEK、MONTH、YEAR
を定義します。MONTH と YEAR
は平均値なので、おおまかな見積もりにだけ使ってください。