如何判断指定月日组合是否处于日期范围(与年份无关)
问题:判断指定月日是否在跨年度日期范围内(与年份无关)
我们已经能轻松判断具体日期是否在起止日期范围内,但现在需要实现:判断指定的月日组合(如07-01)是否处于某一日期范围,且判断结果与年份无关。
示例
判断07-01(7月1日)是否在以下时间范围内:
2020-01-30 - 2020-06-15 --> 否 2020-06-16 - 2021-03-20 --> 是 2013-04-26 - 2019-02-13 --> 是(该日期范围跨多个年度,7月1日在其中的多个年度内出现)
R代码示例
# 设置随机种子 set.seed(1) # 生成测试用的日期范围数量 cases <- 10 # 生成随机天数间隔 gaps <- sort(sample(x = 1:5000, size = cases, replace = TRUE)) # 构建包含起止日期的数据框 df <- data.frame(dates_start = rev(Sys.Date() - gaps[2:cases] + 1), dates_end = rev(Sys.Date() - gaps[1:(cases-1)])) df #> dates_start dates_end #> 1 2009-06-26 2010-01-19 #> 2 2010-01-20 2011-06-05 #> 3 2011-06-06 2011-06-20 #> 4 2011-06-21 2013-04-21 #> 5 2013-04-22 2016-02-17 #> 6 2016-02-18 2016-08-05 #> 7 2016-08-06 2018-05-11 #> 8 2018-05-12 2019-10-09 #> 9 2019-10-10 2021-10-25 # 判断具体日期是否在范围内(作为对比) df$date_in_range <- df$dates_start <= lubridate::ymd("2019-07-01") & lubridate::ymd("2019-07-01") < df$dates_end # 尝试判断月日是否在范围内(伪代码,因缺少month_day函数报错) data.table::between(x = month_day("07-01"), lower = dates_start, upper = dates_end) #> Error in month_day("07-01"): could not find function "month_day" # 期望输出结果 df$monthday_in_range <- c(T, T, F, T, T, T, T, T, T) df #> dates_start dates_end date_in_range monthday_in_range #> 1 2009-06-26 2010-01-19 FALSE TRUE #> 2 2010-01-20 2011-06-05 FALSE TRUE #> 3 2011-06-06 2011-06-20 FALSE FALSE #> 4 2011-06-21 2013-04-21 FALSE TRUE #> 5 2013-04-22 2016-02-17 FALSE TRUE #> 6 2016-02-18 2016-08-05 FALSE TRUE #> 7 2016-08-06 2018-05-11 FALSE TRUE #> 8 2018-05-12 2019-10-09 TRUE TRUE #> 9 2019-10-10 2021-10-25 FALSE TRUE
解决方案
要实现这个需求,核心是处理两种场景:日期范围不跨年、日期范围跨年。以下提供两种可行方法:
方法1:基于“年中天”数值判断
利用lubridate的yday()函数将日期转换为“一年中的第几天”,然后分情况判断:
- 当起始日期的年中天 ≤ 结束日期的年中天时:目标月日的年中天需落在两者之间
- 当起始日期的年中天 > 结束日期的年中天时(范围跨年度):目标月日的年中天需≥起始年中天 或 ≤结束年中天
library(lubridate) # 定义目标月日(选非闰年的年份转换即可) target_md <- ymd("2023-07-01") target_yday <- yday(target_md) # 提取起止日期的年中天数值 df$start_yday <- yday(df$dates_start) df$end_yday <- yday(df$dates_end) # 执行判断 df$monthday_in_range <- ifelse( df$start_yday <= df$end_yday, target_yday >= df$start_yday & target_yday <= df$end_yday, target_yday >= df$start_yday | target_yday <= df$end_yday ) # 验证结果(与期望输出一致) df$monthday_in_range #> [1] TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE
方法2:将目标月日匹配到起止年度
把目标月日分别转换为起始年和结束年的完整日期,只要其中任意一个日期落在范围内,即判定符合条件:
library(lubridate) target_md <- "07-01" # 生成起始年的目标日期 target_start <- ymd(paste(year(df$dates_start), target_md, sep = "-")) # 生成结束年的目标日期 target_end <- ymd(paste(year(df$dates_end), target_md, sep = "-")) # 执行判断 df$monthday_in_range <- (target_start >= df$dates_start & target_start <= df$dates_end) | (target_end >= df$dates_start & target_end <= df$dates_end) # 验证结果 df$monthday_in_range #> [1] TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE
内容的提问来源于stack exchange,提问作者mnist
相关产品推荐
相关产品推荐

