Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】DateTime::sub()メソッドの使い方

subメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

subメソッドは、DateTimeオブジェクトから指定された期間を減算するメソッドです。このメソッドは、日付や時刻の計算において、現在の日時や特定の日時から過去の日時を求めたい場合に非常に役立ちます。例えば、「現在の日時から5日前の日時」や「特定の日付から3ヶ月前の日時」を簡単に算出することができます。

subメソッドの唯一の引数には、減算したい期間を定義したDateIntervalオブジェクトを指定します。DateIntervalオブジェクトは、年、月、日、時間、分、秒といった時間の差を表現するために使用されます。

このメソッドの大きな特徴として、呼び出し元のDateTimeオブジェクト自体を変更する(破壊的な操作である)点が挙げられます。そのため、元のDateTimeオブジェクトを変更したくない場合は、事前にクローンを作成するか、DateTimeImmutableクラスの使用を検討してください。メソッドが正常に実行されると、減算された日時を持つDateTimeオブジェクトが返されます。これにより、メソッドチェーンとしてさらに他のDateTimeメソッドと組み合わせて使用することも可能です。

日付と時刻を扱うアプリケーション開発において、特定の期間を遡る計算が必要な場面で頻繁に利用されます。

構文(syntax)

1<?php
2// 現在の日時を表すDateTimeオブジェクトを作成します。
3$date = new DateTime('2023-01-01 12:00:00');
4
5// 減算したい期間をDateIntervalオブジェクトで定義します。
6// 例: 1ヶ月と2週間と3日と4時間と5分と6秒
7$interval = new DateInterval('P1M2W3DT4H5M6S');
8
9// subメソッドを使用して、DateTimeオブジェクトから指定した期間を減算します。
10$date->sub($interval);
11
12// 結果の日時を表示します。
13echo $date->format('Y-m-d H:i:s');
14?>

引数(parameters)

DateInterval $interval

  • DateInterval $interval: 引き算する期間を表すDateIntervalオブジェクト

戻り値(return)

DateTime|false

指定された期間(DateInterval オブジェクトで表される)を元の DateTime オブジェクトから減算した新しい DateTime オブジェクトを返します。減算に失敗した場合は false を返します。

サンプルコード

PHP DateTime::subで日付を減算する

1<?php
2
3declare(strict_types=1);
4
5/**
6 * DateTime::sub() を使用して、特定の日時から一定期間を引く例を示します。
7 *
8 * この関数は、現在の日時から1ヶ月と10日を引いた結果を表示します。
9 * DateTime::sub() は、指定された DateInterval の期間を
10 * DateTime オブジェクトから減算するためのメソッドです。
11 */
12function demonstrateDateTimeSub(): void
13{
14    try {
15        // 現在の日時でDateTimeオブジェクトを生成します。
16        $date = new DateTime();
17        echo '現在の日時: ' . $date->format('Y-m-d H:i:s') . PHP_EOL;
18
19        // 減算する期間(1ヶ月と10日)を表すDateIntervalオブジェクトを生成します。
20        // 'P1M10D' は Period(期間) 1 Month(月) 10 Days(日) を意味します。
21        $interval = new DateInterval('P1M10D');
22
23        // sub()メソッドを呼び出して、期間を減算します。
24        // このメソッドは、元の$dateオブジェクトを直接変更します。
25        $date->sub($interval);
26
27        // 結果をフォーマットして表示します。
28        echo '1ヶ月と10日前の日時: ' . $date->format('Y-m-d H:i:s') . PHP_EOL;
29    } catch (Exception $e) {
30        // 例外が発生した場合にエラーメッセージを表示します。
31        echo 'エラー: ' . $e->getMessage() . PHP_EOL;
32    }
33}
34
35// 関数を実行してデモを表示します。
36demonstrateDateTimeSub();

DateTime::sub()は、DateTimeオブジェクトが示す特定の日時から、指定した期間を引き算するためのメソッドです。日付や時刻の計算を簡単に行うことができます。

