PHPのエラー『Warning: DateTime::modify(): Failed to Parse Time String』の解決方法

  • 作成日 2025.04.18
  • php
PHPのエラー『Warning: DateTime::modify(): Failed to Parse Time String』の解決方法

PHPで `DateTime::modify()` を使用する際に「Warning: DateTime::modify(): Failed to Parse Time String」というエラーが発生することがある。このエラーは、`modify()` に渡された文字列のフォーマットが `DateTime` クラスで解釈できない場合に発生する。原因と解決策を詳しく見ていく。

1. エラーの発生条件

`DateTime::modify()` は、渡された文字列を解析して日付を変更するメソッド。ただし、無効なフォーマットの文字列を渡すとエラーになる。

2. エラーが発生するコード例

次のコードでは、`modify()` に不正な日付文字列を渡しているためエラーが発生する。

<?php
$date = new DateTime('2024-03-04');
$date->modify('invalid string'); // 無効なフォーマット
?>

実行すると、次のようなエラーが表示される。

Warning: DateTime::modify(): Failed to parse time string (invalid string) at position 0 (i): The timezone could not be found in the database

3. `modify()` で使える文字列の例

`modify()` は、以下のようなフォーマットを正しく解釈できる。

  • +1 day
  • -2 weeks
  • first day of next month
  • last day of this year
  • next Monday

4. 解決方法:正しいフォーマットの文字列を渡す

エラーを防ぐには、`modify()` に渡す文字列を適切なフォーマットに修正する。

<?php
$date = new DateTime('2024-03-04');
$date->modify('+1 day'); // 正しいフォーマット
echo $date->format('Y-m-d');
?>

5. 事前にフォーマットを検証する

入力値が `modify()` で扱える形式かどうかを確認するために、正規表現で検証できる。

<?php
function isValidDateModifyString($str) {
    return preg_match('/^(\+|\-)?\d+ (day|week|month|year)s?$/i', $str);
}

$input = "+3 days";

if (isValidDateModifyString($input)) {
    $date = new DateTime('2024-03-04');
    $date->modify($input);
    echo $date->format('Y-m-d');
} else {
    echo "無効なフォーマットです";
}
?>

6. `strtotime()` を併用する

`strtotime()` を使用すれば、事前に文字列のパースが可能。

<?php
$modifyString = "next Friday";
$timestamp = strtotime($modifyString);

if ($timestamp !== false) {
    $date = new DateTime();
    $date->setTimestamp($timestamp);
    echo $date->format('Y-m-d');
} else {
    echo "無効な日付文字列です";
}
?>

7. 日本語などのロケールを考慮する

`modify()` は英語のフォーマットしか受け付けないため、日本語の日付表記は直接渡せない。

<?php
$modifyString = "来週の金曜日"; // これはNG
?>

日本語の入力を処理するには、変換テーブルを作成し、英語表記に変換する方法がある。

<?php
$translations = [
    '今日' => 'today',
    '明日' => 'tomorrow',
    '昨日' => 'yesterday',
    '来週' => 'next week',
    '先週' => 'last week'
];

$input = "来週";

if (isset($translations[$input])) {
    $modifyString = $translations[$input];
    $date = new DateTime();
    $date->modify($modifyString);
    echo $date->format('Y-m-d');
} else {
    echo "無効な入力です";
}
?>

8. `Exception` をキャッチする

PHP 8 以降では `DateTime::modify()` で例外がスローされるため、`try-catch` を使ってエラーを処理できる。

<?php
try {
    $date = new DateTime('2024-03-04');
    $date->modify('invalid string');
} catch (Exception $e) {
    echo "エラー: " . $e->getMessage();
}
?>

9. `DateTimeImmutable` を使う

`DateTimeImmutable` を使用すると、元のオブジェクトを変更せずに新しいインスタンスを作成できる。

<?php
$date = new DateTimeImmutable('2024-03-04');
$newDate = $date->modify('+1 day');

echo "元の日付: " . $date->format('Y-m-d') . "<br>";
echo "変更後の日付: " . $newDate->format('Y-m-d');
?>

10. `modify()` の代替として `add()` を使う

日付を変更するなら `modify()` ではなく、`add()` も使用可能。

<?php
$date = new DateTime('2024-03-04');
$date->add(new DateInterval('P1D')); // 1日追加
echo $date->format('Y-m-d');
?>

`DateInterval` を使うと、より明確に期間を指定できる。

11. `sub()` で日付を減算する

日付を減算する場合は、`sub()` を使う方法もある。

<?php
$date = new DateTime('2024-03-04');
$date->sub(new DateInterval('P2W')); // 2週間前にする
echo $date->format('Y-m-d');
?>

12. `DateTimeImmutable` と `modify()` の組み合わせ

`DateTimeImmutable` を使用すれば、元の日付を変更せずに `modify()` を使うことができる。

<?php
$date = new DateTimeImmutable('2024-03-04');
$newDate = $date->modify('+3 days');

echo "元の日付: " . $date->format('Y-m-d') . "<br>";
echo "変更後の日付: " . $newDate->format('Y-m-d');
?>

`DateTimeImmutable` を使うことで、副作用を防ぎつつ安全に日付操作が可能。