【问题标题】:date_sun_info() for a specific calendar datedate_sun_info() 用于特定日历日期
【发布时间】:2016-06-08 00:53:14
【问题描述】:

最近让我陷入困境的一件事是 PHP 的 date_sun_info() 函数。它返回一个数组,其中包含有关日光的信息,例如日出和日落,以及各种黄昏阶段。然而,当使用这个函数时,似乎 PHP 总是按时间顺序计算适当的参数。这可能会产生问题,具体取决于您想要这些参数的时区。

我们以这两个例子为例(假设我们使用 UTC 作为默认时区,即date_default_timezone_set("UTC")):

date_sun_info(strtotime("2013-01-01"),31.5,35.2)

返回

sunrise: 2013-01-01 04:38:39
sunset: 2013-01-01 14:47:28
transit: 2013-01-01 09:43:03
civil_twilight_begin: 2013-01-01 04:12:02
civil_twilight_end: 2013-01-01 15:14:05
nautical_twilight_begin: 2013-01-01 03:41:47
nautical_twilight_end: 2013-01-01 15:44:20
astronomical_twilight_begin: 2013-01-01 03:12:11
astronomical_twilight_end: 2013-01-01 16:13:56

注意所有计算参数如何巧妙地落入传递给函数的日历日期。但现在让我们看看地球另一端的价值:

date_sun_info(strtotime("2013-01-01"),-44.5,-176.2)

返回

sunrise: 2013-01-01 16:05:13
sunset: 2013-01-02 07:32:39
transit: 2013-01-01 23:48:56
civil_twilight_begin: 2013-01-01 15:28:55
civil_twilight_end: 2013-01-02 08:08:56
nautical_twilight_begin: 2013-01-01 14:41:04
nautical_twilight_end: 2013-01-02 08:56:47
astronomical_twilight_begin: 2013-01-01 13:40:01
astronomical_twilight_end: 2013-01-02 09:57:50

显然,某些参数不属于提供给函数的日历日期,而是针对指定时区计算的。 I noticed that this has thrown other people off in the past as well。但是,在某些情况下,需要获取指定日历日期的一天中不同阶段的时间。在上述示例的情况下,输出必须如下所示:

transit: 2013-01-01 00:48:26
sunset: 2013-01-01 08:32:38
civil_twilight_end: 2013-01-01 09:09:01
nautical_twilight_end: 2013-01-01 09:57:01
astronomical_twilight_end: 2013-01-01 10:58:26
astronomical_twilight_begin: 2013-01-01 14:39:57
nautical_twilight_begin: 2013-01-01 15:41:01
civil_twilight_begin: 2013-01-01 16:28:52
sunrise: 2013-01-01 17:05:10

我编写了一个自定义函数来解决这个问题:

function adjustedSunInfo($date,$lat,$lon) {
    $sinfo=date_sun_info ( strtotime($date) ,$lat,$lon );
    $sinfoMinus=date_sun_info ( strtotime($date)-86400 ,$lat,$lon );
    $sinfoPlus=date_sun_info ( strtotime($date)+86400 ,$lat,$lon );

    foreach($sinfo as $key=>$val) {
        if(date("d",$val)>date("d",strtotime($date))) { 
            $sinfo[$key]=$sinfoMinus[$key];
        } else if(date("d",$val)>date("d",strtotime($date))) { 
            $sinfo[$key]=$sinfoPlus[$key];
        }
    }

    asort($sinfo);
    return $sinfo;
}

但是,问题是是否有(未记录的)标志可以传递给 PHP - 或任何其他技巧 - 以获得所需的信息?

【问题讨论】:

  • 对所有试图在使用 DST 的时区中使用 8640060*60*24 或类似方法来增加时间的读者的一般警告,您将在特定日期增加或减少一个小时,您的输出可能会受到负面影响。我意识到这个问题使用 UTC(没有 DST),但答案确实如此。幸运的是,答案不会使用86400 增加时间。我之所以提出这一点,是因为在 SO 上有很多情况下,时间被86400 增加而没有承认可能的后果。

标签: php date datetime calendar


【解决方案1】:

我不确定我是否 100% 理解您的问题,但可能是您想多了。我自己也经常为此感到内疚。

另外,我不确定您使用哪个版本的 PHP 作为 date_sun_info 返回一个 associative array of timestamps1,这与您的示例输出不匹配。

无论如何,回答你的问题:-

是否有(未记录的)标志可以传递给 PHP - 或任何其他技巧 - 以获得所需的信息?

没有标志(当然没有记录),但有一些技巧。返回的时间戳是事件的格林威治标准时间(例如日出),因此您所要做的就是为其应用所需的时区。 DateTime classes 将使这变得容易。

作为一个例子,我将如何重写你的函数:-

/**
* Get an array of human readable times for sun events
* @param \DateTime $date A \DateTime Object set to the desired date
*                        and the correct timezone for the place in question
* @param float $lat The latitude of the place in question
* @param float $lon The longitude of the place in question
*
* @return array An associative array of human readable times sorted in chronological order.
*/

function adjustedSunInfo(\DateTime $date,$lat,$lon) {
    $sinfo=date_sun_info ($date->getTimestamp() ,$lat,$lon );

    foreach($sinfo as $key=>$val) {
        //You should check that $val isn't 1 or empty first
        $time = new \DateTime('@' . $val);
        $time->setTimezone($date->getTimeZone());
        $sinfo[$key] = $time->format('Y m d H:i:s');
    }

    asort($sinfo);
    return $sinfo;
}

$time = new \DateTime('2013-01-01', new \DateTimeZone('Pacific/Chatham'));
var_dump(adjustedSunInfo($time, -44.5, -176.2));

See it working.

您的示例位置就在查塔姆群岛附近,因此我使用了他们的时区。您需要知道相关时区才能获得准确的答案。

此方法不会像您那样因 DST 更改或闰年而受到影响,而且我希望您会同意,它更简单且更易于阅读。

我希望这有助于解决您的问题。

1.有时可能会返回 1 或空数组元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 2020-01-11
    • 1970-01-01
    • 2014-10-04
    相关资源
    最近更新 更多