サンプルコードでは、まずnew DateTime()を使って現在の日時を持つオブジェクトを生成します。次に、new DateInterval('P1M10D')で、引き算したい期間である「1ヶ月と10日」を表現するDateIntervalオブジェクトを作成しています。この'P1M10D'という文字列は、期間(Period)が1ヶ月(Month)と10日(Day)であることを示す特別な形式です。

ハイライトとなる$date->sub($interval)の部分で、$dateオブジェクトが持つ日時から$intervalの期間が減算されます。このメソッドの重要な特徴は、新しいDateTimeオブジェクトを返すのではなく、呼び出し元である$dateオブジェクト自身の値を直接変更する点です。

引数には、減算したい期間を表すDateIntervalオブジェクトを渡します。戻り値は、処理が成功した場合には変更後のDateTimeオブジェクト自身を、失敗した場合にはfalseを返します。

DateTime::sub()メソッドを使用する際の最も重要な注意点は、呼び出したオブジェクトの値を直接変更する点です。つまり、$date->sub($interval)を実行すると、元の$dateの値は計算後の過去の日時に上書きされ、元の値は失われます。もし計算前の日時も保持したい場合は、sub()を呼び出す前にオブジェクトをcloneで複製するか、元の値が変更されないDateTimeImmutableクラスの利用を検討してください。また、DateIntervalで月単位の計算をする際は、月によって日数が異なるため、単純な日数計算とは結果が異なる場合がある点も覚えておきましょう。

PHPで日付を減算する

