CakePHP4のFrozenDateで1ヵ月前、先月、今月1日、来月末の日付などを算出する方法
2024/09/27
CakePHP4のFrozenDateで1ヵ月前、今月1日、来月末などの条件を指定して日付を算出する方法
プログラムを作成する際に、下記のような特定の条件に基づいて日付を算出する場合があるかと思います。
・先月の 1日
・来月の月末
・1ヵ月前の日付
CakePHP4では「FrozenTime」「FrozenDate」という便利な関数が用意されていますので、これを使用すると簡単に算出することができますので、ご紹介します。
CakePHPで「FrozenDate」を使用して指定の日付を取得する 3つの方法
CakePHPの「FrozenDate」を使用して、例えば「今月の最終日」を取得する記述方法は下記の 3つあります。
まず最初に、use句で使用する処理を設定します。
(「FrozenDate」と「FrozenTime」の違いについては後述します。)
1 2 |
use Cake\I18n\FrozenDate; // FrozenDate を使用する場合 use Cake\I18n\FrozenTime; // FrozenTime を使用する場合 |
続けて、Controller内の Action内で下記を記述します。
1 2 3 4 5 6 7 8 9 10 |
// modify を使用する方法 $today = new FrozenDate(); $lastDay = $today->modify('last day of this month'); $firstDay = $today->modify('first day of this month'); // new FrozenDate を使用する方法 $lastDay = new FrozenDate("last day of this month"); // FrozenDate::parse を使用する方法 $lastDay = FrozenDate::parse("last day of this month"); |
いずれの場合も、結果は下記のようなオブジェクトとして取得できます。
1 2 3 4 5 |
Cake\I18n\FrozenDate::__set_state(array( 'date' => '2024-08-01 00:00:00.000000', 'timezone_type' => 3, 'timezone' => 'Asia/Tokyo', )) |
CakePHPで「FrozenDate」を使用して様々な条件を指定する方法
先のサンプルでは「last day of this month」と記述して、「今月末の日付」を取得していましたが、「last day of this month」を以下のように書き換えることで、いろいろな条件の日付を取得することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
// 今月末の日付(「last day」で月末の日付、「this month」で今月) var_export( FrozenDate::parse("last day of this month") ); // 今月の初日(「first day」で月初の日付) var_export( FrozenDate::parse("first day of this month") ); // 来月末の日付(「next month」で来月) var_export( FrozenDate::parse("last day of next month") ); // 先月末の日付(「last month」で先月) var_export( FrozenDate::parse("last day of last month") ); // 今日から 5日後(前後を「+」「-」で表記もできる) var_export( FrozenDate::parse("+5 day") ); // 今日から 2ヶ月後(前後を「+」「-」で表記もできる) var_export( FrozenDate::parse("+2 month") ); // 3年前の 3日後(「-3 year」「+3day」を組み合わせることもできる) var_export( FrozenDate::parse("-3 year +3day") ); // 3年前(「ago」を付けると過去に) var_export( FrozenDate::parse("3 year ago") ); // 3年後(「ago」を付けなければ未来に) var_export( FrozenDate::parse("3 year") ); // 3か月後の月末日 var_export( FrozenDate::parse("last day of 3 month") ); // 5か月前の初日 var_export( FrozenDate::parse("first day of -5 month") ); // 5か月前の初日(「ago」を付けると過去に) var_export( FrozenDate::parse("first day of 5 month ago") ); // 5か月後の初日(「ago」を付けなければ未来に) var_export( FrozenDate::parse("first day of 5 month") ); // 「2012-02」の月末日(「2012-02」のように具体的な月の指定もできる) var_export( FrozenDate::parse("last day of 2012-02") ); // 「2012-02-12」の月末日(「2012-02-12」のように具体的な日付の指定もできる) var_export( FrozenDate::parse("last day of 2012-02-12") ); // 今年の 2月の月末日(「February」のように月を指定する事もできる。年を指定しない場合は今年の 2月) var_export( FrozenDate::parse("last day of February") ); // 2020年 2月の月末日(「February」「2020年」を組み合わせることもできる) var_export( FrozenDate::parse("last day of February 2020") ); |
上記は「FrozenDate::parse()
」を使用して取得していますが、「$today->modify()
」でも「new FrozenDate()
」でも同じように条件を指定することができます。
また、上記は取得した値をそのまま画面に表示するために「var_export()」関数を使用しています。
「var_export()」関数については下記に記事を書いていますので、併せて参考にしてください。
「PHPのデバッグで使う print_r、var_dump、var_exportの動作の違い」
ちなみに、「FrozenDate」は日付を扱う処理ですが、時間まで扱う「FrozenTime」の方を使用する場合は、下記のように時間・分・秒を加減算することができます。
1 |
var_export( FrozenTime::parse("+5 hour +10 minute +20 second")); |
日時のオブジェクトは「i18nFormat()」を使用して表示
取得した日時のオブジェクトですが、文字列として表示する場合は、「i18nFormat()」を使用して表示したいフォーマットに変換します。
1 2 3 4 5 6 7 |
// 現在日時をオブジェクトとして生成 $today = new FrozenDate(); $todayTime = new FrozenDate(); // フォーマットを整えて出力 echo $today->i18nFormat('yyyy-MM-dd'); echo $todayTime->i18nFormat('yyyy年MM月dd日 HH:mm:ss'); |
ちなみに「$today
」に値が入っていない場合はエラーとなりますので、「$today
」に値が入っていない可能性がある場合は、下記のように値があるか否かの判定をする処理を追加しておくことをオススメします。
1 |
echo $today ? $today->i18nFormat('yyyy-MM-dd') : ""; |
CakePHPの日付、時間を扱う処理の「FrozenDate」「FrozenTime」
CakePHPの日付、時間を扱う処理には「FrozenDate」「FrozenTime」とあります。
「FrozenDate」は、年月日を扱う関数です。
「FrozenTime」は、年月日に加え、時分秒を扱う関数です。
これを曖昧に使うと結構な問題が発生します。
(実際に私がそれをやってしまっていましたので...)
では、実際に「FrozenDate」「FrozenTime」を使用して「現在」の情報を取得してみます。
1 2 3 4 5 |
$date = new FrozenDate(); var_export($date); $time = new FrozenTime(); var_export($time); |
上記のように実行すると、下記の結果が得られます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// FrozenDate の場合 Cake\I18n\FrozenDate::__set_state(array( 'date' => '2024-09-01 00:00:00.000000', 'timezone_type' => 3, 'timezone' => 'Asia/Tokyo', )) // FrozenTime の場合 Cake\I18n\FrozenTime::__set_state(array( 'date' => '2024-09-01 12:12:12.345678', 'timezone_type' => 3, 'timezone' => 'Asia/Tokyo', )) |
「FrozenDate」では「時分秒」が「0(値がない)」のに対し、「FrozenTime」ではそれらが存在します。
この「FrozenDate」と「FrozenTime」の違いをよく理解せずに、「datetime型」の「created」「modified」などの日時の項目に対して SQLの抽出条件に使用すると、想定していない結果が返ってくることがあります。
例えば、「2024-08-10」~「2024-08-15」を条件に抽出しようとする場合は「FrozenDate」を使う必要があります。
「FrozenTime」を使うと、「時分秒」を持ちますので、実行した時間によって結果が変わってくる、みたいなことが発生してしまいます。
お気を付けください...
PHPでは月末に対して実行する「+1 month」は想定の結果にならない場合がある
PHPでは月末日を基準として「+1 month」を実行したとき、想定した結果にならない場合があるようです。
これは、CakePHPの「FrozenDate」に不具合があるのではなく、PHPの処理自体がそういう仕様で動いているためです。
具体的には以下の通りです。
1 2 3 4 5 6 |
$today = new FrozenDate("2024-01-31"); var_export($today); var_export($today->modify('+1 month')); var_export($today->modify('+2 month')); var_export($today->modify('+3 month')); var_export($today->modify('+4 month')); |
上記を実行すると、以下のようになります。
1 2 3 4 5 |
'date' => '2024-01-31 00:00:00.000000' // today 'date' => '2024-03-02 00:00:00.000000' // +1 month 'date' => '2024-03-31 00:00:00.000000' // +2 month 'date' => '2024-05-01 00:00:00.000000' // +3 month 'date' => '2024-05-31 00:00:00.000000' // +4 month |
この PHPの日付の処理については、下記に詳細な仕様の説明と、対応策を書いていますので、併せて参考にしてください。
「PHPで月末から1ヶ月後「+1 month」を算出すると想定する日付にならない場合がある」
CakePHP4の関連記事
CakePHP4系でJSONレスポンスの処理ではwithStringBodyを使う。3との違い解説CakePHP4、CakePHP5の「warning: DebugKit is disabling...」の対処方法
MySQL+CakePHPのdate型、datetime型項目は「2999-12-31」までしか扱えない
CakePHP4のFrozenDateで1ヵ月前、先月、今月1日、来月末の日付などを算出する方法
CakePHP4のcake cache clear_allでPermission deniedはパーミッションの変更が必要
CakePHP4のクリエビルダーを使用してOR条件をAND条件でつなぐSQL文を作る方法
CakePHP4のController内でViewテンプレート、レイアウトの変更設定を記述する方法
CakePHP4から外部のデータベースにアクセスする方法解説
CakePHP4の数値項目は「like %10%」の部分一致検索(find select)はできない
CakePHP4でロギングスコープやログレベルを使用してログを出し分ける方法を解説
その他の「CakePHP4」に関する記事一覧
GoogleAdwords
GoogleAdwords
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
-
CakePHP4から外部のデータベースにアクセスする方法解説
CakePHP4のシステムから他のシステムのデータベースにアクセスをし、SQL文を実行する方法を解説。try-catchでエラーを取得する方法も解説。
-
-
CakePHP4、5の認証処理で認証が通らない際の確認方法と確認箇所の紹介
CakePHP4、5系の認証処理でログイン認証が通らない場合の確認方法、確認箇所を解説。ログ出力し、ステータスを確認するが、ステータスの内容も紹介。それはそのままusernameを変更する際のポイントでもある。
-
-
CakePHP4で定数の設定と呼び出し方法の解説(defineとConfigure)
CakePHP4で定数を設定、使用する方法を解説。定数定義はdefineとConfigureを使用する方法を解説。また、bootstrap.phpに直接記述する方法と別のファイルにする方法を解説。
-
-
CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も
CakePHP3で Insert … On Duplicate Key Update構文(upsert)を実行する方法を解説。バルク処理の方法も用意されているため大量処理の場合も対応可能。
-
-
MySQL+CakePHPのdate型、datetime型項目は「2999-12-31」までしか扱えない
CakePHPの日付、日時の型であるdate型、datetime型の最大値は2999-12-31となっている。MySQLは9999年までなので違いがあるので注意が必要だ。
-
-
CakePHP3でcomposerを利用してライブラリ・プラグインをインストールする方法
CakePHP3でcomposerを使ってパッケージ(ライブラリ、プラグイン)をインストールする方法の解説。PHPを使うのはCakePHP3が初めてというような方への使い方から解説。
-
-
CakePHP4、5でSELECT telephone as tel FROM usersの様にasでカラムに別名を付ける方法
CakePHP4、CakePHP5でクリエビルダーを利用してテーブルからレコードを取得する際、asを使用してカラムの別名で値を取得したい場合の対応方法を解説。また、別名にはハイフンやアスタリスクなど使用できない文字がある点も解説。
-
-
CakePHP4のフラッシュメッセージの表示場所、デザインを変更する方法を解説
CakePHP4のエラーメッセージ、完了メッセージなどを表示するフラッシュ処理の解説。Controller、レイアウトファイル、テンプレートファイルでそれぞれ処理を指定する。
-
-
Windows環境の XAMPPを利用して CakePHPの開発する際の注意点
WindowsベースにXAMPPで環境を構築しCakePHP4を利用したWebシステムを構築する際は、大文字と小文字の違いを意識する必要がある。LinuxベースのWebサーバに移動させたときに不具合で動作しないこともある。
-
-
CakePHP4の定数定義ファイルを環境変数によって本番と開発を振り分ける方法解説
CakePHP4で開発環境と本番環境とで違う設定ファイルを読み込ませて環境ごとに定数を切り替える方法を解説。Apacheのhttpd.confに環境変数を設定しそれを読み込み判別する。