Требуется немало кодирования, но я думаю, что это сработает.Фактически он получает фактическое время заката и восхода из пакета suncalc
для каждого дня.
Я буду аннотировать его в ближайшее время.
Расчет для дня
Это функциявычислять день и ночь в секундах, когда начальный день и конечный день совпадают.Чтобы получить точное время восхода и захода солнца, вам нужно указать широту и долготу местоположения.
library(lubridate)
library(tidyverse)
library(suncalc)
calc_in_oneday <- function(st, ed, lon = 0, lat = 0) {
sunlight_times <- getSunlightTimes(as.Date(st), lat = lat, lon = lon)
sunset <- sunlight_times$sunset
sunrise <- sunlight_times$sunrise
sec_night <- sec_day <- 0
if(st > sunset | ed<=sunrise) { # when the period includes the night only
sec_night <- difftime(ed, st, units = "secs")
} else if(st > sunrise & ed<=sunset) { # when the period includes the daytime only
sec_day <- difftime(ed, st, units = "secs")
} else { # when things are bit more complicated
if (st<=sunrise) { # if "start" is before sunrise time until sunrise will be added to night
sec_night <- sec_night + difftime(sunrise, st, units = "secs")
} else {
# if otherwise time until sunset will be added to daytime
# in this condition "end" will come after sunset (otherwise the second condition above will be satisfied)
sec_day <- sec_day + difftime(sunset, st, units = "secs")
}
if (ed<=sunset) { # The same logic
sec_day <- sec_day + difftime(ed, sunrise, units = "secs")
} else {
sec_night <- sec_night + difftime(ed, sunset, units = "secs")
}
if(st <= sunrise & ed > sunset) { # above will not add the entire daytime when "start" before sunrise and "end" after sunset
sec_day <- sec_day + difftime(sunset, sunrise, units = "secs")
}
}
sec_night <- unclass(sec_night)
sec_day <- unclass(sec_day)
attr(sec_day, "units") <- NULL
attr(sec_night, "units") <- NULL
return(list(sec_day = sec_day, sec_night = sec_night))
}
Вложенные условия сложны.Я считаю, что это правильно, но, пожалуйста, проверьте сами.
В течение нескольких дней
Используя вышеуказанную функцию, работайте с чеком в течение нескольких дней.Эта функция проверяет, совпадают ли даты начала и окончания, и, если они не совпадают, вычисляет время дня / ночи до конца первой даты, а затем сдвигает время начала к началу следующего дня.( Редактировать : зона времени начала / окончания).
calc_day_night <- function(st, ed, lon = 0, lat = 0) {
attr(st, "tzone") <- "UTC"
attr(ed, "tzone") <- "UTC"
sec_night <- sec_day <- 0
while(as.Date(st) != as.Date(ed)) {
tmp_ed <- as.Date(st) + days(1)
day_night_oneday <- calc_in_oneday(st, tmp_ed, lon, lat)
sec_night <- sec_night + day_night_oneday$sec_night
sec_day <- sec_day + day_night_oneday$sec_day
st <- tmp_ed
}
day_night_oneday <- calc_in_oneday(st, ed, lon, lat)
sec_night <- sec_night + day_night_oneday$sec_night
sec_day <- sec_day + day_night_oneday$sec_day
return(list(sec_day = sec_day, sec_night = sec_night))
}
Тест
Используя данные теста, результаты выглядят так:
dat %>%
rowwise() %>%
mutate(temp = list(calc_day_night(start_time, end_time, lat = 41, lon = -85))) %>%
mutate(sec_day = temp$sec_day) %>%
mutate(sec_night = temp$sec_night) %>%
mutate(min_day = round(sec_day / 60)) %>%
mutate(min_night = round(sec_night / 60)) %>%
select(-matches("sec")) %>%
select(-temp)
## Source: local data frame [11 x 4]
## Groups: <by row>
##
## # A tibble: 11 x 4
## start_time end_time min_day min_night
## <dttm> <dttm> <dbl> <dbl>
## 1 2015-05-08 09:46:44 2015-05-08 11:59:44 133 0
## 2 2015-05-08 12:48:32 2015-05-08 16:15:32 207 0
## 3 2015-05-08 17:37:12 2015-05-08 18:05:12 28 0
## 4 2015-05-09 04:32:36 2015-05-09 05:55:36 26 57
## 5 2015-05-09 06:16:50 2015-05-09 08:43:50 147 0
## 6 2015-05-09 09:07:18 2015-05-09 12:51:18 224 0
## 7 2015-05-09 21:45:36 2015-05-10 01:51:36 0 246
## 8 2015-05-12 06:53:30 2015-05-12 07:02:30 9 0
## 9 2015-05-12 07:42:30 2015-05-12 11:24:30 222 0
## 10 2015-05-12 12:06:56 2015-05-12 13:24:56 78 0
## 11 2015-05-12 14:00:08 2015-05-12 16:22:08 142 0
Я гуглил латы и чикаго и использовал значения.Как видите, для некоторых записей результаты немного сместились (например, запись № 4 не совсем ночная, так как рассвет Чикаго наступил в начале лета).