#php #time
#php #время
Вопрос:
Я рассмотрел несколько вопросов и ответов здесь, на SO, но, похоже, я не могу в этом разобраться. По сути, я пытаюсь проверить, наступила ли ночь в определенном месте (широта / lng) в определенное время.
До сих пор мне удавалось получить время восхода и захода солнца в определенном месте, а затем я пытаюсь сравнить его с текущим временем. У меня немного ситуация с Золушкой, когда все работает нормально, пока не пробьет полночь.
Я создаю свои переменные для сравнения следующим образом:
$currenttime = DateTime::createFromFormat('Y-m-d H:i', $templooptime);
$sunsettime = DateTime::createFromFormat('Y-m-d H:i', $sunsetfinal);
$sunrisetime = DateTime::createFromFormat('Y-m-d H:i', $sunrisefinal);
Я делаю простой оператор IF следующим образом:
if ($currenttime>$sunsettime) {
$nightminutes ;
}
Это выводит следующее:
Current Time:2020-09-22 23:58:00| Location: 50.1776906598,-51.077228098126 | Sunset Start: 2020-09-22 18:48:00 |Sunrise Start: 2020-09-22 06:45:00 | Night:287
Current Time:2020-09-22 23:59:00| Location: 50.202093865458,-50.984342445684 | Sunset Start: 2020-09-22 18:47:00 |Sunrise Start: 2020-09-22 06:44:00 | Night:288
Current Time:2020-09-23 00:00:00| Location: 50.226422634856,-50.891362177619 | Sunset Start: 2020-09-23 18:45:00 |Sunrise Start: 2020-09-23 06:46:00 | Night:0
Current Time:2020-09-23 00:01:00| Location: 50.25067682914,-50.798287405434 | Sunset Start: 2020-09-23 18:44:00 |Sunrise Start: 2020-09-23 06:45:00 | Night:0
Когда я меняю логику на:
if ($currenttime>$sunsettime amp;amp; $currenttime<$sunrisetime) {
$nightminutes ;
}
Он выводит:
Current Time:2020-09-22 23:58:00| Location: 50.1776906598,-51.077228098126 | Sunset Start: 2020-09-22 18:48:00 |Sunrise Start: 2020-09-22 06:45:00 | Night:0
Current Time:2020-09-22 23:59:00| Location: 50.202093865458,-50.984342445684 | Sunset Start: 2020-09-22 18:47:00 |Sunrise Start: 2020-09-22 06:44:00 | Night:0
Current Time:2020-09-23 00:00:00| Location: 50.226422634856,-50.891362177619 | Sunset Start: 2020-09-23 18:45:00 |Sunrise Start: 2020-09-23 06:46:00 | Night:0
Current Time:2020-09-23 00:01:00| Location: 50.25067682914,-50.798287405434 | Sunset Start: 2020-09-23 18:44:00 |Sunrise Start: 2020-09-23 06:45:00 | Night:0
Как я могу решить эту проблему?
ОБНОВЛЕНИЕ, устанавливающее время захода солнца на один день вперед в соответствии с ответом RO, все еще имеет эту проблему:
Current Time:2020-09-22 23:59:00 | Location: 50.202093865458,-50.984342445684 | Sunset Start: 2020-09-22 18:47:00 | Sunrise Start: 2020-09-23 06:46:00 | Night:288
Current Time:2020-09-23 00:00:00 | Location: 50.226422634856,-50.891362177619 | Sunset Start: 2020-09-23 18:45:00 | Sunrise Start: 2020-09-24 06:47:00 | Night:0
Когда оно пересекает полночь, время захода солнца МЕНЬШЕ текущего времени, поэтому оно показывает false. Есть идеи?
ОБНОВЛЕНИЕ 2 Это базовый код, который я использую (выдержки):
<?php
$fulltimestampdateforloop = new DateTime('2020-09-22 23:58:00');
$coords=["50.1776906598,-51.077228098126","50.202093865458,-50.984342445684","50.226422634856,-50.891362177619","50.25067682914,-50.798287405434"];
$nightmin=0;
$offset2=2;
foreach ($coords as $value) {
$latlng = explode(",", $value);
$lat = $latlng[0];
$lng = $latlng[1];
$str_timestamp = $fulltimestampdateforloop->format('Y-m-d');
$str_flighttime =$fulltimestampdateforloop->getTimestamp();
$sunsetTime_a = (clone $fulltimestampdateforloop);
$sunriseTime_a = (clone $fulltimestampdateforloop)->add(new DateInterval('P1D'));
$sunsetStr = date_sunset($sunsetTime_a->getTimestamp(), SUNFUNCS_RET_STRING, $lat, $lng, 90,$offset2);
$sunriseStr = date_sunrise($sunriseTime_a->getTimestamp(), SUNFUNCS_RET_STRING, $lat, $lng, 90,$offset2);
$ssettime = explode(":", $sunsetStr);
$sunsetStr_h = $ssettime[0];
$sunsetStr_m = $ssettime[1];
$srisetime = explode(":", $sunriseStr);
$sunriseStr_h = $srisetime[0];
$sunriseStr_m = $srisetime[1];
$sunsetTime_e = (clone $fulltimestampdateforloop)->setTime($sunsetStr_h,$sunsetStr_m);
$sunriseTime_e = (clone $fulltimestampdateforloop)->add(new DateInterval('P1D'))->setTime($sunriseStr_h,$sunriseStr_m);
if ($fulltimestampdateforloop > $sunsetTime_e amp;amp; $fulltimestampdateforloop < $sunriseTime_e) {
$nightmin="Night";
} else{
$nightmin="Day";
}
echo 'Current Time:'.$fulltimestampdateforloop->format('Y-m-d H:i:s').' | Location: '.$lat.','.$lng.' | Sunset Start: '.$sunsetTime_e->format('Y-m-d H:i:s').' | Sunrise Start: '.$sunriseTime_e->format('Y-m-d H:i:s').' | Night or Day? : '.$nightmin."<br>";
$fulltimestampdateforloop->modify(' 1 minutes');
}
?>
Ответ №1:
Вы рассчитали время восхода солнца до захода солнца.
Смотрите Этот пример для иллюстрации:
<?php
$today = new DateTime;
$randomAfternoonTime = (clone $today)->setTime(13, 25);
$randomNightTime = (clone $today)->add(new DateInterval('P1D'))->setTime(2, 23);
// Times relevant to Amsterdam on 2020-09-23.
// Sunset happens this evening.
$sunsetTime = (clone $today)->setTime(19, 36);
// Sunrise happens tomorrow, so add one day.
$sunriseTime = (clone $today)->add(new DateInterval('P1D'))->setTime(7, 30);
echo "Sunset at:n" . $sunsetTime->format('Y-m-d H:i') . "nn";
echo "Sunrise at:n" . $sunriseTime->format('Y-m-d H:i') . "nn";
echo "Some time in the afternoon (NOT in between sunset/sunrise):n" . $randomAfternoonTime->format('Y-m-d H:i') . "nn";
echo "At night (in between sunset/sunrise):n" . $randomNightTime->format('Y-m-d H:i') . "nn";
// Shows bool(false): 13:25 is not in between sunset/sunrise.
var_dump($randomAfternoonTime->getTimestamp() > $sunsetTime->getTimestamp() amp;amp; $randomAfternoonTime->getTimestamp() < $sunriseTime->getTimestamp());
// Shows bool(true): 02:23 is in between sunset/sunrise.
var_dump($randomNightTime->getTimestamp() > $sunsetTime->getTimestamp() amp;amp; $randomNightTime->getTimestamp() < $sunriseTime->getTimestamp());
Смотрите этот 3v4l для живой демонстрации: https://3v4l.org/lLUfL
Обновить
Я взял на себя смелость провести рефакторинг вашего кода, как показано ниже. Я намеренно оставил то, что я считаю вашей логической ошибкой. Мой код выводит следующее:
Текущее время: 2020-09-22 23:58:00 Местоположение: 50.1776906598, -51.077228098126 Начало захода солнца: 2020-09-22 23:18:17 Начало восхода солнца: 2020-09-23 11:16:49 Ночью или днем? : ночь
Текущее время: 2020-09-22 23:59:00 Местоположение: 50.202093865458, -50.984342445684 Начало захода солнца: 2020-09-22 23:17:55 Начало восхода солнца: 2020-09-23 11:16:27 Ночь или день? : ночь
Текущее время: 2020-09-23 00:00:00 Местоположение: 50.226422634856, -50.891362177619 Начало захода солнца: 2020-09-23 23:15:20 Начало восхода солнца: 2020-09-24 11:17:36 Ночью или днем? : день
Текущее время: 2020-09-23 00:01:00 Местоположение: 50.25067682914, -50.798287405434 Начало захода солнца: 2020-09-23 23:14:57 Начало восхода солнца: 2020-09-24 11:17:14 Ночью или днем? : день
И 2020-09-23 00:00:00, и 2020-09-23 00: 01:00 демонстрируют проблему, когда сравнение должно производиться не по метке времени UNIX, а только по времени. Поскольку и 00: 01:00, и 00:00:00 находятся в пределах периода захода / восхода солнца («ночь»), но вы сравниваете полные даты и время. Вы близки. Дайте мне знать, если вам понадобится дополнительная помощь.
Переработанный код (с намеренно оставленной в нем ошибкой):
<?php
$referenceDateTime = new DateTime('2020-09-22 23:58:00');
$coordinates =
[
[ 50.1776906598, -51.077228098126 ],
[ 50.202093865458, -50.984342445684 ],
[ 50.226422634856, -50.891362177619 ],
[ 50.25067682914, -50.798287405434 ]
];
foreach ($coordinates as $coordinate)
{
[ $lat, $long ] = $coordinate;
$sunsetDateTime = (clone $referenceDateTime)->setTimestamp(date_sunset($referenceDateTime->getTimestamp(), SUNFUNCS_RET_TIMESTAMP, $lat, $long, 90, 2));
$sunriseDateTime = (clone $referenceDateTime)->setTimestamp(date_sunrise((clone $referenceDateTime)->add(new DateInterval('P1D'))->getTimestamp(), SUNFUNCS_RET_TIMESTAMP, $lat, $long, 90, 2));
$daySegment = ($referenceDateTime > $sunsetDateTime amp;amp; $referenceDateTime < $sunriseDateTime)?'night':'day';
echo "Current Time: {$referenceDateTime->format('Y-m-d H:i:s')}nLocation: $lat, $longnSunset Start: {$sunsetDateTime->format('Y-m-d H:i:s')}nSunrise Start: {$sunriseDateTime->format('Y-m-d H:i:s')}nNight or day? : $daySegmentnn";
$referenceDateTime->add(new DateInterval('PT1M'));
}
ОБНОВЛЕНИЕ 2
Хотел разобраться в этом сам, поэтому пошел и написал следующее, что поможет вам думать в правильном направлении:
<?php
$referenceHour = 22;
$referenceMinute = 31;
$sunsetHour = 23;
$sunsetMinute = 50;
$sunriseHour = 7;
$sunriseMinute = 30;
$referenceHour -= ($referenceHour < 12)?-12:12;
$sunsetHour -= ($sunsetHour < 12)?-12:12;
$sunriseHour -= ($sunriseHour < 12)?-12:12;
$referenceTime = ($referenceHour * 60) $referenceMinute;
$sunsetTime = ($sunsetHour * 60) $sunsetMinute;
$sunriseTime = ($sunriseHour * 60) $sunriseMinute;
$daySegment = ($referenceTime >= $sunsetTime amp;amp; $referenceTime <= $sunriseTime)?'night':'day';
echo "Reference time: " . sprintf('d:d', $referenceHour, $referenceMinute) . ", sunset time: " . sprintf('d:d', $sunsetHour, $sunsetMinute) . ", sunrise time: " . sprintf('d:d', $sunriseHour, $sunriseMinute) . ", night/day: $daySegmentn";
Комментарии:
1. А, понятно! Так должен ли я затем добавить один день к текущему времени и рассчитать восход солнца на следующий день?
2. ДА. Вы можете использовать
add
метод дляDateTime
объекта, который принимаетDateInterval
объект. Его конструктор принимает строку в определенном формате . Вы, скорее всего, хотитеP1D
. Пожалуйста, подумайте о том, чтобы отметить мой ответ как принятый, если он был полезен :).3. Идеальный. Не могу поверить, как я это пропустил, большое спасибо, Ro, действительно ценю это.
4. Просто попробовал, и та же проблема возникает после полуночи, поскольку время восхода солнца больше текущего времени.
5. Я намеренно сделал свое добавление немного многословным, чтобы вы могли видеть шаги. Они должны быть достаточно самокомментирующимися. Вы можете подключить эту логику к своему коду, и все должно быть готово. Если это сработает, то, пожалуйста, подумайте о том, чтобы отметить мой ответ как принятый 🙂