如何比较 PHP 5.2.8 中的两个 DateTime 对象?
Posted
技术标签:
【中文标题】如何比较 PHP 5.2.8 中的两个 DateTime 对象?【英文标题】:How do I compare two DateTime objects in PHP 5.2.8? 【发布时间】:2010-10-31 22:58:05 【问题描述】:查看 php 文档,DateTime
对象的以下两种方法似乎都可以解决我的问题:
这两种方法都在doco 中标记为在 >= 5.3 版本中可用(毫不奇怪,如果我尝试调用它们,我会发现它们不存在)。我找不到 5.2.8 的任何特定文档,所以我不确定我的版本中是否有等效的方法。我有Googled 的问题,并找到了一系列不拘一格的解决方案,但没有一个能满足我非常简单的要求:
如何比较两个 DateTime 对象? 在哪里可以找到以前 PHP 版本的文档?具体是 5.2.8 版?对于某些情况,我有以下代码:
$st_dt = new DateTime(verifyParam ('start_date'));
$end_dt = new DateTime(verifyParam ('end_date'));
// is the end date more ancient than the start date?
if ($end_dt < $start_dt)
显然这家伙没有比较运算符。
编辑
显然我的假设完全错误(感谢 Milen 如此有效地说明这一点)。有一个比较运算符,它工作得很好,谢谢。有时我真的很想念一个编译器。错误就在上面的代码中,我相信你会比我发现它的速度快得多:)。
【问题讨论】:
关于缺少编译器 - 将“error_reporting”设置为“E_ALL”,您会收到类似“Notice: Undefined variable: start_dt in ...”的通知。 另外,请在$_POST
变量上使用 htmlentities,否则小猫将被杀死。
错误在哪里? :p ,我也在做 U_U 。提前致谢!
@castarco 我初始化了 $st_dt ,但我与未初始化的 $start_dt 进行了比较。检查您的变量名称,也许遵循 Milen 的建议并将 error_reporting 设置为 E_ALL 以获得未定义的变量警告。 :)
【参考方案1】:
以下似乎证实了 DateTime 类有比较运算符:
dev:~# php
<?php
date_default_timezone_set('Europe/London');
$d1 = new DateTime('2008-08-03 14:52:10');
$d2 = new DateTime('2008-01-03 11:11:10');
var_dump($d1 == $d2);
var_dump($d1 > $d2);
var_dump($d1 < $d2);
?>
bool(false)
bool(true)
bool(false)
dev:~# php -v
PHP 5.2.6-1+lenny3 with Suhosin-Patch 0.9.6.2 (cli) (built: Apr 26 2009 20:09:03)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
dev:~#
【讨论】:
谢谢 Milen,看来我只是需要删除我的错误假设,突然间我的代码中明显的错误对我来说变得很明显了。 嗯,这很有趣。也许在某个时候,我们将能够在用户定义的类中重载运算符。 来自php.net/manual/en/language.operators.comparison.php 内置类可以定义自己的比较,不同的类是无法比较的,同一个类——比较属性的方式和数组一样(PHP 4),PHP 5有自己的解释跨度> 在比较一个没有设置小时的日期时间和一个设置了小时的日期时间时要小心(默认构造函数) TiMESPLiNTER,我相信警告是,如果您只对比较日期感兴趣,您可能会忽略时间不同的事实,因此两个具有相同日期的DateTime
s 不会当您认为它们应该进行比较时,它们是相等的。您可以通过在比较它们之前将对象的时间分量显式设置为零来解决此问题。【参考方案2】:
来自the official documentation:
从 PHP 5.2.2 开始,可以使用 comparison operators 比较 DateTime 对象。
$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");
var_dump($date1 == $date2); // false
var_dump($date1 < $date2); // true
var_dump($date1 > $date2); // false
对于 5.2.2 之前的 PHP 版本(实际上是任何版本),可以使用diff。
$datetime1 = new DateTime('2009-10-11'); // 11 October 2013
$datetime2 = new DateTime('2009-10-13'); // 13 October 2013
$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%a days'); // +2 days
【讨论】:
我发现这个答案最好,因为它引用了手册,而不是仅仅检查行为并假设结果符合预期。所以不是猜测的地方。布拉沃罗伯托。 @roberto DateTime::diff 仅在 PHP 5.3 中添加【参考方案3】:您还可以比较纪元秒数:
$d1->format('U') < $d2->format('U')
来源:http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (关于 DateTime 的相当有趣的文章)
【讨论】:
注意format
会产生一个字符串,所以这是一个字符串比较。在 1000000000 纪元时间之后(大约 2001 年 9 月 9 日)几乎没有问题,但是如果您必须处理日期之前,您可能会因为不同的数字长度而遇到问题。将结果转换为数字(减去它们也可以),或者使用真正可排序的格式,如c
。
@MaxArt 您能否详细说明由于字符串长度不同导致的问题?手册,关于数字上下文中的字符串:"If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float." 未来日期(大约 2038 年)可能会溢出有符号的 32 位整数,但旧日期有什么问题?
@AdrianGünter 问题是我们不会在数字上下文中,但我们会处理字符串。数字,但仍然是字符串。所以会进行 string 比较。
@MaxArt:根据文档:If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically. These rules also apply to the switch statement. The type conversion does not take place when the comparison is === or !== as this involves comparing the type as well as the value..
@FrédéricMarchal 是的,我后来确实知道我之前的评论实际上是错误的。 PHP 有一种非常邪恶的方式来处理这些情况,当你有两个要比较的字符串时,没有其他语言(据我所知)强制转换为数字。如果您真的想进行字典比较,它真的会搞砸您的代码。【参考方案4】:
如果你想比较日期而不是时间,你可以使用这个:
$d1->format("Y-m-d") == $d2->format("Y-m-d")
【讨论】:
您还可以设置重置时间。$d1->setTime(0, 0, 0);
【参考方案5】:
$elapsed = '2592000';
// Time in the past
$time_past = '2014-07-16 11:35:33';
$time_past = strtotime($time_past);
// Add a month to that time
$time_past = $time_past + $elapsed;
// Time NOW
$time_now = time();
// Check if its been a month since time past
if($time_past > $time_now)
echo 'Hasnt been a month';
else
echo 'Been longer than a month';
【讨论】:
timestamp 有一些限制,你可能想阅读这个***.com/a/7229760/2652018 很高兴知道!这只是为了一种比较时间的简单方法。【参考方案6】:从 PHP 7.x 开始,您可以使用以下内容:
$aDate = new \DateTime('@'.(time()));
$bDate = new \DateTime('@'.(time() - 3600));
$aDate <=> $bDate; // => 1, `$aDate` is newer than `$bDate`
【讨论】:
这个答案需要解释其不寻常的符号 [反斜杠和 '@'] 以及它是如何工作的 [concat '@' with result of time(), ] 答案需要包括对任何异常符号的解释,例如反斜杠、At-symbol 和宇宙飞船运算符。代码应包含有关如何工作的 cmets,例如: - 将“@”与 time() 的结果相连接,可选择减去一小时的秒数 - 实例化 DateTime 对象 - 比较 DateTime 对象,如果相等则返回 0,如果左值更大则返回 1 , 如果正确的值更大,则为 -1 [评论编辑超时窗口已过期;无法删除之前的评论]【参考方案7】:您提到DateTime::diff
比较两个日期,您可以使用它来获得比布尔值更精确的值。
例如天数:
$date1 = new DateTime('2021-07-09');
$date2 = new DateTime('2020-10-21');
echo $date1->diff($date2)->format('%R%a days');
但您也可以使用 DateTime::diff
的别名,即 date_diff
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
$date1 = new DateTime('2021-07-09');
$date2 = new DateTime('2020-10-21');
echo date_diff($date1, $date2)->format('%R%a days');
【讨论】:
【参考方案8】:这可能会对您有所帮助。
$today = date("m-d-Y H:i:s");
$thisMonth =date("m");
$thisYear = date("y");
$expectedDate = ($thisMonth+1)."-08-$thisYear 23:58:00";
if (strtotime($expectedDate) > strtotime($today))
echo "Expected date is greater then current date";
return ;
else
echo "Expected date is lesser then current date";
【讨论】:
timestamp 有一些限制,你可能想读这个***.com/a/7229760/2652018 @SteelBrain 您是否认为时间戳限制会打扰上面具有所有当前日期时间的代码,请再次阅读代码,它基本上会检查 $expectedDate 这将始终在当前月份。我认为在这种情况下我们不应该考虑这里的时间戳限制。 我知道,但这不是推荐的方式,(我没有投反对票:-)) 你能推荐一个推荐的方法吗? 当然,$today = new DateTime("now");
$time = DateTime::createFromFormat('d-m-Y',"26-October-1998");
if ($today > $time)echo "today is greater";elseecho "other time is greater";
干杯。以上是关于如何比较 PHP 5.2.8 中的两个 DateTime 对象?的主要内容,如果未能解决你的问题,请参考以下文章
PHP:如何将一个数组中的键与另一个数组中的值进行比较,并返回匹配项?