Определяем долготу дня.

На написание этой статьи меня сподвигла очень интересная находка в библиотеках 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





Читайте также:



9 Ответов на “Определяем долготу дня.”

  1. >Самый длинный день в июне в моем городе (число): 20
    >Самый короткий день в декабре в моем городе (число): 21

    Это не только твоего города касается :)))

    Ага

  2. novice

    Эх, точно :) Спасибо :)

  3. elis

    $day_length = $sunset - $sunrise;
    для северных широт эта формула летом может давать ошибку: если закат - после полуночи, долгота дня будет отрицательна.

  4. novice

    Тогда нужно сделать так: $day_length = abs($sunset - $sunrise);

  5. elis

    это будет длительность ночи :)

    надо проверять, что больше, и если получится, что восход, добави 24 часа

    кстати, эта ошибка в [ссылка] присутствует

  6. А зачем в варианте с date_sun_info использовать foreach?
    Если все элементы массива известны, не проще ли извлекать переменные так:
    $sunrise = $sun_info[‘sunrise’];

  7. novice

    Верно :) Не помню, почему так сделал.

  8. Шедший мимо

    Потому, что в мане перебор сделан через foreach. Вы, вероятно, его оттуда скопировали.

  9. Сергей

    Для определения восхода и захода, высоты Солнца над горизонтом и других несложных астрономических задач лучше использовать простое пособие - меридианальную планисферу:
    astroexperiment.ru/sam/planispher-m.shtml


© Copyright. . I-Novice. All Rights Reserved. Terms | Site Map