Я довольно долго размышлял над этой проблемой. Думаю, я слишком стараюсь и продолжаю бегать кругами.
Проблема
Мне нужно рассчитать часы лунного света ночью, т.е. количество времени, в течение которого луна находится над горизонтом вне дневного времени. Что известно, так это время восхода/захода солнца и восхода/захода луны в UTC для данной даты. Самый простой (гипотетический) сценарий выглядит следующим образом:
sunrise: 06:45
sunset: 18:20
moonrise: 02:30
moonset: 19:50
Алгоритм расчета лунных часов будет следующим:
if(moonrise<sunset && sunrise<moonset) {
moonlighthours = (sunrise-moonrise)-(moonset-sunset);
}
Так же легко:
sunrise: 06:45
sunset: 18:20
moonrise: 10:30
moonset: 19:50
if(moonrise>sunset && sunrise<moonset) {
moonlighthours = (moonset-sunset);
}
Но поскольку мы имеем дело с UTC, это может стать довольно сложным в зависимости от часового пояса, поскольку время восхода/захода и восхода/захода луны может быть растянуто на три разные даты:
sunrise: 2014-02-05 23:30
sunset: 2014-02-06 12:20
moonrise: 2014-02-06 11:00
moonset: 2014-03-07 00:50
Таким образом, чтобы рассчитать лунные часы на 06.02.2014, я бы попробовал что-то запутанное, например:
if(sunrise<midnight) { sunrise = midnight; }
if(sunset>midnight+24) { sunset = midnight+24; }
if(moonrise<midnight) { moonrise = midnight; }
if(moonset>midnight+24) { moonset = midnight+24 }
if(moonrise<sunset && sunrise<moonset) {
moonlighthours = (sunrise-moonrise)-(moonset-sunset);
} else if (moonrise>sunset && sunrise<moonset) {
moonlighthours = (moonset-sunset);
} else if (moonrise<sunset && sunrise>moonset) {
moonlighthours = (sunrise-moonrise);
} else {
moonlighthours=0;
}
Попытка охватить все возможные сценарии в результате фазового сдвига между лунным и дневным светом с использованием структур if... else
— это кошмар. Поэтому я надеюсь, что есть кто-то со свежим взглядом на проблему. Любая помощь будет принята с благодарностью.
ИЗМЕНИТЬ
Вот решение, которое я придумал на основе предложений @Ilmari Karonen
. Это подсчитает лунные часы в течение заданной даты календаря (используя синтаксис PHP):
$mid00 = midnight; // unixtimestamp , e.g. 1391558400 (2014-02-05 00:00:00)
$mid24 = midnight+86399; // 1399075199 (2014-02-05 23:59:59)
$mr = moonrise;
$ms = moonset;
$sr = sunrise;
$ss = sunset;
$mr = $mr < $mid00 ? $mid00 : $mr;
$ms = $ms > $mid24 ? $mid24 : $ms;
$sr = $sr < $mid00 ? $mid00 : $sr;
$ss = $ss > $mid24 ? $Mid24 : $ss;
$ml_morn = 0; // moonlight hours during morning night
$ml_even = 0; // moonlight hours during evening night
if($ms > $mr) { // moon set later than moon rise
$ml_morn = $mr < $sr ? $sr-$mr : 0; // moon rises before sunrise?
$ml_even = $ms > $ss ? $ms-$ss : 0; // moon sets after sunset?
} else { // moon set before moon rise
$ml_even = $mr > $ss ? $mid24-$mr : $mid24 - $ss; // moon rises before sunset?
$ml_morn = $ms < $sr ? $ms-$mid00 : $sr - $mid00; // moon sets before sunrise?
}
moonlight_hours = $ml_morn = $ml_even;
datetime
. И да, мне нужен лунный свет для определенных дат календаря, поскольку я имею дело с данными временных рядов, где необходимо проверить другие параметры, относящиеся к дате, на корреляцию с видимостью в ночное время. - person Tomm   schedule 06.02.2014