Tips
PHPで日時切り替えを実装する前に確認すること
2025-11-12
この記事が解決する状況
| あなたの状況 | 読むべきセクション |
|---|---|
| 「◯月◯日 0時に切り替えて」と依頼された | 実装前に確認すること |
| 本番で動かなかった経験がある | キャッシュ環境での選択肢 |
| WordPressで日時切り替えを実装したい | WordPress:ショートコード化 |
| キャッシュプラグインを使っている | JavaScript実装 |
「テスト環境では動いたのに本番で動かない」を経験したことがあるなら、必ず読むべき。
よくある失敗
「11月10日 0時に切り替わるはずが、翌朝まで旧バナーのままだった」
コードは正しい。でもキャッシュが効いていて、PHPが実行されていなかった。
実装前に確認すること
| 項目 | 確認方法 | NGだった場合 |
|---|---|---|
| サーバー時刻 | echo date('Y-m-d H:i:s'); | NTPで同期、またはオフセット計算 |
| ページキャッシュ | キャッシュプラグインの設定 | 該当ページを除外 |
| CDNキャッシュ | CloudflareなどのTTL設定 | 動的コンテンツとして除外 |
キャッシュが効いている環境では、PHPの日時判定は機能しない。
これを知らずに実装すると、テスト環境で動いて本番で動かない。
事故事例:タイムゾーンと時刻の罠
事例1: 9時間ズレた
状況: 0時に切り替わるはずが、9時に切り替わった
原因: サーバーのタイムゾーンがUTCだった
対処: date_default_timezone_set('Asia/Tokyo') を追加
事例2: キャンペーン終了後も表示され続けた
状況: 11月20日で終了のはずが、21日も表示されていた
原因: 終了条件を設定し忘れた(開始条件のみだった)
対処: 期間指定は必ず開始・終了両方をチェック
事例3: 本番だけ動かない
状況: ローカル・ステージングでは動く、本番だけ古いまま
原因: 本番にはページキャッシュが効いていた
対処: 該当ページをキャッシュ除外、またはJS実装に切り替え
キャッシュ環境での選択肢
| 方法 | メリット | デメリット |
|---|---|---|
| 該当ページをキャッシュ除外 | PHP判定がそのまま使える | そのページだけ遅くなる |
| JavaScriptで切り替え | キャッシュの影響を受けない | クライアント時刻依存、SEO的に不利 |
| Cronで静的ファイル生成 | 高速、確実 | 実装が複雑 |
判断基準: キャッシュを外せるならPHP、外せないならJavaScript。
PHP実装:基本パターン
<?php
date_default_timezone_set('Asia/Tokyo');
$now = date('Y-m-d H:i');
$target = '2024-11-10 00:00';
?>
<?php if ($now >= $target): ?>
<div class="banner-new">新キャンペーン実施中</div>
<?php else: ?>
<div class="banner-old">Coming Soon</div>
<?php endif; ?>
| ポイント | 理由 |
|---|---|
date_default_timezone_set | サーバーのデフォルトがUTCの可能性 |
Y-m-d H:i 形式 | 文字列比較で正しく動作する |
なぜこの書き方が安全か
Y-m-d H:i 形式は辞書順ソートと時系列が一致する。2024-11-10 00:00 は 2024-11-09 23:59 より「文字列として」大きい。これが d/m/Y 形式だと壊れる。
PHP実装:期間指定
<?php
date_default_timezone_set('Asia/Tokyo');
$now = date('Y-m-d H:i');
$start = '2024-11-10 00:00';
$end = '2024-11-20 23:59';
?>
<?php if ($now >= $start && $now <= $end): ?>
<div class="campaign-banner">期間限定セール開催中</div>
<?php endif; ?>
開始と終了を両方チェック。片方だけだと終了後も表示され続ける。
PHP実装:複数フェーズ
<?php
date_default_timezone_set('Asia/Tokyo');
$now = date('Y-m-d H:i');
?>
<?php if ($now < '2024-11-01 00:00'): ?>
<p>予告</p>
<?php elseif ($now < '2024-11-10 00:00'): ?>
<p>エントリー受付中</p>
<?php elseif ($now < '2024-11-20 00:00'): ?>
<p>投票期間</p>
<?php else: ?>
<p>結果発表</p>
<?php endif; ?>
上から順に評価される。条件の順序を間違えると意図しない表示になる。
WordPress:ショートコード化
再利用するならショートコードにしておく。
// functions.php
function timed_content_shortcode($atts, $content = null) {
date_default_timezone_set('Asia/Tokyo');
$atts = shortcode_atts([
'start' => '',
'end' => '',
], $atts);
$now = date('Y-m-d H:i');
if (!empty($atts['start']) && $now < $atts['start']) {
return '';
}
if (!empty($atts['end']) && $now > $atts['end']) {
return '';
}
return do_shortcode($content);
}
add_shortcode('timed', 'timed_content_shortcode');
投稿・固定ページで使用:
[timed start="2024-11-10 00:00" end="2024-11-20 23:59"]
期間限定コンテンツ
[/timed]
WordPressでの注意点
WordPressは wp_timezone() でサイト設定のタイムゾーンを取得できる。管理画面の「設定 → 一般 → タイムゾーン」と一致させたい場合:
function timed_content_shortcode($atts, $content = null) {
$timezone = wp_timezone();
$now = (new DateTime('now', $timezone))->format('Y-m-d H:i');
// ...
}
JavaScript実装(キャッシュ環境用)
PHPが使えない場合の代替。
<div id="timed-content" data-start="2024-11-10T00:00:00+09:00">
<div class="before">Coming Soon</div>
<div class="after" style="display:none;">公開中</div>
</div>
<script>
(function() {
const container = document.getElementById('timed-content');
const start = new Date(container.dataset.start);
const now = new Date();
if (now >= start) {
container.querySelector('.before').style.display = 'none';
container.querySelector('.after').style.display = 'block';
}
})();
</script>
注意: クライアント側の時刻に依存する。厳密な制御には不向き。
JSの限界
- ユーザーのPC時刻がズレていたら意図しない表示になる
- 「厳密に0時に切り替わる必要がある」案件には不向き
- SEO観点では、クローラーがJSを実行しないと古いコンテンツがインデックスされる
本番前チェックリスト
| 項目 | 確認 |
|---|---|
| サーバー時刻は正しいか | echo date('Y-m-d H:i:s'); |
| タイムゾーン設定はあるか | date_default_timezone_set('Asia/Tokyo') |
| キャッシュ除外設定はあるか | プラグイン・CDNの設定 |
| 終了日時も設定したか | 開始だけだと永久表示 |
| テスト方法は決めたか | 日時を変えてテストできるか |
| ロールバック手順はあるか | 動かなかった時の対処 |
まとめ
- キャッシュ環境ではPHP日時判定が効かない
- 実装前にキャッシュ設定を確認、除外できるか判断
- タイムゾーンとサーバー時刻の確認は必須
- 期間指定は開始・終了の両方をチェック
- キャッシュを外せないならJavaScriptで対応
Y-m-d H:i形式を使えば文字列比較で正しく動く
関連記事
- WP-Cronが動かない原因と対処 — 予約投稿が動かない問題
- お問い合わせフォームが届かない原因の特定方法 — WordPressのメールトラブル