DateTime类与本机PHP日期函数

时间:2011-12-22 14:52:03

标签: php strtotime

DateTime类确实有一些方便的方法,并且总体上优于本地PHP日期函数,如strtotimemktimestrftime(以及更多)。但是,我不应该使用它有任何缺点或原因吗?

我能想到的唯一原因是创建一个类的整个实例可能比使用一个函数更昂贵。

  • 你同意吗?
  • 将DateTime对象用于简单的东西是否有意义?
  • 还有其他缺点吗?

在这两个选项之间切换似乎有点令人困惑,所以我想要清除我应该做的事情。

我的决定有两个例子:

  • 将日期转换为本地化值
  • 计算两个日期之间的时间

4 个答案:

答案 0 :(得分:43)

如果你担心创建一个类实例是昂贵的并且它会阻碍性能,那么我担心你会在错误的树上吠叫。人们不应该考虑是否在有意义的地方使用经过验证的OO方法。如果使用DateTime类来执行某些日期计算是有意义的,那么使用它。除非你做了一些疯狂的事情,比如创建100万个DateTime对象,否则你的应用程序会觉得它并不昂贵。

DateTime很棒的原因是因为它通过在创建对象时指定时区来减轻夏令时的担忧。在日期之间获得差异或获得不同对象之间的间隔也很容易。它基本上减少了所需的担忧和编码量(但我承认它有时是错误的,希望它能在5.4版本的PHP中得到解决)。

底线 - 我总是使用它。

答案 1 :(得分:0)

出于记录目的,我在使用类DateTime时出错了。这是一个大错误。虽然它具有一些不错的功能,但是却不值得付出努力。我解释:

假设您有一个表单(带有日期选择器)并且要存储到数据库中,那么就有3种格式来表示日期。

  1. 内部,变量的类型为DateTime()
  2. 从视觉上看,显示给用户的变量是格式为dd-mm-yyyy或mm-dd-yyyy的字符串(取决于区域设置)
  3. 在数据库中,存储的变量也是yyyy-mm-dd(ANSI)格式的字符串

因此,我要处理3种不同类型的表示,用于同一类型的数据

另外,假设您要序列化(json,xml等),它就是序列化:

object(stdClass)#1 (1) {
  ["field1"]=>
  object(DateTime)#2 (3) {
    ["date"]=>
    string(26) "2018-12-02 09:14:09.216273"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(30) "America/Argentina/Buenos_Aires"
  }
}

尝试序列化是一个真正的痛苦。 我的替代方法很简单,将任何时间日期存储为字符串,并且仅在需要时才将其转换为DateTime。

object(stdClass)#3 (1) {
  ["field1"]=>
  string(19) "2018-12-02 09:14:09"
}

答案 2 :(得分:0)

与strtotime()等函数的过程方法相比,使用DateTime()使代码更具可读性。

if( strtotime( date( 'm/d/Y', strtotime( $strStartDate ) ) ) > strtotime( date( 'm/d/Y', strtotime( '+6 month', strtotime( $strEndDate ) ) ) ) ) {

vs

if( new DateTime( $strStartDate ) > ( new DateTime( $strEndDate ) )->modify( '+6 month' ) ) {

在Windows 64位开发计算机上,PHP仍为32位。它将为您提供1901年12月13日星期五20:45:54 UTC到2038年1月19日星期二03:14:07 UTC之外的日期的怪异结果。

echo ( new DateTime( '20 Jan 2038' ) )->format( 'm/d/Y' ) . PHP_EOL; // gives 01/20/2038
echo strtotime( '20 Jan 2038' ); // returns false

https://www.php.net/manual/en/function.strtotime.php#refsect1-function.strtotime-notes

  

注意:时间戳记的有效范围通常是从1901年12月13日星期五20:45:54 UTC到2038年1月19日星期二03:14:07 UTC。 (这些日期对应于32位有符号整数的最小值和最大值。)在PHP 5.1.0之前,并非所有平台都支持负时间戳,因此日期范围不得超过Unix纪元。 。这意味着例如1970年1月1日之前的日期不适用于Windows,某些Linux发行版和其他一些操作系统。对于64位版本的PHP,时间戳的有效范围实际上是无限的,因为64位可以在任一方向上代表大约2,930亿年。


我不确定夏令时是否可以通过本机日期时间功能正确处理。


与本地日期时间函数相比,我建议使用DateTime()函数。

答案 3 :(得分:0)

作为记录,为什么要使用 DateTime 类

@magallanes,您的方法很好:将所有日期和时间转换为 GMT-0,然后再将其保存到数据库(如果适用)。

然而,问题在于:您的用户是全球性的,因此您不知道他们当前的时区和夏令时法。即使您使用服务器自己的时间以 GMT-0 保存数据,您仍然不知道如何将其转换为用户的时间 - 例如,将其正确打印在他/她的声明上。如果你问用户他们在哪个时区,他们可能并不确切知道;或者他们可能忘记了最近生效的夏令时规则;或者,自上次向您提供时区信息以来,他们的政府可能已经更改了夏令时规则,因此他们现在属于不同的时区。

因此,如果用户所在的国家/地区实施了新的时区或夏令时法(发生这种情况),我们可能会遇到以下情况:
如果时间在 1 月 1 日在您的服务器上存储为格林威治标准时间 07:35,对于您的用户来说,它可能会转换为 1 月 1 日 23:35。但是明年,07:35 GMT-0 的相同服务器时间可能不再为您的用户转换为 23:35。事实上,它甚至可能转换为 2/1 月的时间。这可能在确定以下事项方面发挥重要作用:交易在哪一天结束? ... 事件发生时用户的保险单是否仍然有效?等

PHP 的 DateTime 类使用 IANA 数据库来跟踪国家/地区时区和夏令时法律的这些变化。查看 IANA 数据库 (www.iana.org/time-zones)。它是巨大的。您还将看到位于相同经度的国家/地区可能使用不同的时区,因为它们倾向于主要城市的经度。当日期和时间从一个国家/地区的当前或历史时间转换为 GMT-0 并返回时,PHP 的 DateTime 类会自动应用必要的调整。对我来说,这就是 DateTime 类最大的加分项,此外它还可以进行三层(db、code、user)之间的格式转换。