日付と時刻

Nette には日付と時刻を扱うクラスが 2 つあります。Nette\Utils\DateTimeImmutable(不変。推奨)と Nette\Utils\DateTime(可変)です。どちらも PHP のネイティブクラスを継承しているので、ネイティブのメソッドはすべてそのまま使え、そこに同じ 2 つの改善が加わります。

ひとつめは、厳格であることです。PHP は 0000-00-00-0001-11-30 に変換されます)や 2024-02-312024-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 は秒単位の長さを表す定数 MINUTEHOURDAYWEEKMONTHYEAR を定義します。MONTHYEAR は平均値なので、おおまかな見積もりにだけ使ってください。

バージョン: 4.x