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

查看:75
本文介绍了为什么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个月有何不同?
  • 如果给定日期之间没有夏令时,leap年没有特别之处,为什么计算模式取决于我使用的时区?
  • 在哪里可以找到算法的确切描述,如何计算差异?

推荐答案

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
  • 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.

当两个日期都在澳大利亚/墨尔本中时,该函数将进行以下比较:

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
  • 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校正的时区偏移量).如我们所见,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成员,

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

PS

此答案中的值是通过 TIMELIB_DEBUG 宏.

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

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

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