Can someone explain why there's a one-year difference in the results of PHP's date diff function for these two dates with the same timezone?

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

Can someone explain why there's a one-year difference in the results of PHP's date diff function for these two dates with the same timezone?

问题

$a = new DateTime("2023-05-31", new DateTimeZone('Europe/Rome'));
$b = new DateTime("1970-05-31", new DateTimeZone('Europe/Rome'));
var_dump($a->diff($b)->y);
// int(52)

$a = new DateTime("2023-05-30", new DateTimeZone('Europe/Rome'));
$b = new DateTime("1970-05-30", new DateTimeZone('Europe/Rome'));
var_dump($a->diff($b)->y);
// int(53)
英文:
$a = new DateTime("2023-05-31", new DateTimeZone('Europe/Rome'));
$b = new DateTime("1970-05-31", new DateTimeZone('Europe/Rome'));
var_dump($a->diff($b)->y);
// int(52)

$a = new DateTime("2023-05-30", new DateTimeZone('Europe/Rome'));
$b = new DateTime("1970-05-30", new DateTimeZone('Europe/Rome'));
var_dump($a->diff($b)->y);
// int(53)

Why in the first case the diff is 52?

I expect 53 for both cases

答案1

得分: 1

以下是翻译好的部分:

似乎总体来说,意大利有些问题。可能是因为某年他们没有进行夏令时调整,这可能会导致功能出现混淆(这只是一个猜测)。

foreach ($zones as $zone){
    $tz = new DateTimeZone($zone);
    $a = new DateTime("2023-05-31", $tz);
    $b = new DateTime("1970-05-31", $tz);
    if ($a->diff($b)->y != 53) {
        printf(" !!! %s diff = %d\n", $zone, $a->diff($b)->y);
    } else {
        //printf("%s diff = %d\n", $zone, $a->diff($b)->y);
    }
}
结果

 !!! Europe/Rome diff = 52
 !!! Europe/Malta diff = 52
 !!! Europe/San_Marino diff = 52
 !!! Europe/Vatican diff = 52

如果从1971年开始就没有这个问题,所以可能有问题的年份是1970年。

https://www.timeanddate.com/time/change/italy/rome?year=1970 上找到了以下信息,这可能有助于解释。

1970年5月31日 - 夏令时开始
当地标准时间即将达到
1970年5月31日星期日,00:00:00 时钟被向前调整1小时至

1970年5月31日星期日,01:00:00 当地夏令时。

与前一天相比,1970年5月31日的日出和日落时间要晚大约1小时。
当天晚上有更多的光。

也称为“春季前进时间”、“夏令时”和“节约时间”。
英文:

There seems to be something about Italy in general. Possibly they didnt do a Summer time one year that is confusing the function (Thats a guess)

$zones = [
        'Europe/Rome', 'Europe/Malta', 'Europe/San_Marino', 'Europe/Vatican',
        
        'Europe/Amsterdam', 'Europe/Andorra', 'Europe/Astrakhan',	'Europe/Athens', 
        'Europe/Belgrade', 'Europe/Berlin', 'Europe/Bratislava', 'Europe/Brussels',
        'Europe/Bucharest' ,'Europe/Budapest', 'Europe/Busingen', 'Europe/Chisinau',
        'Europe/Copenhagen', 'Europe/Dublin', 'Europe/Gibraltar', 'Europe/Guernsey',
        'Europe/Helsinki', 	'Europe/Isle_of_Man', 'Europe/Istanbul', 'Europe/Jersey',
        'Europe/Kaliningrad', 'Europe/Kirov' ,	'Europe/Kyiv', 	'Europe/Lisbon',
        'Europe/Ljubljana', 'Europe/London', 'Europe/Luxembourg', 'Europe/Madrid',
         'Europe/Mariehamn', 'Europe/Minsk', 'Europe/Monaco',
        'Europe/Moscow', 'Europe/Oslo', 'Europe/Paris', 'Europe/Podgorica',
        'Europe/Prague','Europe/Riga' ,	'Europe/Samara',
         'Europe/Sarajevo' ,	'Europe/Saratov', 'Europe/Simferopol',
        'Europe/Skopje', 'Europe/Sofia' ,	'Europe/Stockholm', 'Europe/Tallinn',
        'Europe/Tirane', 'Europe/Ulyanovsk', 	'Europe/Vaduz', 
        'Europe/Vienna', 'Europe/Vilnius', 	'Europe/Volgograd', 'Europe/Warsaw',
        'Europe/Zagreb', 'Europe/Zurich'];

