PHP <8.2 和 8.2+ 之间的双重减日期修饰符差异

huangapple go评论62阅读模式
英文:

Differences in double subtract date modifiers between PHP <8.2 and 8.2+

问题

我正在将一个代码库从PHP 7.4升级到8.2。我的单元测试发现了一个在修改提供的日期的代码区域中的奇怪问题。

看起来PHP 8.2在使用" -- "(双算术运算符)修改日期时引入了一些日期函数工作方式的行为。

这似乎是在使用DateTime对象以及它的->modify()方法时的情况。似乎更多与双"-"修饰符有关,如果$index是负数将使用该修饰符。在这里可以看到示例:https://3v4l.org/fNR2X

但是这个方法需要支持发送正数和负数修饰符。

在我完全重构这个旧代码之前,我试图找到PHP 8.2的实际更改描述,以便我能够准确了解发生了什么变化。我在changelog或谷歌搜索中找不到任何关于这方面的信息。有人知道吗?

英文:

I am upgrading a codebase from PHP 7.4 to 8.2. My unit tests picked up an oddity in an area of code that modifies a provided date.

It looks like PHP 8.2 introduced some behaviour with how date functions work when you modify a date using "--" (double arithmetic operators).

public static function getCorrectedTime(
        int $year,
        int $month,
        int $day,
        int $index,
        string $period
    ): int {

        // PHP 7.4 - if $index=0, $timestamp=1625443200, if $index=-1, $timestamp=1625529600 - test passes
        // PHP 8.2 - if $index=0, $timestamp=1625443200, if $index=-1, $timestamp=1625356800 - test fails
        $timestamp = strtotime(&quot;{$year}-{$month}-{$day} -{$index} {$period}&quot;);
        return $timestamp;
    }

This seems to be the case when using DateTime objects and it's ->modify() method. It seems like it's more to do with the double "-" modifier that will be used if $index is a negative number. See scratch pad here: https://3v4l.org/fNR2X

But this method needs to support both positive and negative modifiers being sent to it.

Before I completely refactor this old code, I was trying to hunt down an actual description of the change to PHP 8.2 so I can understand exactly what was changed. I can see nothing about this in the changelog or Google hunt. Is anyone aware?

答案1

得分: 1

当您将 $index = -1*$index; 添加到您的代码中,并在区间之前删除 -

<?php
$year=2023;
$month=5;
$day=28;
$index=-1;
$period='day';

$index = -1*$index;
// strtotime test
$dateString = $year . "-" . $month . "-" . $day . " " . $index . " " . $period;
$timestamp1 = strtotime("{$year}-{$month}-{$day} {$index} {$period}");

// DateTime test
$dateStamp = new \DateTime("{$year}-{$month}-{$day}");
$dateStamp->modify("{$index} {$period}");
$timestamp2 = $dateStamp->getTimeStamp();

echo $dateString . PHP_EOL;
echo "strtotime: " . $timestamp1 . PHP_EOL;
echo "DateTime: " . $timestamp2;

输出在 8.1.2 和 8.2.6 中是相同的。

顺便说一下:(在 Linux 上) date -d "--1 day" 也会返回昨天的日期,而 date -d "-1 day" 也是如此。

英文:

When you add $index = -1*$index; to your code, and remove the - in the expressions before the interval:

&lt;?php
$year=2023;
$month=5;
$day=28;
$index=-1;
$period=&#39;day&#39;;

$index = -1*$index;
// strtotime test
$dateString = $year . &quot;-&quot; . $month . &quot;-&quot; . $day . &quot; &quot; . $index . &quot; &quot; . $period;
$timestamp1 = strtotime(&quot;{$year}-{$month}-{$day} {$index} {$period}&quot;);

// DateTime test
$dateStamp = new \DateTime(&quot;{$year}-{$month}-{$day}&quot;);
$dateStamp-&gt;modify(&quot;{$index} {$period}&quot;);
$timestamp2 = $dateStamp-&gt;getTimeStamp();

echo $dateString . PHP_EOL;
echo &quot;strtotime: &quot; . $timestamp1 . PHP_EOL;
echo &quot;DateTime: &quot; . $timestamp2;

The output is the same in 8.1.2 and 8.2.6

BTW: (on linux) date -d &quot;--1 day&quot; also returns the date for yesterday, while date -d &quot;-1 day&quot;

答案2

得分: 1

使用 sprintf 强制索引的符号允许您在日期前面拥有一个字符串,而不是出现 "--" 或 "-"...

重要的部分是格式字符串 %+d...

// strtotime 测试
$dateString = sprintf('%d-%d-%d %+d %s', $year, $month, $day, $index, $period);
$timestamp1 = strtotime($dateString);

// DateTime 测试
$dateString = sprintf('%+d %s', $index, $period);
$dateStamp = new \DateTime("{$year}-{$month}-{$day}");
$dateStamp->modify($dateString);
$timestamp2 = $dateStamp->getTimeStamp();
英文:

Using sprintf to force the sign for the index would allow you to have a string with either +/- before the days rather than having a -- or -...

The important part is the format string %+d...

// strtotime test
$dateString = sprintf(&#39;%d-%d-%d %+d %s&#39;, $year, $month, $day, $index, $period);
$timestamp1 = strtotime($dateString);

// DateTime test
$dateString = sprintf(&#39;%+d %s&#39;, $index, $period);
$dateStamp = new \DateTime(&quot;{$year}-{$month}-{$day}&quot;);
$dateStamp-&gt;modify($dateString);
$timestamp2 = $dateStamp-&gt;getTimeStamp();

答案3

得分: 1

这些内容的翻译如下:

英文:

It's listed in the chapter Migrating from PHP 8.1.x to PHP 8.2.x / Backward Incompatible Changes and the bottom of Relative Formats.

> number symbols in relative formats no longer accept multiple signs, e.g. +-2.

Here's a related issue: #11237

huangapple
  • 本文由 发表于 2023年5月28日 16:43:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76350644.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定