何时选择DateTime而不是Timestamp?

6

由于我大部分时间都在使用php、mysql或pgsql,所以我会使用DateTime作为通用的日期API。在php中没有“Date”、“Time”、“DateTime”和“DateTimeOffset”。

随着我开发的web应用程序变得越来越复杂,我大部分时间都在使用DateTime,但有时我会想它是否真的是我想要的。 例如,当我想要存储论坛或博客文章时,有时只是想显示今天的日期,没有计算、过滤或迭代要执行...那么为什么我要使用\DateTime而不是date()函数呢?

我看到了这个话题,它提供了一些各种技术优劣的简单描述。

但它并没有真正回答这个问题。在PHP中,如果我可以使用DATE_INTERVAL API(在php中是DateInterval)和IntlDateFormatter,将2个字节多存储在DateTime对象中和数据库中是否真的会有损失呢?

此外,该帖子说unix_timestamp从1970年开始保留。但这并不合乎逻辑,一些测试也证明了这一点:

echo date('d/m/Y',time(-1));

回声'31/12/1969'!这是合理的。32位无符号整数从0到4 294 967 295,68年中只有近20亿秒,因此整数为有符号的,并且“负时间戳”必须存在!

对我来说真正重要的另一件事情是,我希望处理日期,而不是整数。DateTime是一个日期,时间戳不是!我发现时间戳唯一有意义的地方是当我想要标记文件名的时间时,因为在那种情况下时间戳就是时间戳...

然而,仍然存在一个问题:时区处理。 由于MySQL等数据库在将日期存储为DateTime时不能处理时区,因此目前我使用TimeZone集成作为“过滤和转义”的逃逸部分。

$toStoreDate = new \DateTime($_POST['date'],new DateTimeZone('UTC'));
$dao->exec('INSERT INTO mytable(mydate) VALUES (\''.$toStoreDate->format('Y-m-d h:i:s').'\')');
$toDisplayDate =new \DateTime( $dao->query('SELECT mydate FROM mytable')
    ->fetch(DAO::FETCH_ASSOC)['mydate']);
$toDisplayDate->setTimeZone(new DateTimeZone('myLocal'));

这是正确的方式吗?将一个简单的时间戳存储起来,然后获取良好的本地时间不是更好吗?


所以这里是问题的总结:

  • 在API的真正简单使用中(仅用于显示),DateTime的两个字节会有损失吗?
  • 是时候放弃unix_timestamp了吗?
  • 将一个简单的时间戳存储起来,然后获取好的本地时间不是更好吗?

可能与主题无关,但是 date() 函数只能工作到2038年。在那一年,date() 函数可能会被弃用;-) - Glavić
即使在2038年,64位系统成为标准,也不会有问题吗?如果不是这样,将Unix时间戳规范从int迁移到long int的问题是什么? - artragis
毫秒是使用长整型表示的,因为至少需要10位以上的位数才能提供今天日期的数字。 - artragis
我认为最重要的是使用你最熟悉的工具。我们的PHP系统需要与.NET进行交互,因此当DateTime可以通过更简单和基于OOP的接口完成所有操作时,时间戳就不再那么有用了。 - Rudi Visser
你能否更深入地开发互操作性问题?如果你想发布一个答案,它也可以是正确的。 - artragis
显示剩余2条评论
2个回答

4
如评论所说,我认为这主要取决于个人偏好。在今天的世界中,使用Unix时间戳和“传统的”非面向对象接口不是未来发展的方式,例如,我们不应该在数据库中使用INT数据类型以Unix时间戳格式存储日期,而应该使用数据库的本地类型,通常是DATE或DATETIME类型,它们与PHP的DateTime对象(和其他语言)几乎能够在标准转换方面自然地进行合作。
稍微详细解释一下我的意思:当你使用MySQL并将值返回到PHP时,你会得到一个ISO格式的日期字符串,其中DateTime类在其构造函数中解析,从而给你一个可立即使用的对象。相比之下,如果使用Unix时间戳路线,你将不得不使用strtotime,然后date将其转换为任何你想要的本地格式。
我之前提到过我们的PHP系统和.NET系统之间的互操作性。虽然使用时间戳没有造成具体问题,但它并不是实际的解决方案,因为我们使用的是返回DateTime值的数据库,可以直接发送。如果我们将其转换为用于PHP内部使用的unix时间戳,则还必须在发送响应时将其转换回来,或者向.NET应用程序(或者在这种情况下应该说API)发送时间戳,并在最后进行转换。通过在整个过程中使用DateTime,可以消除任何转换的需要,整个开发过程更加轻松。
最后再补充一点,正如你在帖子中提到的那样,当你使用DateTime及其相关面向对象的伙伴们,例如DateInterval、更容易的时区处理、更容易的操作和格式化等,你可以使用闪亮的东西。在我的眼中,这只是一个更容易的开发过程。
我不认为像我最初所说的那样有一个“正确”的答案,只是更多基于你自己的编码风格以及上述评论反映了我的风格的个人偏好。