foreach ( $zones as $zone){
    $tz = new DateTimeZone($zone);
    $a = new DateTime("2023-05-31", $tz);
    $b = new DateTime("1970-05-31", $tz);
    if ( $a->diff($b)->y != 53) {
        printf (" !!! %s diff = %d\n", $zone, $a->diff($b)->y);
    } else {
        #printf ("%s diff = %d\n", $zone, $a->diff($b)->y);
    }
    
}

RESULTS

 !!! Europe/Rome diff = 52
 !!! Europe/Malta diff = 52
 !!! Europe/San_Marino diff = 52
 !!! Europe/Vatican diff = 52

>It also does not happen if you start from 1971, so maybe the year with an issue is 1970

Found this on https://www.timeanddate.com/time/change/italy/rome?year=1970 which may go some way to explain.

31 May 1970 - Daylight Saving Time Started
When local standard time was about to reach
Sunday, 31 May 1970, 00:00:00 clocks were turned forward 1 hour to

Sunday, 31 May 1970, 01:00:00 local daylight time instead.

Sunrise and sunset were about 1 hour later on 31 May 1970 than the day before. 
There was more light in the evening.

Also called Spring Forward, Summer Time, and Daylight Savings Time.

</details>



# 答案2
**得分**: 1

我自己测试了一下,发现了一些有趣的事情。正如我在评论中提到的,31号之间有一个小时的差异,但后来我注意到这一点:

    $b = new DateTime("1970-05-31", new DateTimeZone('Europe/Rome'));
    // = DateTime @12956400 {#7126
    // date: 1970-05-31 01:00:00.0 Europe/Rome (+02:00),
    // }
    
    $b = new DateTime("1970-05-30", new DateTimeZone('Europe/Rome'));
     // = DateTime @12870000 {#7124
    // date: 1970-05-30 00:00:00.0 Europe/Rome (+01:00),
    // }

如你所见,在31日有2小时的偏移,但在30日有1小时的偏移。通过查看https://www.timeanddate.com/time/zone/italy/rome ,我发现1970年5月31日凌晨12:00时,时间发生了变化,实际上并不存在12:00时,而是跳到了1:00时。比较是完整的比较,因此实际差异是`52年11个月30天23:00:00.0`。

<details>
<summary>英文:</summary>

Tested it myself, and I noticed something interesting. As I mentioned in my comment, there was a 1 hour difference between the 31st dates, but then I noticed this:

    $b = new DateTime(&quot;1970-05-31&quot;, new DateTimeZone(&#39;Europe/Rome&#39;));
    // = DateTime @12956400 {#7126
    // date: 1970-05-31 01:00:00.0 Europe/Rome (+02:00),
    // }
    
    $b = new DateTime(&quot;1970-05-30&quot;, new DateTimeZone(&#39;Europe/Rome&#39;));
     // = DateTime @12870000 {#7124
    // date: 1970-05-30 00:00:00.0 Europe/Rome (+01:00),
    // }

As you can see, on the 31st, there&#39;s a 2 hour offset, but on the 30th, there&#39;s a 1 hour offset. Checking with https://www.timeanddate.com/time/zone/italy/rome , the time changed on May 31st, 1970 at 12:00 am, so the 12am hour didn&#39;t actually exist, and it jumped to 1am. The comparison does a full comparison, and so the difference is actually `52y 11m 30d 23:00:00.0`

</details>



huangapple
  • 本文由 发表于 2023年6月1日 23:28:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76383503.html
匿名

发表评论

匿名网友

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

确定