date_sun_info () для конкретной календарной даты

Одна вещь, которая недавно вызвала меня в неприятности, – это функция date_sun_info () PHP. Он возвращает массив с информацией о дневном свете, такой как восход и закат солнца, а также различные фазы сумерек. Однако при использовании этой функции кажется, что 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 

Обратите внимание, что все параметры cacluited аккуратно попадают в календарную дату, которая была передана функции. Но теперь давайте посмотрим на ценности для другой стороны земного шара:

 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 

Очевидно, что некоторые параметры не попадают в календарную дату, поданную в функцию, но рассчитываются для указанного часового пояса. Я заметил, что в прошлом это тоже отбросило других людей . Однако в некоторых случаях желательно получить время разных этапов дня для указанной календарной даты. В случае вышеприведенного примера вывод должен выглядеть следующим образом:

 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, или любые другие трюки, чтобы получить нужную информацию?

    Я не уверен, что я понимаю вашу проблему на 100%, но может быть, вы немного переусердствовали. Я сам часто виноват в этом.

    Кроме того, я не уверен, какую версию PHP вы используете, поскольку date_sun_info возвращает ассоциативный массив временных меток 1 , который не соответствует вашему примеру.

    В любом случае, чтобы ответить на ваш вопрос:

    есть ли (недокументированные) флаги, которые могут быть переданы на PHP, или любые другие трюки, чтобы получить нужную информацию?

    Нет флажков (конечно, не задокументированных), но есть некоторые трюки. Возвращаемая метка времени – это время GMT (например, восход солнца), поэтому все, что вам нужно сделать, это применить к нему необходимый часовой пояс. Классы DateTime сделают это легким.

    В качестве примера я хотел бы переписать вашу функцию:

     /** * 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 md 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)); по /** * 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 md 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)); - /** * 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 md 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)); 

    Смотрите, как работает .

    Ваша примерная позиция находится недалеко от островов Чатем, поэтому я использовал для этого свой часовой пояс. Вы должны знать часовой пояс, чтобы получить точный ответ.

    Этот метод не будет расстроен изменениями DST или Leap Years по вашему усмотрению, и, надеюсь, вы согласитесь, намного проще и легче читать.

    Надеюсь, это поможет решить вашу проблему.

    1. Иногда может быть возвращен 1 или пустой элемент массива.