php / php/php-src

Miscalculation of a date using microseconds

未关闭
#20,550 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Bug Extension: date Status: Needs Triage
主要语言
C
星标
40.4k
派生
8.2k
平均合并
2 天 13 小时
30 天内合并 PR
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. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 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 摘要。