为什么 php datetime diff 依赖于时区? [英] Why does php datetime diff depend on time zones?

查看:37
本文介绍了为什么 php datetime diff 依赖于时区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

见以下代码:

function printDiff($tz) {
    $d1 = new DateTime("2015-06-01", new DateTimeZone($tz));
    $d2 = new DateTime("2015-07-01", new DateTimeZone($tz));
    $diff = $d1->diff($d2);
    print($diff->format("Year: %Y Month: %M Day: %D"). PHP_EOL);
}
printDiff("UTC");
printDiff("Australia/Melbourne");

结果是:

Year: 00 Month: 01 Day: 00
Year: 00 Month: 00 Day: 30

问题:

  • 相邻两个月(6 月 1 日和 7 月)的同一天之间的差异如何与 1 个月不同?
  • 如果给定日期之间没有夏令时,没有闰年,没有什么特别的,为什么计算模式取决于我使用的时区?
  • 我在哪里可以找到关于如何计算差异的算法的确切描述?

推荐答案

date 扩展以 GMT 格式存储时间值.GMT 偏移量单独存储.它应用于计算的后期阶段,以进行修正.

The date extension stores the time values in GMT. The GMT offset is stored separately. It is applied at the late phases of calculations, for correction.

特别是,DateTime::diff 在内部调用 timelib_diff 函数,它计算两个日期之间的差异,应用 DST 校正,然后按该顺序规范化其内部结构.

Particularly, DateTime::diff internally calls timelib_diff function, which calculates difference between two dates, applies the DST correction, then normalizes its internal structures, in that order.

当两个日期都在 UTC 时,函数会比较以下内容:

When both dates are in UTC, the function compares the following:

  • Timestamp=1433116800,year=2015,month=6,day=1,hour=0,minute=0,second=0
  • Timestamp=1435708800, year=2015, month=7, day=1, hour=0, minute=0, second=0

它会相应地减去年、月、日、小时、分钟和秒.差值正好是一个月.因此,之后内部结构没有被修改归一化.

It subtracts years, months, days, hours, minutes, and seconds correspondingly. The difference is exactly one month. Therefore, the internal structures are not modified after normalization.

当两个日期都在 Australia/Melbourne 时,该函数会比较以下内容:

When both dates are in Australia/Melbourne, the function compares the following:

  • Timestamp=1433080800,year=2015,month=5,day=31,hour=14,minute=0,second=0
  • Timestamp=1435672800,year=2015,month=6,day=30,hour=14,minute=0,second=0

这两个日期都是减去 10 小时(没有 DST 校正的时区偏移).正如我们所见,夏令时校正 是如果需要(特别是不需要),在减去时间值后应用.归一化前的区别是:

Both dates are obtained by subtracting 10 hours (the timezone offset without DST correction). As we have seen, the DST correction is applied after subtraction of the time values, if needed (it is not needed, in particular). The difference before normalization is:

0 years, 1 month, -1 day, 0 hours, 0 minutes, 0 seconds

由于我们在月份之间有一个偏移量,因此归一化函数将差异计算为

Since we have an offset between the months, normalization function computes the difference as

0 years, 0 months, 30 days, 0 hours, 0 minutes, 0 seconds

DateInterval::format 方法很简单.它只是将占位符替换为 的成员timelib_rel_time 结构.这就是为什么我们在 UTC 获得 1 个月,在澳大利亚/墨尔本获得 30 天.

The DateInterval::format method is straightforward. It just substitutes the placeholders to the members of timelib_rel_time structure. That's why we get 1 month for UTC, and 30 days for Australia/Melbourne.

a 格式字符

The a format character

这看起来有点不可靠.但是,在 timelib_rel_time 结构中有一个 days 成员,它 总是等于天差.该值可通过 a 格式字符获得:

That looks somewhat unreliable. However, there is a days member in the timelib_rel_time structure, which always equals to the difference in days. The value is available via the a format character:

function printDiff($tz) {
  $d1 = new DateTime("2015-06-01", new DateTimeZone($tz));
  $d2 = new DateTime("2015-07-01", new DateTimeZone($tz));
  $diff = $d1->diff($d2);
  print($diff->format("Year: %Y Month: %M Day: %D days: %a"). PHP_EOL);
}

printDiff("UTC");
printDiff("Australia/Melbourne");

输出

Year: 00 Month: 01 Day: 00 days: 30
Year: 00 Month: 00 Day: 30 days: 30

附言

此答案中的值是在 TIMELIB_DEBUG 宏.

The values in this answer are obtained with the help of TIMELIB_DEBUG macro.

这篇关于为什么 php datetime diff 依赖于时区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