2016-06-08 2 views
0

Одной из вещей, которая в последнее время вызвала у меня проблемы, была функция date_sun_info() от PHP. Он возвращает массив с информацией о дневном свете, такой как восход и закат солнца, а также различные фазы сумерек. Однако при использовании этой функции кажется, что PHP всегда вычисляет соответствующие параметры в хронологическом порядке. Это может создать проблему в зависимости от часового пояса, для которого вы хотите использовать эти параметры.date_sun_info() для конкретной даты календаря

Давайте рассмотрим эти два примера (при условии, что мы используем 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 

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

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

+0

Общее предупреждение всем будущим читателям, которые пытаются увеличить время, используя '86400' или' 60 * 60 * 24' или аналогичные в часовом поясе, который использует DST, вы получите или потеряете час в определенные даты и ваш результат может отрицательно сказаться. Я понимаю, что этот вопрос использует UTC (нет DST), но ответ есть. К счастью, ответ не увеличивает время, используя '86400'. Я только поднимаю этот вопрос, потому что на SO времени много экземпляров увеличивается на '86400', не подтверждая возможные последствия. – mickmackusa

ответ

0

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

Кроме того, я не уверен, что версия PHP вы используете в качестве date_sun_info возвращает associative array of timestamps , который не соответствует вашему примеру вывода.

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

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

Нет флагов (конечно, не документировано), но есть некоторые трюки. Возвращаемая метка времени - это время GMT (например, восход солнца), поэтому все, что вам нужно сделать, это применить к нему необходимый часовой пояс. 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.

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

Этот метод не будет расстроен изменениями ДСТ или Високосных лет, как вам будет, и, надеюсь, вы согласитесь, намного проще и легче читать.

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

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

Смежные вопросы