我正在尝试使用PHP的date_sun_info
函数来获取有关太阳某些位置时间的信息:
目前我使用的代码与documentation中的代码类似。
$sun_info = date_sun_info(strtotime('today'), 40.42, 74.0);
foreach ($sun_info as $key => $val) {
echo "$key: " . date("H:i:s", $val) . "<br>";
}
输出是:
sunrise: 20:50:20
sunset: 07:45:03
transit: 02:17:41
civil_twilight_begin: 20:22:45
civil_twilight_end: 08:12:38
nautical_twilight_begin: 19:51:01
nautical_twilight_end: 08:44:22
astronomical_twilight_begin: 19:19:28
astronomical_twilight_end: 09:15:55
这显然是错误的。
我不确定为什么会这样。任何帮助将不胜感激。
我原以为这与时区有关系?如果是这样我该如何纠正?服务器的时区设置为America / New_York,这将比GMT落后5小时,但即使考虑到时间也不合适,除非我计算错误。
答案 0 :(得分:4)
我认为你混淆了数字。 40.42, 74.0
翻译成Kyrgysztan山区的一个点。对于(大约)纽约,你可能意味着40.42, -74
?
至于为什么会发生这种情况,似乎该功能确实是时区敏感的,这是没有正确记录的:
相当于11小时的差异。
此时的日出时间是当地时间7:50,纽约时间20:50
答案 1 :(得分:1)
正如@Pekka评论的那样,这个功能是时区敏感的,它可以让你疯狂一段时间,直到你发现。
实际上这个函数应该有一个额外的参数来传递时区,就像date_sunrise / date_sunset一样。无论如何,作为确保所有计算都正确的解决方案,您必须始终这样做($ timezone是目标位置的tz,其中纬度/长点):
// push tz
$tz = date_default_timezone_get();
date_default_timezone_set($timezone);
$dsi = date_sun_info($timestamp, $latitude, $longitude);
// pop tz
date_default_timezone_set($tz);
结果是基于UTC的标准时间戳,您必须将$ timezone应用于结果才能获得正确的(本地)日期和时间:
$dsi_tz = new DateTimeZone($timezone);
$sunrise = new DateTime("@" . $dsi['civil_twilight_begin']);
$sunrise->setTimezone($dsi_tz);
echo $sunrise->format('Y-m-d H:i:s e');
$sunset = new DateTime("@" . $dsi['civil_twilight_end']);
$sunset->setTimezone($dsi_tz);
echo $sunset->format('Y-m-d H:i:s e');
处理时间戳和时区的经验法则是:所有时间戳必须始终以UTC为基础读取,存储和处理,并且时区必须仅在链的末尾使用,表示。混淆有偏见的时间戳使它们成为局部或添加偏移量是令人头痛的一个秘诀。
答案 2 :(得分:0)
感谢您提出这个问题,我同意您选择的@ Pekka是正确的,但我遇到了类似的问题,原因不同(您在问题中提到过),所以我想我会分享。
我发现当使用上面的相同脚本时,但是有一组不同的纬度/经度和时区,它的外观是日出/日落和黄昏值被反转。这是由于默认timezone that was set in my php.ini file不正确。这可以在ini文件的+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | canada | ALL | province,ppc | NULL | NULL | NULL | 5484 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
部分找到,可以通过输入correct timezone进行更正(如果需要)。
大多数人(包括你自己)可能会注意到时区将会立即关闭,因为存在明显的差异,但在我的辩护中,我被默认时区“UTC”和我正在寻找的时区抛弃了“太平洋/奥克兰”正好相反(时区明智)。