【问题标题】:DateTime()->sub/add vs DateTime->modifyDateTime()->sub/add vs DateTime->modify
【发布时间】:2017-11-29 21:05:00
【问题描述】:

我正在编写代码,它将执行 3 个查询来选择在 30 天、60 天和 90 天内过期的项目:

$arrDates = array("30"=>array(), "60"=>array(), "90"=>array());
$sDateFormat = 'Y-m-d';
$sQuery = "SELECT *
            FROM `table
            WHERE `expiry_date` BETWEEN "; // Ranges will be added later

foreach ($arrDates as $sInterval=>$arrContainer)
{
    $dtStart = new DateTime();
    $dtEnd = new DateTime();
    $sRangeStart = $dtStart->add(new DateInterval("P{$sInterval}D"))->format("{$sDateFormat} 00:00:00");
    $sRangeEnd = $dtEnd->add(new DateInterval("P{$sInterval}D"))->format("{$sDateFormat} 23:59:59");

    $arrDates[$sInterval] = fetch_all($sQuery . "'{$sRangeStart}' AND '{$sRangeEnd}'");
}

此代码可以正常工作。一位同事建议我替换 foreach 循环内的代码 带有以下内容:

$dtStart = new DateTime();
$dtEnd = new DateTime();
$dtStart->modify("+{$sInterval} days")->setTime(0, 0, 0)->format("{$sDateFormat} 00:00:00");
$dtEnd->modify("+{$sInterval} days")->setTime(23, 59, 59)->format("{$sDateFormat} 23:59:59");

$arrDates[$sInterval] = fetch_all($sQuery . "'{$sRangeStart}' AND '{$sRangeEnd}'");

他做出这一改变的理由是,这意味着不必在每个循环中实例化 2 个 DateInterval。 我不同意他的推理,主要是因为 ->modify 是一种旧的日期修改方式,我不是 100% 确信他的方式将意味着性能的提高(即使性能受到打击,我们会采取任何一种方式 可以忽略不计)。

如果有人能提供证据证明哪种方式更好(欢迎任何一种方式),我将不胜感激!

【问题讨论】:

  • 我认为,与执行查询并返回结果相比,在处理 DateTime 对象的任何一种方法上所花费的处理时间/资源都是九牛一毛。
  • 这完全正确,整个论点的基础有点傻,但我想使用较新的 add 函数而不是 modify 函数,并且“这是新方法去做”似乎对他来说不是一个足够好的理由,所以我正在寻找其他优点或缺点来看看。
  • .add().sub() 并没有那么多更新。它们是在 5.3 中添加的,而 .modify() 是在 5.2 中添加的。另外两点:(a)为什么在第二个版本中调用setTime(),而不是第一个版本? (b) 如果你真的很担心效率,你应该使用prepared statement,这样数据库就不用重复解析SQL语句了。
  • @Manngo 这是很久以前的事了,我不记得是否需要设置时间,或者为什么这样做。

标签: php datetime intervals


【解决方案1】:

这两种方式都差不多,如何编写代码只是个人喜好问题。

在我看来,$dt->modify('+5 days')$dt->add(new DateInterval("P5D")) 更具可读性

至于性能,下面是测试它的代码,结果是:

$dt->modify('+5 天') - 0.0503 秒

$dt->add(new DateInterval("P5D")) - 0.0572 秒

因此,对于问题的情况,可读代码也是 非常少更快的代码:)

<?php

    $i = 0;
    $start = microtime(true);
    while($i++ < 10000) {
        $date = new DateTime('2018-02-13');
        $date->modify('+5 days');
    }
    $end = microtime(true);

    echo $end - $start, "\n";

    $i = 0;
    $start = microtime(true);
    while($i++ < 10000) {
        $date = new DateTime('2018-02-13');
        $date->add(new DateInterval('P5D'));
    }
    $end = microtime(true);

    echo $end - $start, "\n";

【讨论】:

  • 我们谈论的是微优化,但您使用 DateTinterval 的示例较慢,因为您每次都创建一个新的 DateInterval 对象。如果在循环之外创建对象会更快。
  • 好收获! :) 没错,不用在循环中创建对象会更快。
  • @WayFarer 看起来 DateTime::modify 忽略了夏令时,所以,不,它们不一样。 DateTime::add 在这种情况下表现正确。
  • @EugeneK 我不明白你忽略 DST 的意思。如果我使用.modify('1 day'),它肯定会在 DST 期间增加 24 小时。当 1 天的 DST 发生变化时,它还会增加 24 小时。
【解决方案2】:

但是没有setTime()不一样吗?

$dtStart = new DateTime();
$dtEnd = new DateTime();
$dtStart->modify("+{$sInterval} days")->format("{$sDateFormat} 00:00:00");
$dtEnd->modify("+{$sInterval} days")->format("{$sDateFormat} 23:59:59");
$arrDates[$sInterval] = fetch_all($sQuery . "'{$sRangeStart}' AND '{$sRangeEnd}'");

【讨论】:

    猜你喜欢
    • 2016-04-26
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2016-10-09
    • 2013-09-28
    相关资源
    最近更新 更多