Определяем долготу дня.
На написание этой статьи меня сподвигла очень интересная находка в библиотеках PHP. Нет, мы не будем писать сложный математический алгоритм определения времени восхода и захода солнца! Мы просто используем интересные функции в PHP5, на которые я совсем недавно наткнулся. |
Итак, оказывается, в пхп начиная с версии 5 в дополнение к функциям по работе с временем есть две функции для определения времени восхода и захода Солнца. Да-да, вы не ослышались, такие функции есть И сейчас я поделюсь своей находкой с вами.
date_sunrise
Эта функция позволяет определять время в часах, минутах и секундах, когда произойдет восход солнца. Хм, подумать только… да не. Не думать надо, а пробовать:
$date = strtotime("2008-06-10");
$latitude = 54.283; // северная широта - знак плюс, южная - минус
$longitude = 48.25; // восточная долгота - плюс, западная - минус
$sunrise = date_sunrise(
$date, // Метка времени (даты)
SUNFUNCS_RET_TIMESTAMP, // Возвращаем тоже метку
$latitude,
$longitude
);
?>
Что это я тут написал? В общем, сначала мы преобразуем желаемую дату -06-10, т.е. 10 июня г., в метку времени (количество секунд от какой-то стартовой даты по-моему) с помощью функции strtotime. Потом нам, естественно, нужно задать широту и долготу места на земле, у которого мы хотим определить время восхода и захода Солнца. Конечно, задаем это дело в градусах. Я задал координаты своего местонахождения.
Вы же можете определить координаты своего города либо с помощью GPS, если таковой есть, либо с помощью полезного ресурса https://travel.org.ua/sunrise/coordinates.php. На худой конец можно взять атлас и примерно там прикинуть, какие у вас координаты (вспомним немного географию ).
Второй параметр функции говорит о том, что мы хотим вернуть метку времени вместо текстовой строки. Если бы мы хотели, чтобы функция вернула строку, вторым параметром мы бы указали SUNFUNCS_RET_STRING. Тогда она вернула бы не число, а что-то вроде «8:30».
Далее, чтобы превратить метку времени с строку, делаем так:
echo ‘Sunrise: ‘.date(‘H:i:s’, $sunrise);
Функция date вернет текстовое представление метки времени, в данном случае в формате ЧЧ:ММ:СС. Это мы определили время восхода Солнца там где я нахожусь 10 июня г.
Если бы мы указали вторым параметром функции date_sunrise SUNFUNCS_RET_STRING, то преобразовывать метку времени с помощью функции date нам бы не пришлось. Но учтите при этом, что функция в этом случае вернет время без учета летнего. Поэтому, чтобы учитывать переход на летнее время, используем функцию date.
date_sunset
Эта функция аналогична предыдущей, только возвращает время захода Солнца:
$date = strtotime("2008-06-10");
$latitude = 54.283;
$longitude = 48.25;
$sunrise = date_sunset(
$date, // Метка времени (даты)
SUNFUNCS_RET_TIMESTAMP, // Возвращаем тоже метку
$latitude, // Широта
$longitude // Долгота
);
?>
Теперь, чтобы вычислить долготу дня, что нам нужно? Правильно! Нужно из времени захода вычесть время восхода. Итак, приведем здесь исходный код:
$date = strtotime("2008-06-10");
$latitude = 54.283;
$longitude = 48.25;
$sunrise = date_sunrise($date, SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude);
$sunset = date_sunset($date, SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude);
echo 'Sunrise: '.date('H:i:s', $sunrise);
echo '<br>';
echo 'Sunset: '.date('H:i:s', $sunset);
echo '<br>';
$day_length = $sunset - $sunrise;
echo gmdate("H:i:s", $day_length);
?>
Запустив приведенный скрипт, я получил вот такой результат:
Sunrise: 04:13:18
Sunset: 21:19:48
17:06:30
Т.е. долгота дня в моем городе 10 июня года - 17 часов 6 минут. Заметим, что для превращения метки времени в строку мы использовали функцию gmdate - возвращает результат по Гринвичу (GMT). А почему не использовали date? Попробуйте и увидите
Вот и все! Это все, что я … стоп. Нет, еще не все! Я еще одну функцию откопал:
date_sun_info
Эта функция позволяет определять время восхода и захода Солнца, в какой час и минуту Солнце будет в зените в заданный день, время начала и окончания сумерек.
Однако эта функция появилась в версии PHP 5.1.2. У меня 5.2.0, поэтому могу смело экспериментировать:
$sun_info = date_sun_info(strtotime(“2008-06-10″), 48.25, 54.283);
Замечу, что в этой функции долгота и широта меняются местами в параметрах. Второй параметр - долгота, третий - широта. Эта функция возвращает массив с информацией, которую мы можем получить следующим образом:
$sun_info = date_sun_info(strtotime("2008-06-10"), 48.25, 54.283);
foreach ($sun_info as $key => $val) {
if ($key == 'sunrise') {
$sunrise = $val;
echo 'Восход: '.date("H:i:s", $sunrise).'<br>';
}
if ($key == 'sunset') {
$sunset = $val;
$day_length = $sunset - $sunrise;
echo 'Заход: '.date("H:i:s", $sunset).'<br>';
echo 'Долгота дня: '.gmdate("H:i:s", $day_length).'<br>';
}
if ($key == 'transit') {
echo 'В зените: '.date("H:i:s", $val).'<br>';
}
if ($key == 'civil_twilight_begin') {
echo 'Начало утренних сумерек: '.date("H:i:s", $val).'<br>';
}
if ($key == 'civil_twilight_end') {
echo 'Конец вечерних сумерек: '.date("H:i:s", $val).'<br>';
}
}
?>
Ну-ка, запустим:
Восход: 04:13:18
Заход: 21:19:48
Долгота дня: 17:06:30
В зените: 12:46:33
Начало утренних сумерек: 03:18:54
Конец вечерних сумерек: 22:14:12
Во! Интересно же? А может даже и полезно. Хотя мне лично ни разу еще не приходилось определять долготу дня. Я до этого только в календарик отрывной смотрел. Теперь могу сам определить долготу. И вы тоже кстати
Да, а почему бы нам не посмотреть, какой самый длинный и какой самый короткий день в этом году? Да легко! Только учтем наши знания о том, что самый длинный день в июне, а самый короткий - в декабре, и не будем перебирать остальные месяцы.
// Определяем самый длинный день в июне
$long_day = 0;
$day_len = 0;
for ($i = 1; $i <= 30; $i++) {
$date = '2008-06-'.$i;
$sun_info = date_sun_info(strtotime($date), 48.25, 54.283);
foreach ($sun_info as $key => $val) {
if ($key == 'sunrise') {
$sunrise = $val;
}
if ($key == 'sunset') {
$sunset = $val;
$day_length = $sunset - $sunrise;
if ($day_length > $day_len) {
$day_len = $day_length;
$long_day = $i;
}
}
}
}
echo 'Самый длинный день в июне в моем городе (число): '.$long_day.'<br>';
echo '<br>';
// Определяем самый короткий день в декабре
$short_day = 0;
$day_len = 0;
for ($i = 1; $i <= 31; $i++) {
$date = '2008-12-'.$i;
$sun_info = date_sun_info(strtotime($date), 48.25, 54.283);
foreach ($sun_info as $key => $val) {
if ($key == 'sunrise') {
$sunrise = $val;
}
if ($key == 'sunset') {
$sunset = $val;
$day_length = $sunset - $sunrise;
if ($day_length < $day_len || $i == 1) {
$day_len = $day_length;
$short_day = $i;
}
}
}
}
echo 'Самый короткий день в декабре в моем городе (число): '.$short_day.'<br>';
echo '<br>';
?>
А вот и результат:
Самый длинный день в июне в моем городе (число): 20
Самый короткий день в декабре в моем городе (число): 21
Вот теперь это все, чем я хотел поделиться с вами в этой статье. Теперь можете поэкспериментировать со своими координатами ?
P.S. Кстати я нашел в интернете пару ресурсов, где можно посмотреть то же самое, что и мы теперь умеем:
https://www.timezone.ru/suncalc.php
https://travel.org.ua/sunrise/index.php
>Самый длинный день в июне в моем городе (число): 20
>Самый короткий день в декабре в моем городе (число): 21
Это не только твоего города касается :)))
Ага
Эх, точно Спасибо
$day_length = $sunset - $sunrise;
для северных широт эта формула летом может давать ошибку: если закат - после полуночи, долгота дня будет отрицательна.
Тогда нужно сделать так: $day_length = abs($sunset - $sunrise);
это будет длительность ночи
надо проверять, что больше, и если получится, что восход, добави 24 часа
кстати, эта ошибка в [ссылка] присутствует
А зачем в варианте с date_sun_info использовать foreach?
Если все элементы массива известны, не проще ли извлекать переменные так:
$sunrise = $sun_info[‘sunrise’];
Верно Не помню, почему так сделал.
Потому, что в мане перебор сделан через foreach. Вы, вероятно, его оттуда скопировали.
Для определения восхода и захода, высоты Солнца над горизонтом и других несложных астрономических задач лучше использовать простое пособие - меридианальную планисферу:
astroexperiment.ru/sam/planispher-m.shtml