php / php/php-src

Miscalculation of a date using microseconds

オープン
#20,550 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

Bug Extension: date Status: Needs Triage
主要言語
C
スター
40.4k
フォーク
8.2k
平均マージ
2日 13時間
マージ済み PR(30日)
96

説明

Description

The following code:

<?php
date_default_timezone_set("UTC");

$beginningOfYear = new \DateTimeImmutable('1st january this year')
    ->setTime(0, 0);
$endOfYear = new \DateTimeImmutable('31th december this year')
    ->setTime(23, 59, 59, 999999);


$uuThisYear = (int) $endOfYear->format('Uu') - (int) $beginningOfYear->format('Uu');
$sThisYear = (int) $endOfYear->format('U') - (int) $beginningOfYear->format('U');
$usThisYear = (int) $endOfYear->format('u') - (int) $beginningOfYear->format('u');

$uuThisYear2 = (int) ($sThisYear . $usThisYear);

echo "<pre>" . var_export([
    'from' => $beginningOfYear,
    'fromMs' => (int) $beginningOfYear->format('Uu'),
    'to' => $endOfYear,
    'toMs' => (int) $endOfYear->format('Uu'),
    'nbMicrosecondsBetweenToAndFrom' => $uuThisYear,
    'nbMicrosecondsBetweenToAndFromOtherCalculation' => $uuThisYear2,
    'equal' => $uuThisYear === $uuThisYear2,
    'nbSecondsBetweenToAndFrom' => $sThisYear,
    'nbUsecondsBetweenToAndFrom' => $usThisYear,
    'shouldEqualToFromButDoesntWork' => (clone $endOfYear)->modify('-' . $uuThisYear . ' µsec'),
    'shouldEqualToFromWorks' => (clone $endOfYear)
        ->modify('-' . $sThisYear . ' seconds')
        ->modify('-' . $usThisYear . ' microseconds'),
], true);

Resulted in this output:

array (
  'from' => 
  \DateTimeImmutable::__set_state(array(
     'date' => '2025-01-01 00:00:00.000000',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  )),
  'fromMs' => 1735689600000000,
  'to' => 
  \DateTimeImmutable::__set_state(array(
     'date' => '2025-12-31 23:59:59.999999',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  )),
  'toMs' => 1767225599999999,
  'nbMicrosecondsBetweenToAndFrom' => 31535999999999,
  'nbMicrosecondsBetweenToAndFromOtherCalculation' => 31535999999999,
  'equal' => true,
  'nbSecondsBetweenToAndFrom' => 31535999,
  'nbUsecondsBetweenToAndFrom' => 999999,
  'shouldEqualToFromButDoesntWork' => 
  \DateTimeImmutable::__set_state(array(
     'date' => '2026-01-01 09:59:59.999998',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  )),
  'shouldEqualToFromWorks' => 
  \DateTimeImmutable::__set_state(array(
     'date' => '2025-01-01 00:00:00.000000',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  )),
)

But I expected this output instead:

array (
  'from' => 
  \DateTimeImmutable::__set_state(array(
     'date' => '2025-01-01 00:00:00.000000',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  )),
  'fromMs' => 1735689600000000,
  'to' => 
  \DateTimeImmutable::__set_state(array(
     'date' => '2025-12-31 23:59:59.999999',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  )),
  'toMs' => 1767225599999999,
  'nbMicrosecondsBetweenToAndFrom' => 31535999999999,
  'nbMicrosecondsBetweenToAndFromOtherCalculation' => 31535999999999,
  'equal' => true,
  'nbSecondsBetweenToAndFrom' => 31535999,
  'nbUsecondsBetweenToAndFrom' => 999999,
  'shouldEqualToFromButDoesntWork' => 
  \DateTimeImmutable::__set_state(array(
     'date' => '2025-01-01 00:00:00.000000',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  )),
  'shouldEqualToFromWorks' => 
  \DateTimeImmutable::__set_state(array(
     'date' => '2025-01-01 00:00:00.000000',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  )),
)

Check the "shouldEqualToFromButDoesntWork" value.

PHP Version
8.4.14
Operating System

Mint 22.2 Zara

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

Start by reproducing the DateTimeImmutable::modify('-... µsec') case from the issue on PHP 8.4.14, then trace the date/time implementation that handles microsecond modifiers. Compare it with the separate seconds-and-microseconds calls; done when the single microsecond subtraction produces the same 2025-01-01 00:00:00.000000 result.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
php
領域
backend
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
42/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。