1<?php
2
3/**
4 * DateTime::sub メソッドのサンプルコード
5 *
6 * このスクリプトは、HTMLフォームからの入力を受け取り、指定された日付から特定の日数を減算します。
7 * システムエンジニアを目指す初心者向けに、フォーム処理(submit)とPHPの日付操作の基本を示します。
8 */
9
10// フォームがPOST送信された場合の処理
11if ($_SERVER['REQUEST_METHOD'] === 'POST') {
12    // フォームから基準日と減算する日数を取得
13    // null合体演算子 (??) で未定義の場合に備える
14    $baseDateStr = $_POST['base_date'] ?? null;
15    $daysToSubtract = $_POST['days_to_subtract'] ?? null;
16
17    $resultDate = null; // 減算後の日付を格納する変数
18    $errorMessage = null; // エラーメッセージを格納する変数
19
20    try {
21        // 入力値の検証
22        if ($baseDateStr && is_numeric($daysToSubtract) && (int)$daysToSubtract >= 0) {
23            // 基準日を DateTime オブジェクトとして生成
24            // 無効な日付文字列の場合、Exception がスローされる
25            $dateTime = new DateTime($baseDateStr);
26
27            // 減算する期間を DateInterval オブジェクトとして生成
28            // 'P' は Period(期間)、'D' は Days(日)を表すISO 8601形式
29            $interval = new DateInterval("P{$daysToSubtract}D");
30
31            // DateTime::sub メソッドで日付を減算
32            // 成功すると新しい DateTime オブジェクトを返し、失敗すると false を返す
33            $modifiedDateTime = $dateTime->sub($interval);
34
35            if ($modifiedDateTime) {
36                // 減算後の日付を指定したフォーマットで取得
37                $resultDate = $modifiedDateTime->format('Y-m-d H:i:s');
38            } else {
39                // sub メソッドが false を返した場合(稀だが念のため)
40                $errorMessage = "日付の減算処理に失敗しました。";
41            }
42        } else {
43            // 入力値が不正な場合のエラーメッセージ
44            $errorMessage = "有効な基準日と0以上の減算日数を入力してください。";
45        }
46    } catch (Exception $e) {
47        // DateTime や DateInterval の生成時にエラーが発生した場合のハンドリング
48        $errorMessage = "日付処理中にエラーが発生しました: " . $e->getMessage();
49    }
50}
51?>
52<!DOCTYPE html>
53<html lang="ja">
54<head>
55    <meta charset="UTF-8">
56    <meta name="viewport" content="width=device-width, initial-scale=1.0">
57    <title>PHP DateTime::sub サンプル</title>
58    <style>
59        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 20px; background-color: #f4f7f6; color: #333; }
60        .container { max-width: 600px; margin: 30px auto; background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.08); }
61        h1 { color: #0056b3; text-align: center; margin-bottom: 25px; }
62        p { line-height: 1.6; }
63        form div { margin-bottom: 15px; }
64        label { display: block; margin-bottom: 5px; font-weight: bold; color: #555; }
65        input[type="date"],
66        input[type="number"] {
67            width: calc(100% - 20px);
68            padding: 10px;
69            border: 1px solid #ccc;
70            border-radius: 5px;
71            box-sizing: border-box;
72            font-size: 16px;
73        }
74        input[type="submit"] {
75            display: block;
76            width: 100%;
77            padding: 12px;
78            background-color: #007bff;
79            color: white;
80            border: none;
81            border-radius: 5px;
82            font-size: 18px;
83            cursor: pointer;
84            transition: background-color 0.3s ease;
85        }
86        input[type="submit"]:hover {
87            background-color: #0056b3;
88        }
89        .result, .error {
90            margin-top: 25px;
91            padding: 15px;
92            border-radius: 5px;
93            font-size: 16px;
94        }
95        .result {
96            background-color: #e6f7ff;
97            border: 1px solid #91d5ff;
98            color: #0050b3;
99        }
100        .error {
101            background-color: #fff0f6;
102            border: 1px solid #ffadd2;
103            color: #cf1322;
104        }
105        .result p, .error p { margin: 5px 0; }
106        .code-explanation { font-size: 0.9em; color: #666; margin-top: 20px; padding: 10px; background-color: #f9f9f9; border-left: 3px solid #007bff; }
107    </style>
108</head>
109<body>
110    <div class="container">
111        <h1>日付減算ツール (<code>DateTime::sub</code>)</h1>
112        <p>
113            基準日と減算したい日数を入力し、「日付を減算」ボタンを押してください。
114            PHPの<code>DateTime::sub</code>メソッドを使用して、新しい日付を計算します。
115        </p>
116
117        <form method="POST" action="">
118            <div>
119                <label for="base_date">基準日:</label>
120                <!-- 現在日付を初期値として設定 -->
121                <input type="date" id="base_date" name="base_date" value="<?= htmlspecialchars($baseDateStr ?? date('Y-m-d')) ?>" required>
122            </div>
123            <div>
124                <label for="days_to_subtract">減算する日数:</label>
125                <!-- 7日を初期値として設定、0以上の整数のみ入力可能 -->
126                <input type="number" id="days_to_subtract" name="days_to_subtract" value="<?= htmlspecialchars($daysToSubtract ?? '7') ?>" min="0" required>
127            </div>
128            <div>
129                <input type="submit" value="日付を減算">
130            </div>
131        </form>
132
133        <?php if (isset($resultDate)): ?>
134            <div class="result">
135                <p><strong>元の基準日:</strong> <?= htmlspecialchars($baseDateStr) ?></p>
136                <p><strong>減算した日数:</strong> <?= htmlspecialchars($daysToSubtract) ?></p>
137                <p><strong>減算後の日付:</strong> <?= htmlspecialchars($resultDate) ?></p>
138            </div>
139        <?php elseif (isset($errorMessage)): ?>
140            <div class="error">
141                <p><strong>エラー:</strong> <?= htmlspecialchars($errorMessage) ?></p>
142            </div>
143        <?php endif; ?>
144    </div>
145</body>
146</html>

PHP 8 の DateTime::sub メソッドは、DateTime クラスに属し、特定の日付から指定された期間を減算するために使用されます。このメソッドは、引数として DateInterval オブジェクトを受け取ります。DateInterval は「2日」や「1ヶ月」といった期間を定義するためのPHPのクラスで、例えば現在の日付から7日間前の日付を計算したい場合に便利です。

サンプルコードでは、HTMLフォームからのデータ送信(php submit)を受け取り、ユーザーが入力した基準日から、指定された日数を減算する処理を行っています。具体的には、まずフォームから受け取った日付文字列を基に DateTime オブジェクトを作成し、次に減算したい日数を DateInterval オブジェクトとして生成します。その後、この DateIntervalDateTime::sub メソッドに渡すことで日付を減算します。成功した場合、減算後の新しい DateTime オブジェクトが戻り値として返され、これを format メソッドで表示に適した文字列に変換して出力します。もし減算処理に失敗した場合は false が返されることがありますが、通常は有効な DateInterval が与えられれば DateTime オブジェクトが返されます。このコードは、ウェブフォームの処理とPHPでの日付操作の基本を学ぶための良い例であり、エラー発生時には try-catch で例外を捕捉し、適切なメッセージを表示する堅牢性も備えています。

このサンプルコードでは、フォームから受け取った入力値は、常に不正な値が送られる可能性があるため、is_numericなどで必ず検証することが重要です。また、DateTimeDateIntervalのオブジェクト生成時に無効な値が渡されると例外が発生しますので、try-catch構文でエラーを捕捉し適切に処理すると安全性が高まります。DateTime::subメソッドは、成功すると変更後の新しいDateTimeオブジェクトを返しますが、処理に失敗した場合はfalseを返す可能性も考慮し、戻り値をチェックする習慣をつけましょう。さらに、ユーザーの入力をHTMLに出力する際は、htmlspecialchars()関数を使用して必ずサニタイズし、クロスサイトスクリプティング(XSS)攻撃を防ぐことがセキュリティ上不可欠です。

PHP DateTime subで日付を減算する

1<?php
2
3/**
4 * 現在の日付から指定した期間を減算し、結果を表示する関数。
5 *
6 * @param string $intervalSpec DateIntervalコンストラクタに渡す期間指定文字列。
7 *                             例: 'P3D' (3日間), 'P1M' (1ヶ月), 'PT1H30M' (1時間30分)。
8 *                             形式についてはPHPマニュアルのDateIntervalを参照してください。
9 * @return void
10 */
11function demonstrateDateTimeSub(string $intervalSpec): void
12{
13    // 現在の日付と時刻を表すDateTimeオブジェクトを作成します。
14    $currentDate = new DateTime();
15    echo "現在の年月日: " . $currentDate->format('Y-m-d H:i:s') . "\n";
16
17    try {
18        // 指定された期間を表すDateIntervalオブジェクトを作成します。
19        // 不正な期間指定文字列の場合、ここで例外(Exception)が発生します。
20        $interval = new DateInterval($intervalSpec);
21
22        // DateTime::sub() メソッドを使って、現在のDateTimeオブジェクトから期間を減算します。
23        // このメソッドは元のDateTimeオブジェクト自体を変更し、そのオブジェクト自身を返します。
24        // (DateTimeImmutable::sub()とは異なり、新しいオブジェクトは作成されません。)
25        $resultDate = $currentDate->sub($interval);
26
27        // 減算後の日付を表示します。
28        echo "指定期間 (" . $intervalSpec . ") を減算した年月日: " . $resultDate->format('Y-m-d H:i:s') . "\n";
29
30    } catch (Exception $e) {
31        // DateIntervalの生成失敗など、エラーが発生した場合の処理。
32        echo "エラーが発生しました: " . $e->getMessage() . "\n";
33    }
34}
35
36// --- サンプル実行例 ---
37
38// 1. 現在の日付から3日間を減算する例
39demonstrateDateTimeSub('P3D');
40echo "\n";
41
42// 2. 現在の日付から1ヶ月と5日間を減算する例
43demonstrateDateTimeSub('P1M5D');
44echo "\n";
45
46// 3. 現在の時刻から2時間30分を減算する例
47demonstrateDateTimeSub('PT2H30M');
48echo "\n";
49
50// 4. 不正な期間指定文字列の例(エラーハンドリングの確認)
51// この場合、DateIntervalコンストラクタが例外をスローし、エラーメッセージが表示されます。
52demonstrateDateTimeSub('INVALID_INTERVAL_FORMAT');
53

PHPのDateTime::subメソッドは、日付や時刻から特定の期間を減算するために使われる、DateTimeクラスの重要なメソッドです。システムエンジニアを目指す方にとって、ログの分析やレポート生成、予約システムなどで日付・時刻の計算が必要な場面で頻繁に利用されます。

このメソッドを利用するには、まずnew DateTime()で現在の日時や、特定の日時を表すDateTimeオブジェクトを作成します。次に、減算したい期間をDateIntervalオブジェクトとして準備します。DateIntervalは、'P3D'(3日間)や'P1M5D'(1ヶ月と5日間)、'PT2H30M'(2時間30分)のように、PHPが定める特別な形式の文字列を引数に与えることで生成します。

DateTime::sub()メソッドは、このDateIntervalオブジェクトを引数として受け取り、基準となるDateTimeオブジェクトからその期間を減算します。重要な点として、このメソッドは元のDateTimeオブジェクトそのものを変更し、減算後の新しい日時で更新します。新しいDateTimeオブジェクトを別途生成するわけではありません。戻り値は、減算処理後のDateTimeオブジェクト自身ですが、処理が失敗した場合はfalseを返します。例えば、不正な期間指定文字列でDateIntervalを生成しようとすると例外が発生するため、サンプルコードのようにtry-catchブロックでエラーハンドリングを行うことが堅牢なコードを書く上で非常に重要です。

DateTime::subメソッドは、元のDateTimeオブジェクト自体の日時を変更します。新しいオブジェクトが作成されるDateTimeImmutable::subとは異なりますのでご注意ください。DateIntervalの期間指定文字列は、マニュアルに沿った正しいフォーマットで記述しないと、例外(エラー)が発生します。予期せぬ挙動を防ぐため、サンプルコードのようにtry-catchで例外を適切に処理することが重要です。また、このメソッドは稀にfalseを返す場合もありますので、エラー処理を考慮して利用してください。

PHP substr_replaceによる文字列置換

1<?php
2
3/**
4 * 指定された文字列の一部を別の文字列で置き換える関数。
5 * substr_replaceは、文字列の一部をマスクしたり、特定の位置に挿入したり、
6 * または既存の文字列を上書きしたりする際に使用されます。
7 *
8 * @param string $originalString 処理対象の元の文字列。
9 * @param string $replacement 置き換える文字列。
10 * @param int $offset 置き換えを開始する位置(0から開始)。負の値を指定すると、文字列の最後からのオフセットとして扱われます。
11 * @param int|null $length 置き換える元の文字列の文字数。null(または省略)の場合、オフセットから文字列の最後までを置き換えます。
12 *                          0を指定すると、指定されたオフセットに$replacementが挿入されます。
13 *                          負の値を指定すると、文字列の最後からその文字数分を置き換えます。
14 * @return string 置き換え後の新しい文字列。
15 */
16function replaceSubstringExample(string $originalString, string $replacement, int $offset, ?int $length = null): string
17{
18    // substr_replace 関数を使用して文字列の一部を置き換える
19    // 第1引数: 元の文字列
20    // 第2引数: 置き換える文字列
21    // 第3引数: 置き換えを開始するオフセット
22    // 第4引数: 置き換える元の文字列の長さ
23    return substr_replace($originalString, $replacement, $offset, $length);
24}
25
26// --- サンプルコードの利用例 ---
27
28// 例1: 文字列の一部をマスクする
29$email = "user@example.com";
30echo "元のメールアドレス: " . $email . PHP_EOL;
31// "example" の部分を "***" でマスクする
32// "@" の位置を探し、その次の文字から置き換えを開始します。
33$atPos = strpos($email, '@');
34if ($atPos !== false) {
35    // '@' の次の文字から7文字 ("example") を "***" で置き換える
36    $maskedEmail = replaceSubstringExample($email, '***', $atPos + 1, 7);
37    echo "マスクされたメールアドレス: " . $maskedEmail . PHP_EOL; // 出力例: user@***.com
38}
39
40echo PHP_EOL;
41
42// 例2: 文字列の途中に文字列を挿入する
43$sentence = "Hello world!";
44echo "元の文字列: " . $sentence . PHP_EOL;
45// "world" の前に "beautiful " を挿入したい場合
46// "w" の位置(0から数えて6番目)から0文字を "beautiful " で置き換えるように指定すると、実質挿入になります。
47$insertedSentence = replaceSubstringExample($sentence, 'beautiful ', 6, 0);
48echo "挿入後の文字列: " . $insertedSentence . PHP_EOL; // 出力例: Hello beautiful world!
49
50echo PHP_EOL;
51
52// 例3: 文字列の途中から最後までを置き換える
53$url = "http://www.example.com/old-path";
54echo "元のURL: " . $url . PHP_EOL;
55// "/old-path" の部分を "/new-path" で置き換える
56$pathOffset = strpos($url, '/old-path');
57if ($pathOffset !== false) {
58    // オフセットから文字列の最後までを置き換える場合、$length に null を指定するか省略します。
59    $replacedUrl = replaceSubstringExample($url, '/new-path', $pathOffset);
60    echo "置き換え後のURL: " . $replacedUrl . PHP_EOL; // 出力例: http://www.example.com/new-path
61}
62

PHPのsubstr_replace関数は、指定された文字列の一部を別の文字列で置き換える際に使用する便利な関数です。この関数は、文字列の一部をマスクしたり、特定の文字列を挿入したり、あるいは既存の文字列を上書きしたりする多様な場面で活躍します。

第一引数には処理対象の「元の文字列」を、第二引数には「置き換えたい文字列」を指定します。第三引数の「オフセット」は、置き換えを開始する位置を0から数えて指定します。例えば、オフセットが6であれば、文字列の7文字目から操作が開始されます。負の値を指定すると、文字列の最後から数えた位置が開始点となります。

第四引数の「長さ」は、元の文字列のうち、置き換えの対象となる文字数を指定します。この値を省略したりnullを指定したりすると、オフセットから文字列の最後までが置き換えの対象となります。また、長さに0を指定すると、指定したオフセットの位置に新しい文字列が挿入される形になります。負の値を指定した場合は、文字列の最後からその文字数分を置き換えます。

この関数は、置き換え処理後の「新しい文字列」を返します。例えば、メールアドレスの一部を***でマスクしたり、文章の途中に言葉を追加したり、URLのパス部分を変更したりといった操作を簡単に行うことができます。

substr_replaceは文字列をバイト単位で処理するため、日本語などのマルチバイト文字を含む文字列に使用すると、文字化けや意図しない位置での置換が発生する可能性があります。マルチバイト文字を扱う場合は、mb_substr_replaceのようにマルチバイト対応の関数を検討してください。オフセットと長さの指定では、文字列の先頭を0として数えることに注意が必要です。負の値を指定すると、文字列の末尾から数え始めますので、予期せぬ結果にならないよう確認してください。特に長さとして0を指定すると、指定したオフセットに文字列を挿入する挙動になります。また、strposなどでオフセットを取得する際は、検索対象が見つからなかった場合にfalseが返るため、その戻り値を必ずチェックし、適切なエラーハンドリングを行うことが重要です。

関連コンテンツ

関連IT用語

関連プログラミング言語