获取两个日期时间之间的间隔秒在PHP?


Answers:


131

您可以使用strtotime()来做到这一点:

$diff = strtotime('2009-10-05 18:11:08') - strtotime('2009-10-05 18:07:13')

对于DateTime对象,可以使用类似的方法,例如

$date = new DateTime( '2009-10-05 18:07:13' );
$date2 = new DateTime( '2009-10-05 18:11:08' );

$diff = $date2->getTimestamp() - $date->getTimestamp();

1
注意:当您的“下”时间是“现在”并且date()用于获取现在的日期时间()时,请务必使用大写的“ H”小时(24小时模式date("Y-m-d H:i:s"))。
jave.web 2015年

通过查看各个组成部分之间的分隔符,可以消除m / d / y或dmy格式的日期的歧义:如果分隔符为斜杠(/),则假定为美国m / d / y;相反,如果分隔符是破折号(-)或点(。),则采用欧洲dmy格式。但是,如果以两位数格式给出年份,并且分隔符为破折号(-,则将日期字符串解析为ymd。为避免可能出现的歧义,最好使用ISO 8601(YYYY-MM-DD)日期或日期时间:: createFromFormat()时可能```。
尼古拉Petkanski

检查JCM答案并选择您的案子
Leandro '18

156

使用DateTime对象,您可以这样做:

$date = new DateTime( '2009-10-05 18:07:13' );
$date2 = new DateTime( '2009-10-05 18:11:08' );

$diffInSeconds = $date2->getTimestamp() - $date->getTimestamp();

1
这也考虑了夏令时!
Brainware

5
这是对该问题的最优雅的解决方案。这应该是公认的答案。
Giel Berkers

1
请注意,为了正确考虑夏令时,您需要提供正确的DateTimeZone。如果您的系统设置正确,则php可能已经从系统默认值知道您的时区。如果有疑问,请手动实例化:$ tz = new DateTimeZone('Europe / Berlin'); 并将其作为第二个参数传递给DateTime构造函数。
j4k3

很好的解决方案,但是更长的时间(例如1个小时),我收到了负值(溢出?),您知道如何解决此问题吗?
marto


4

由于unix时代的局限性,在1970年之前和2038年之后的日期计算上可能会遇到问题。我选择放宽精度(=不要看一秒钟),但要避免通过谷歌unix时代转换(getTimestamp)。这取决于你在做什么...

在我的情况下,使用365(12 * 30)和“ 30”作为平均月长可以减少可用输出中的错误。

function DateIntervalToSec($start,$end){ // as datetime object returns difference in seconds
    $diff = $end->diff($start);
    $diff_sec = $diff->format('%r').( // prepend the sign - if negative, change it to R if you want the +, too
                ($diff->s)+ // seconds (no errors)
                (60*($diff->i))+ // minutes (no errors)
                (60*60*($diff->h))+ // hours (no errors)
                (24*60*60*($diff->d))+ // days (no errors)
                (30*24*60*60*($diff->m))+ // months (???)
                (365*24*60*60*($diff->y)) // years (???)
                );
    return $diff_sec;
}

请注意,如果“平均”数量用于差异,则误差可能为0。PHP文档没有讲到这一点……在很坏的情况下,错误可能是:

  • 如果对小于1个月的时间间隔应用差异,则为0秒
  • 如果对大于1个月的时间间隔应用差异,则为0到3天
  • 如果对大于1年的时间间隔应用差异,则为0到14天

我更喜欢假设有人决定将“ m”视为30天,将“ y”视为365,当“ diff”走过非30天月份时,将“ d”的差额收取...

如果有人对此有更多了解并可以提供正式文档,欢迎您!


使用days属性而不是d属性来获取两天之间的确切日期。因此,那里没有不准确的结果。
Nilz11 '11

2
strtotime("2009-10-05 18:11:08") - strtotime("2009-10-05 18:07:13")

2

如果您需要真实的当地时差并希望与 getTimestamp,则必须考虑在计算的期间内的DST开关。因此,方程中必须包括UTC的局部偏移。

以以下日期为例:

$tz = new \DateTimeZone("Europe/Berlin");
$start = new \DateTime("2018-02-01 12:00:00", $tz);
$end = new \DateTime("2018-04-01 12:00:00", $tz);

$start在UTC中为“ 2018-02-01 11:00:00”,在UTC中$end为“ 2018-04-01 10:00:00”。请注意,尽管柏林时区中的一天中的时间相同,但UTC中的时间却有所不同。UTC偏移量为的1小时$start和的2小时$end

请记住,getTimestamp始终返回UTC!因此,在寻找实际的局部差异时,必须从时间戳中减去偏移量。

// WRONG! returns 5094000, one hour too much due to DST in the local TZ
echo $end->getTimestamp() - $start->getTimestamp();

// CORRECT: returns 5090400
echo ($end->getTimestamp() - $end->getOffset()) - ($start->getTimestamp() - $start->getOffset());

这个答案是可怕的错误信息。我只是编写了自己的测试用例来检查这一点,但很高兴发现这完全是错误的。5094000%86400 =82800。如果时钟在DST边界向前跳了一个小时,则表示“丢失小时”的整整秒数减去3600。更简单的测试用例:“ 2019-03-31 01:59:59”和“ 2019-03-31 03:00:01”之间的时间戳差异为2秒,这是正确的数量。“ 2019-10-27 01:59:59”和“ 2019-10-27 02:00:01”之间的时间戳差异为3602秒,这是正确的值。
j4k3

关于此的更多信息:getTimestamp和setTimestamp指的是始终没有时区的unix时间戳。您正在将时区自由格式与时区偏移量混合在一起。在您的“带有unix时间戳的交易”示例中,您正在寻找3600 + 1 = 3720秒,因为时钟被拨回了一个小时,而不是两个小时。
j4k3

-1

一个简单而精确的解决方案(以Nilz11的评论为例):

$hiDate = new DateTime("2310-05-22 08:33:26");
$loDate = new DateTime("1910-11-03 13:00:01");
$diff = $hiDate->diff($loDate);
$secs = ((($diff->format("%a") * 24) + $diff->format("%H")) * 60 + 
   $diff->format("%i")) * 60 + $diff->format("%s");
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.