DateTime的2个额外字节在API的真正简单的使用中(仅显示)是否有损失?

我完全不这么认为,尤其是PHP脚本通常运行时间很短。

是时候放弃unix_timestamp了吗?

是的 :)

存储一个简单的时间戳,然后获取良好的本地时间是否更好?

请参考上面关于数据库的评论,我认为使用Unix时间戳并不是一个“本地”的方法。你可以调用->getTimezone并将其存储在数据库中,然后在再次提取时使用->setTimezone


我非常喜欢这个答案。你在某种程度上遵循了我的观点。 除此之外,也许你忘记了DateTime :: createFromFormat允许您从unixtimestamp创建日期(并且您还可以通过format('u')或getTimestamp方法从DateTime对象获取unixtimestamp)。 - artragis
当然。我认为这个问题的根源也在于PHP提供了许多不同的方法来执行一个简单的任务。我的主要观点是使用DateTime及其本地构造函数直接从ISO格式的日期构造实例,你将从中获取到。这样,你就可以直接从实例中读取/写入。要将它作为时间戳从MySQL中读取,你需要使用createFromFormat,当你将其写回数据库时,你还需要将其格式化。在我看来,这是不必要的开销。 - Rudi Visser

1

虽然这不是你问题的确切答案,但我会选择Timestamp而不是DateTime,因为我相信使用Integer值更具成本效益(测量CPU处理时间),而不是处理DateTime值。

当我在Binary Machine上有Numbers时,我感觉更舒适,而不是有StringsObjects

人类 vs. 机器

可理解性而言,当我为计算机编写程序时,我会考虑我正在为Machine制作工作,但如果在那个层面上的抽象可以帮助人们更好地理解它,为什么我们不在Performance不是问题的情况下使用它呢?

我记不得是谁说过或者我在哪里听到过,但有人说过类似于People hate Computers, but they should hate Programmers的话,我完全同意。所以,作为一个人,我仍然尊重那台机器,并尝试制作更易于计算机理解的程序。 :)

更新:

为了更好地形象化,想象一下我们有一个处理“日期”的程序,每分钟处理10,000次,对吧?

// it LOOKS Better
$date = new DateTime();
$date->setDate(1986, 3, 24);   // March 24, 1986
echo $date->format('Y-m-d');

// it WORKS Better
echo date("Y-m-d", mktime(0, 0, 0, 3, 24, 1986));    // March 24, 1986

假设我每周需要花一个小时来查看这段代码,假设有10,000人需要全年无休地处理它,当然我不会亲自处理,这是机器的任务。
顺便说一句,我想再次强调,如果性能不是问题,那么为什么我们不让程序员更容易理解呢?如果我们需要最大限度地利用它,那么让程序员查看工作效果更好的代码,而不是外表更好看的代码! :)

1
谢谢你的回答。我会说我更喜欢“编写人类可理解程序”的观点,因为每个人都可以编写一些“计算机可理解”的东西。此外,SQL查询结果是字符串,这意味着在处理php脚本中的日期时每次都需要进行转换。而PHP并不被视为成本效益很高的语言(Java或.NET也是如此)。 - artragis
1
我已经为你的答案点赞,但还没有接受它。 我的问题是,仅使用整数处理日期、时间段等真的很混乱。用只有整数的方式计算日期间隔就像重新发明轮子,但可读性更差。 - artragis
你的评论很好,但要完全避免数据库管理问题。当你获取数据库结果时,你得到字符串。当你将数据推入查询中时,你有字符串等等。 使用DateTime数据库格式允许你(这是正确的方法)处理日期间隔并计算所有内容。因此,你将始终转换一切,而不是在脚本的每个位置保留一个表示“我是日期”的格式。 - artragis
@a_horse_with_no_name 你好,非常抱歉我误解了你的评论。老实说,我从未在日期(时间戳)列上使用过约束。我会仔细研究如何轻松完成它,但现在没有想法。再次道歉,我真的误解了你的意思。 - Mahdi
2
一个日期列本身会验证日期(在任何明智的数据库中,但在MySQL中您需要激活严格模式)。使在MySQL中验证整数更加困难的是,它不支持检查约束。因此,在数据库内部几乎没有(有效的)方法来确保数据完整性。 - user330315
显示剩余6条评论

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