确定日期/时间间隔是否跨R中午

时间:2020-06-30 23:43:13

标签: r lubridate

我有一个df,描述了整个夏天鸟类对鸟巢的造访次数。其中包括每次访问的开始时间和结束时间(POSIXct)。

df <- read.csv(text="
starttime,endtime,duration
2015-03-23 11:07:10,2015-03-23 17:57:10,420    
2015-03-31 22:47:10,2015-04-01 06:47:10,490    
2015-04-11 23:47:10,2015-04-12 06:17:10,400    
2015-04-14 00:07:10,2015-04-15 06:27:10,1830   
2015-06-23 02:17:10,2015-06-25 04:07:10,3000", stringsAsFactors=FALSE)
df$starttime <- as.POSIXct(df$starttime)
df$endtime <- as.POSIXct(df$endtime)

我需要确定的是,无论访问的日期是什么,每次访问是否都跨越中午时间(12:00)。在进行多日访问时,我还需要确定中午经过的次数。

我不知所措。想法?

2 个答案:

答案 0 :(得分:4)

这是一个可以在dplyr的帮助下计数中午数的功能

count_noons <- function(start, end) {
  stopifnot(all(start<end))
  full_days <- pmax(0, date(end) - date(start) - 1)
  full_days + (lubridate::hour(start) <=12) + (lubridate::hour(end) >=12) - (date(start)==date(end))
}

with(df, count_noons(starttime, endtime))

基本思想是,我看第一天和最后一天是否已经过了中午(但如果开始和结束在同一天,则不要重复计算),然后加上开始之间的天数差然后结束(因为每天一整天都是中午)

我测试了更多案例

df <- read.csv(text="
starttime,endtime
2015-03-23 11:07:10,2015-03-23 17:57:10
2015-03-31 22:47:10,2015-04-01 06:47:10
2015-04-11 23:47:10,2015-04-12 06:17:10
2015-04-12 13:47:10,2015-04-12 19:17:10
2015-04-14 00:07:10,2015-04-15 06:27:10
2015-06-23 02:17:10,2015-06-25 04:07:10
2015-06-23 02:17:10,2015-06-25 14:07:10", stringsAsFactors=FALSE)
df$starttime <- as.POSIXct(df$starttime)
df$endtime <- as.POSIXct(df$endtime)

然后我得到

transform(df, noons=count_noons(starttime, endtime))
#             starttime             endtime noons
# 1 2015-03-23 11:07:10 2015-03-23 17:57:10     1
# 2 2015-03-31 22:47:10 2015-04-01 06:47:10     0
# 3 2015-04-11 23:47:10 2015-04-12 06:17:10     0
# 4 2015-04-12 13:47:10 2015-04-12 19:17:10     0
# 5 2015-04-14 00:07:10 2015-04-15 06:27:10     1
# 6 2015-06-23 02:17:10 2015-06-25 04:07:10     2
# 7 2015-06-23 02:17:10 2015-06-25 14:07:10     3

答案 1 :(得分:2)

format(df$starttime, format = "%p") == "AM" & format(df$endtime, format="%p") == "PM"
# [1]  TRUE FALSE FALSE FALSE FALSE

这可能对语言环境敏感,因此您可能需要对此稍加小心。

AM <- format(as.POSIXct("2020-01-01 06:00:00"), format = "%p")
format(df$starttime, format = "%p") == AM & format(df$endtime, format="%p") != AM
# [1]  TRUE FALSE FALSE FALSE FALSE

要获取中午的次数,我们可以将该技术与“天数”相结合:

round(difftime(df$endtime, df$starttime, units="days"), 0)
# Time differences in days
# [1] 0 0 0 1 2

获得

pmax(+(format(df$starttime, format = "%p") == AM & format(df$endtime, format="%p") != AM),
     round(difftime(df$endtime, df$starttime, units="days"), 0))
# [1] 1 0 0 1 2