DateTime diff

时间:2019-01-11 15:44:26

标签: php database datetime

我正在尝试使用DateTime查找两个日期之间的天数差异。我了解还有其他几篇文章介绍了如何执行此操作。但是,运行代码时收到错误消息。我认为这可能是格式问题,但我很茫然。

如您所见,我已尝试将$ orderdate格式化为文档中建议的Y-m-d格式。它似乎正在解决问题。我想念什么吗?根据文档,这应该可以正常工作。

$orderdate = strip_tags(str_replace(array('"', "'"), "", str_replace(array("\n", "\r"), ' ', $_POST['pickupship-date'])));
$orderdate = $conn->real_escape_string($orderdate);
$orderdate = date( "Y-m-d", strtotime($orderdate) );
echo $orderdate;

date_default_timezone_set('America/Chicago');
$completiondate = date("m/d/Y");
$completiondate = date( "Y-m-d", strtotime($completiondate) );
echo $completiondate;

$duration = $orderdate->diff($completiondate);
$duration->format('%R%a days');
echo $duration;

编辑:我已经根据收到的建议更新了代码。 echo $ orderdate和echo $ completiondate完全按预期输出。但是,对于$ duration,我什么也没得到。

3 个答案:

答案 0 :(得分:0)

这是最终对我有用的代码:

$orderdate = strip_tags(str_replace(array('"', "'"), "", str_replace(array("\n", "\r"), ' ', $_POST['pickupship-date'])));
$orderdate = $conn->real_escape_string($orderdate);

$completiondate = new DateTime('now', new DateTimeZone('America/Chicago'));
$completiondate = $completiondate->format('Y-m-d');

$orderdate = new DateTime($orderdate);
$completiondate = new DateTime($completiondate);
$duration = $orderdate->diff($completiondate);
$duration = $duration->format('%R%a days');

答案 1 :(得分:0)

目前尚不清楚您想用此代码实现什么。它所做的大部分操作都不正确或不需要。

$orderdate = strip_tags(str_replace(array('"', "'"), "", str_replace(array("\n", "\r"), ' ', $_POST['pickupship-date'])));

您应该为pickupship-date字段设置固定格式。像Y-m-d(或m/d/Y,如果您更喜欢它)之类的东西坚持下去。在日期时间字段中使用引号,撇号,换行符或HTML标记没有任何意义。如果输入值与预期格式不匹配,则显示错误并在此处停止处理。

$orderdate = $conn->real_escape_string($orderdate);

仅对用于构建SQL查询的数据使用DB字符串转义功能。此操作对于您下面对$orderdate进行的操作没有任何意义。
您应该使用准备好的SQL查询来保护应用程序免受SQL注入,而不是通过转义字符串来随意转义和构建查询。

$completiondate = date("m/d/Y");
$completiondate = date( "Y-m-d", strtotime($completiondate) );

date("m/d/Y")使用m/d/Y格式将当前日期和时间格式化为字符串。
strtotime($completionDate)则相反;它将尝试将刚刚生成的字符串解析回当前时间,并返回数字(自1970-01-01 00:00:00 UTC起的秒数)。

然后,date("Y-m-d", ...)生成另一个文本格式,表示刚刚解析的日期和时间。总之,这两行与$completiondate = date('Y-m-d');

相同
$duration = $orderdate->diff($completiondate);

这是完全错误的。 $orderdate是一个字符串,它没有diff()方法(它没有任何方法,字符串不是PHP中的对象)。
此外,DateTime::diff()需要另一个DateTime对象作为参数。

$duration->format('%R%a days');

此行是正确的(但只有在正确创建$duration且当前不会发生的情况下,此行才有效。)

您的代码应如何显示。

因为它是2019年而不是2009年,所以您应该远离旧的date & time functions(它们不知道如何处理时区,而且无论如何它们都很尴尬),并且仅使用DateTime类(和its friends)。

您需要的代码如下:

// The timezone
$tz = new DateTimeZone('America/Chicago');

// Parse the input value, get a DateTime object back, or FALSE on error
$orderDate = date_create($_POST['pickupship-date'], $tz);
if (! $orderDate) {
  // The input value does not look like a valid date
  // Display an error, stop the processing here
  // ...
}

// Get the current date & time
$processingDate = new DateTime('now', $tz);

// Compute the difference
$duration = $orderdate->diff($completionDate);

// Format the difference for display
$duration->format('%R%a days')

备注

通话:

date_create($_POST['pickupship-date'], $tz)

几乎与以下内容相同:

new DateTime($_POST['pickupship-date'], $tz)

,但如果输入值无效,它将返回FALSE
无法使用new来获取表示无效输入的值。

使用new DateTime()时,代码看起来更简洁,但只有在已经(通过其他方式)验证了传递给它的值之后,它才能按预期工作。如果输入的字符串不是有效日期,则新的DateTime对象将用1970-01-01 00:00:00或其他您不希望/期望的值初始化。

date_create()通过在输入字符串不是有效的日期和时间时返回FALSE来防止这种情况。

两种方式都接受multiple formats作为参数,包括部分日期和时间表示以及几乎所有英语文本日期时间描述(例如'yesterday noon')。

如果要为输入字符串使用固定格式,则可以使用DateTime::createFromFormat()
它使用一个附加参数(第一个参数)作为格式字符串(采用date()DateTime::format()接受的格式),并且仅在输入字符串与提供的字符串匹配时返回DateTime对象格式(否则为FALSE)。

答案 2 :(得分:0)

让您的生活变得简单,并使用DateTime类,它将为您做很多事情。 重要:date()函数返回一个字符串,而不是某些Date对象。 所以

$orderdate = date( "Y-m-d", strtotime($orderdate) );
$orderdate->diff

区别字符串而不是你想要的东西。

<?php
$_POST['pickupship-date'] = "2018-03-04";
$replaceNewLines = str_replace(array("\n", "\r"), ' ', $_POST['pickupship-date']);
//not necessary when you use prepared statements. Always use prepared statements!!!
// $replaceQuotes = str_replace(array('"', "'"), "", $replaceNewLines);
$orderdate = strip_tags($replaceNewLines);
//always use prepared statements, then you don't have to do this
//$orderdate = $conn->real_escape_string($orderdate);
// strtotime not necessary $orderdate = date( "Y-m-d ", strtotime($orderdate) );
$orderdate = new DateTime($orderdate);
echo '$orderdate :';
var_dump($orderdate->format("Y-m-d"));

date_default_timezone_set('America/Chicago');
$completiondate = new DateTime();
echo '$completiondate :';
var_dump( $completiondate->format("Y-m-d"));

$duration = $orderdate->diff($completiondate);
echo '$duration :';
var_dump($duration->format('%d days'));