我如何学会停止使用 strtotime() 并爱上 PHP DateTime
PHP中的DateTime类从5.2版开始就可用,但直到最近我基本上都忽略了它们。这部分是因为我经常在PHP5.1环境中工作(不要问),但主要是因为我只是习惯使用标准日期函数,这些函数一直是PHP的一部分(嗯,从版本4)。我想解释一下为什么我会从现在开始更多地使用新的DateTime类,以及为什么您应该毫不犹豫地使用它们。
使用的组合strtotime()并date()可以处理大部分事情,并且是迅速抢占日期的好方法。
echo strtotime("02/23/2013 12:00"); //打印1361620800 echo strtotime("today"); //打印1362096000 echo strtotime("2013-02-23"); //打印1362096000
但是,当字符串与strtotime()预期的不完全相同时,您可能会遇到真正的问题,尤其是在尝试解析非美国日期格式的日期时。如果日期字符串不被理解,strtotime()那么它将返回false。
var_dump(strtotime("23/02/2013"));//printsbool(false)
发生这种情况时,您可以尝试一些方法来强制strtotime()正确解析日期。有时就像将斜杠交换为破折号一样简单,这会强制strtotime()以不同的方式解析日期。
$date = "23/02/2013"; $timestamp = strtotime($date); if ($timestamp === FALSE) { $timestamp = strtotime(str_replace('/', '-', $date)); } echo $timestamp; //prints1361577600
但是,当日期字符串不仅仅包含日期时,这会变得更加复杂。获取以下日期字符串,我发现它是从我使用的Web服务返回的。
Thu,23/02/2012-15:18
尝试之前尝试替换斜杠的技巧在这里不起作用,因此需要采取进一步的步骤。在玩弄字符串几分钟后,我发现删除日期和时间之间的破折号(-)会导致strtotime()函数接受字符串并正确解析它。
$timestamp=strtotime(trim(str_replace('/','-',str_replace('-','',$date))));
正是在这一点上,我质疑我想要做什么。在我尝试解析日期字符串时,我使用了三个昂贵的字符串操作函数,只是为了尝试将日期时间字符串置于strtotime()可以理解的状态。因此,我决定找到一个更好的解决方案来解决这个问题,经过一些研究,我重新发现了PHPDateTime类。特别有趣的是一个名为DateTime::的方法createFromFormat(),它接受一个格式和一个字符串并创建一个日期对象。下面是使用该createFromFormat()方法正确解析上述日期时间值的示例。
$str_date = 'Thu, 23/02/2012 - 15:18'; $obj_date = DateTime::createFromFormat('D, d/m/Y - H:i', $str_date); echo $obj_date->getTimestamp(); //prints1330010280
我在这一切中的最终目标是简单地将一个日期与另一个日期作为usort()函数调用的一部分进行比较。我最初开始做的是将时间转换为时间戳,然后比较这些时间戳。使用PHPDateTime类,这不是必需的,因为对象可以直接比较(至少从5.2.2版开始)。这是比较两个不同DateTime对象的示例。
$str_date = 'Thu, 23/02/2012 - 15:18'; $obj_date_1 = DateTime::createFromFormat('D, d/m/Y - H:i', $str_date); $str_date = 'Thu, 08/11/2012 - 12:57'; $obj_date_2 = DateTime::createFromFormat('D, d/m/Y - H:i', $str_date); var_dump($obj_date_1 < $obj_date_2); //printsbool(true)
strtotime()最好使用DateTime类,而不是尝试将字符串破解为工作格式并将其推送到其中,以便您绝对确定从输入中获得的日期。事实上,如果您不确定日期的输入格式,那么您需要退后一步,了解为什么会这样。您必须确定将哪些输入参数传递给任何程序,如果您收到不同日期格式的混合,那么事情可能会很快出现可怕的错误。
这个createFromFormat()方法的好处是,如果你给它错误的日期格式,那么它会返回false。这意味着您在创建DateTime对象时确实有一些回旋余地,并且可以正确检测事情是否与看起来的不一样。
$str_date = 'Thu, 23/02/2012'; $obj_date = DateTime::createFromFormat('D, d/m/Y - H:i', $str_date); var_dump($obj_date); //printsbool(false)
这比使用DateTime类构造函数要健壮得多,如果为它提供无效的日期格式,它将抛出异常。这是一个使用PHPDateTime类产生异常的示例。
try { $date = new DateTime('11n5fgfgh'); } catch (Exception $e) { echo $e->getMessage(); exit(1); }
这会产生以下输出。
DateTime::__construct():Failedtoparsetimestring(11n5fgfgh)atposition0(1):Unexpectedcharacter
所有这一切的底线是,如果您正在接受用户输入(或任何类型的输入),那么在开始处理之前,您需要尽一切努力确保其格式正确。如果您正在使用Web服务并且日期格式不断变化,那么您需要告诉他们这一点,因为这确实是一种糟糕的做法。
几年前,我有维护系统的第一手经验(我没有构建它,我赶紧添加!)其中有一个函数来操作日期,但我无法确定日期的格式由于系统的不同部分记录日期不同,因此将传入。系统将调用这个单一函数并传递一个空值或四种不同日期格式中的一种。这意味着有几次strtotime()会失败并返回false,然后该date()函数将其作为1970年1月1日返回,然后将其保存回数据库。我最终不得不追踪调用这个函数的每个地方,并确保它传递了正确的值。如果我用一个DateTime()对象,然后我会确定日期是否被正确读取。