繁体   English   中英

发现两次之间存在差异。 (PHP / MySQL)

[英]Issue finding difference between two times. (PHP/MySQL)

我试图通过找到开始时间和结束时间之间的差异来确定某项内容的持续时间。

//bring date & time input into mysql datetime format for query

$t_start_datetime = date('Y-m-d G:i:s' ,strtotime($_POST['t_date'].' '.$_POST['t_start'].' '.$_POST['s_ampm']));
$t_end_datetime = date('Y-m-d G:i:s' ,strtotime($_POST['t_date'].' '.$_POST['t_end'].' '.$_POST['e_ampm']));

// get duration value of test by finding the difference between the start and end time.
$end_time= strtotime($_POST['t_date'].' '.$_POST['t_start'].' '.$_POST['s_ampm']);
$start_time= strtotime($_POST['t_date'].' '.$_POST['t_end'].' '.$_POST['e_ampm']);

$temp = $end_time - $start_time;

echo date('G:i:s', $end_time);
echo date('G:i:s', $start_time);
//here is the duration
echo date('G:i:s', abs($temp));

因此,可以说start_time的值为6:00:00和end_time 7:45:00的持续时间为2:45:00:S

它总是比实际差异多一个小时。

我究竟做错了什么? 请赐教。

谢谢

问题

首先,考虑一下:

<?php
echo date('Y-m-d H:i:s', 300); // Output for GMT: "1970-01-01 00:05:00"
?>

UNIX时间戳是UNIX时代之后的300秒(或5分钟)。 date()在您当前的本地时区显示此时间。

现在考虑一下:

<?php
echo date('Y-m-d H:i:s', 18000); // Output for GMT: "1970-01-01 05:00:00"
?>

这是UNIX时代之后的5个小时。 但是请记住, date()使用您当前的本地时区,因此,例如,如果您处于英国夏令时(GMT + 1),则会得到:

<?php
date_default_timezone_set("Etc/GMT+1"); // Setting manually for demonstration
echo date('Y-m-d H:i:s', 18000); // Output for BST: "1970-01-01 04:00:00"
?>

即使不是1970年1月1日的BST,现在也就是BST,这就是用于显示日期的时区。

但是,您并不是真的想谈论1970年的日期……您只想格式化一个工期 持续时间是五个小时,但是您又可以返回四个小时。

一个解法

您可以使用变体gmdate()来解决这个问题,该变体始终使用GMT:

<?php
date_default_timezone_set("Etc/GMT+1"); // Setting manually for demonstration
echo gmdate('Y-m-d H:i:s', 18000); // Output always: "1970-01-01 05:00:00"
?>

您还可以通过使用PHP的面向对象的DateTime类来完全避免有限的UNIX时间戳:

<?php
$d = new DateTime('@18000');
echo $d->format('G:i:s'); // Output always: 05:00:00
?>

在上下文中

现在考虑您自己的代码。 调用strtotime$temp是UNIX时间戳,类似于上面示例中使用的日期。 当您随后使用date()时,同样的问题也适用。

gmdate()

$start_time = strtotime($_POST['t_date'].' '.$_POST['t_end'].' '.$_POST['e_ampm']);
$end_time   = strtotime($_POST['t_date'].' '.$_POST['t_start'].' '.$_POST['s_ampm']);

$temp = $end_time - $start_time;
echo gmdate('H:i:s', $temp);

使用DateTime

$start_time = strtotime($_POST['t_date'].' '.$_POST['t_end'].' '.$_POST['e_ampm']);
$end_time   = strtotime($_POST['t_date'].' '.$_POST['t_start'].' '.$_POST['s_ampm']);

$temp = $end_time - $start_time;
$temp = new DateTime('@' . $temp);
echo $temp->format('H:i:s');

希望能有所帮助。

$end_time   = new DateTime($_POST['t_date'].' '.$_POST['t_send'].' '.$_POST['s_ampm']);
$start_time = new DateTime($_POST['t_date'].' '.$_POST['t_start'].' '.$_POST['e_ampm']);
$diff       = $end_time->diff($start_time);
echo $diff->format('%H:%I:%S');

您不能在此处使用常规日期格式,因为它将$temp视为UNIX时间戳,因此会受到时区和诸如DST之类的问题的影响,例如

$e = strtotime('2011-03-31 12:30:00'); // 1301567400
$s = strtotime('2011-03-31 10:55:00'); // 1301561700
$d = $e - $s;                          //       5700
echo date(DateTime::RSS, $d);
// Thu, 01 Jan 1970 02:35:00 +0100
echo date('G:i:s', $d);
// 2:35:00

为了解决这个问题,您可以使用

$d = new DateTime('@'.$d);
echo $d->format('G:i:s');

因为DateTime与时间戳一起使用时不会考虑时区。

编辑

由于OP使用PHP 5.1.x,因此存在另一种解决方案:

$end_time   = strtotime($_POST['t_date'].' '.$_POST['t_start'].' '.$_POST['s_ampm']);
$start_time = strtotime($_POST['t_date'].' '.$_POST['t_end'].' '.$_POST['e_ampm']);
$temp       = abs($end_time - $start_time);
echo gmdate('G:i:s', $temp);

但这仅在$start_time$end_time在24小时的时间跨度内有效(除了第一个解决方案,所有提供的解决方案都一样)。

手动解决方案(但通常可以使用,并且不依赖任何日期时间处理

$end_time   = strtotime($_POST['t_date'].' '.$_POST['t_start'].' '.$_POST['s_ampm']);
$start_time = strtotime($_POST['t_date'].' '.$_POST['t_end'].' '.$_POST['e_ampm']);
$temp       = abs($end_time - $start_time);

$hours   = floor($temp / 3600);
$minutes = floor( ($temp - $hours*3600) / 60 );
$seconds = $temp - $hours*3600 - $minutes*60;
$diff    = sprintf('%d:%02d:%02d', $hours, $minutes, $seconds);

这可以轻松地延长到几天和几周。 几个月和几年会很困难,因为它们会改变一年或几十年的时间长度。

strtotime()考虑了夏令时。 这取决于当前时区。 因此,您的工期是实际的时差(考虑了小时数),而不是理论上的日差。 此功能是PHP中用于日期计算的nigmare!

如果您的PHP> = 5.3.0,可以尝试使用date_diff()

$ end_time和$ start_time变量被取反。

此外,date()还考虑了服务器时间和GMT之间的差异。

只需使用

gmdate ('G:i:s', abs($temp))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM