检查两个PHP日期时间对象是否设置为相同的日期(忽略时间)

65

我只想比较两个日期对象是否设置为相同的日期,但不关心对象的时间部分。目前我正在使用date_format命令提取类似于“Y-m-d”的字符串进行比较,但这似乎很笨拙。

$firstDate = date_format($firstDateTimeObj, 'Y-m-d');
$secondDate = date_format($secondDateTimeObj, 'Y-m-d');

if !($firstDate == $secondDate) {

// some code
}

我是编程和PHP的新手,所以任何指导都会感激。


3
我相信会有人想出一些聪明的时间戳操作之类的东西,但你真正掌握了要点。很抱歉它表述不太自然... - Brian Driscoll
1
很遗憾,PHP没有“只给我日期”的格式化选项,所以你正在做的就是最好的选择。 - Marc B
有什么问题吗?它导致了错误吗?我唯一能建议的改进是直接在对象上使用format()方法。 - liquorvicar
谢谢。至少我现在有信心,我没有不必要地复杂化问题 - PHP正在为我做这件事;-) - Dave Shaw
10个回答

75

使用对象语法!

$firstDate = $firstDateTimeObj->format('Y-m-d');
$secondDate = $secondDateTimeObj->format('Y-m-d');
你的if表达式非常接近正确,但是!操作符必须放在圆括号里面。
if (!($firstDate == $secondDate))

这也可以表达为

if ($firstDate != $secondDate)

13
通过这种方式,你将无法进行日期比较(<、<=、>等)。 - TeChn4K
3
使用DateTime对象,你将会做到。 - Amal Murali
1
这里有一个关于使用 <, == 等比较 DateTime 对象的 PHP 文档链接:http://php.net/manual/en/datetime.diff.php#example-2364。当然,它并没有解决“忽略时间”的问题 - 在比较之前将两个 DateTime 对象的时间设置为相同即可解决该问题。 - Sam
2
你也可以使用$diff=($d1->format("Ymd")-$d2->form("Ymd")),这样更加简洁。 - Andreas Dyballa
@TeChn4K:请小心!->format('Y-m-d')肯定是字符串 - 不是DateTime - 所以$firstDate == $secondDate是一个字符串比较! - Hauke
2
您可以使用任何比较运算符准确比较格式为Y-m-d的日期,因为PHP词法分析器在日期和月份有前导零时会适当地解释这些值。这相当于使用strcmp('A10', 'A02')以及字符串排序的工作方式。例如:https://3v4l.org/BfI00 然而,由于缺少前导零,您无法准确比较格式为Y-n-j的日期。例如:"A10" > "A2" = false,应使用strnatcmp('A10', 'A2') > 0 - Will B.

17

我的第一个答案完全错误,所以我开始写一个新的。

如其他答案所示,最简单的方法是使用date_format。这几乎肯定是正确的方法。然而,还有另一种方法可以利用DateTime类的全部功能。使用diff创建一个DateInterval实例,然后检查它的d属性:如果为0,则表示是同一天。

// procedural
$diff = date_diff($firstDateTimeObj, $secondDateTimeObj);

// object-oriented
$diff = $firstDateTimeObj->diff($secondDateTimeObj);

if ($diff->format('%a') === '0') {
    // do stuff
} else {
    // do other stuff
}
请注意,这几乎肯定对于这个实例来说过于复杂,但如果您想在未来进行更复杂的操作,这可能是一种有用的技术手段。

也许你能解释一下 "d" 属性是什么意思? (m:月份;d:日;h:小时;i:分钟;s:秒;) - TeChn4K
16
实际上,这种方法并不总是可行的。只有在你确信两个DateTime对象拥有相同的时间时它才有效。例如,如果你有两个日期时间,一个时间设置为2012年2月11日22:00:00,另一个设置为2012年2月12日20:00:00,由于时间相差不到24小时,它们会被认为是同一天。 - William King
1
请纠正我,如果日期时间对象相隔整整一个月,则此方法将无法奏效。例如:2013-01-25 00:00:002013-02-25 00:00:00 - Cesar
@Cesar 你是完全正确的。format('a') 是正确的代码,我认为。 - lonesomeday
3
你的格式字符串有误,DateInterval格式要求在格式字符之前加上百分号。应该是 format('%a')。请注意不要改变原意。 - VanTanev
4
如果一个日期时间是'2014-03-28 10:00',另一个是'2014-03-27 17:00',那么这也会失败。它们之间不到24小时,因此时间间隔只会显示几个小时的差异。 - Alexander Garden

16

在寻找解决方案时,我发现这个方法比使用diff或其他方法更好。

主要问题是忽略DateTime对象的时间部分,只将其设置为特定时间,例如12:00:00。

$firstDateTimeObj->setTime(12, 0, 0);
$secondDateTimeObj->setTime(12, 0, 0);

// The main problem was checking if different.. but you can use any comparison
if ($firstDateTimeObj != $secondDateTimeObj) {
}

最佳答案是使用setTime(12, 0)来检查一个日期是否早于或晚于另一个日期。这样做就足够了,因为秒和微秒会自动设置为0。 - Roubi
8
注意! $DateTimeObj->setTime(12, 0, 0); 将修改您原始的 DateTime 对象!如果您想采用此方法,请先 clone DateTime 对象,然后修改时间并比较克隆的对象。 - Alberto
重要提示:如果两个对象具有不同的时区,则它们将不被视为相等。这可能是您想要的,也可能不是。 - jlh

12

我觉得你的方法很好,但我会删除 - ,因为它们没有添加任何内容。

$firstDate = date_format($firstDateTimeObj, 'Ymd');
$secondDate = date_format($secondDateTimeObj, 'Ymd');

if ($firstDate != $secondDate) {
    // some code
}

作为Evert,它仅适用于此条件。如果您比较这些日期,它将是字符串类型。strtotime在理论上是一种更好的比较方式。 - TeChn4K
理论上 - 是的,我同意。但这非常实用 - 并且通过类型转换,这也适用于< >比较。我不建议在这种简单情况下进行任何过度比较。 - Wesley van Opdorp
我认为每个人都应该提供最佳实践建议。PHP是一种弱类型语言,也是养成坏习惯的最佳选择。 - TeChn4K

6
这对我非常有帮助。

$date1=DateTime::createFromFormat('Y-m-d H:i:s', '2014-07-31 07:30:00')->format('Y-m-d');
$date2=DateTime::createFromFormat('Y-m-d H:i:s', '2014-08-01 17:30:00')->format('Y-m-d');
if($date1==$date2){
    echo "==";
}else{
    echo "!=";
}

4

我在这里寻找相同的问题,并想出了另一种解决方法。非常简洁:

$diff = date_diff($date1,$date2);
if ($diff->days == '0') {
  /* it's the same date */
}

首先使用date_diff获得一个date_interval对象。date_interval对象具有“days”属性,您可以使用该属性获取两个日期之间的总天数。

我将其用于比较今天与注册日期,并根据成为会员的时间间隔在特定时间间隔发送电子邮件。


5
这实际上是错误的。你检查了这两个日期之间是否有一天的间隔,但并没有检查它们是否是两天。请尝试比较“1970-12-12T23:00”和“1970-12-13T00:00”。虽然时间间隔小于一天,但它们是两个不同的日期。 - anonym-developer
换句话说,如果您需要比较天数,则可以使用此方法,但如果您需要比较不到一天的时间,则无法使用。由于原始问题特别想知道是否为同一天并忽略时间,因此这种方法可行。 - Don Bryn
@DonBryn 实际上,它并没有忽略时间。在2019-01-01的23:50与2019-01-02的01:15进行比较将返回true。差异小于1天,因此$diff->days将返回0。我已经测试过了以确保其正确性。 - Tim Ogilvy

-1

快速且方便,可重复使用,可以使用多个日期,可能仍需要一些调整:

更新:不那么难看了。

if(sameDate($firstDateTimeObj, $secondDateTimeObj, $ThirdDateTimeObj))
{
   // your code

}

function sameDate (DateTime ...$dates) {

   foreach($dates as $date)
   {
      $test[] = $date->format('Ymd');
   }

   $result = array_unique($test);

   if(count($result) == 1)
   {
      return true;
   {

   return false;

}

你只是在胡闹吗? - Friedrich Roell
一定是漫长的一天,我进行了更新。还没有测试 :) - Jonathan Joosten

-1

strtotime函数将文本日期转换为Unix时间戳:http://fr.php.net/manual/zh/function.strtotime.php

$first = strtotime(date_format($firstDateTimeObj, 'Y-m-d'));
$second = strtotime(date_format($secondDateTimeObj, 'Y-m-d'));

if ($first != $second) {

// some code
}

还有:

if ($first > $second) {
// some code
}

if ($first < $second) {
// some code
}

问询者特别询问如何避免仅仅做这件事。 - lathomas64

-1
$first = strtotime(date_format($firstDateTimeObj, 'Y-m-d'));
$second = strtotime(date_format($secondDateTimeObj, 'Y-m-d'));

if ($first != $second) {
    // some code
}

1
不应该混合面向过程的方式和面向对象的方式来处理 DateTime - Raptor

-2

初始化一个 DateTime 对象并将时间设置为 00:00:00。然后您可以使用任何日期比较而忽略时间:

$today = \DateTime::createFromFormat('d/m/Y H:i:s', '21/08/2014 00:00:00');
$tomorrow = \DateTime::createFromFormat('d/m/Y H:i:s', '22/08/2014 00:00:00');

// now you can compare them just with dates
var_dump($today < $tomorrow); //true
var_dump($today === $tomorrow); //false
var_dump($today !== $tomorrow); //true

@Evert's answer works fine, but it looks like really wrong to transform a DateTime object into a string and then compare them.


1
$today !== $tomorrow; 会一直为 true,因为 $today$tomorrow 是不同的实例。即使第二个参数相同,$today === $tomorrow; 也会一直为 false。 - thomas-hiron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接