You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R中创建非标准轮班重复日期时间序列的技术求助

非标准轮班日期时间序列生成与事件关联(R实现)

需求与问题

需要生成A、B、C三类非标准轮班的日期时间序列,用于关联其他表的事件数据。轮班规则:

  • 以08:00为每日轮班起止点,模式为:3个交替的24小时出勤/1天休息周期,随后是96小时(4天)连续休息
  • 2022年各轮班出勤日期:
    • 结转A班:1日、3日
    • A班:8日、10日、12日、17日、19日...
    • B班:2日、4日、6日、11日、13日...
    • C班:5日、7日、9日、14日、16日...

核心问题:

  • 如何在一年内循环生成符合规则的轮班序列
  • 轮班跨午夜,无需秒级表即可关联事件(受限于美国山地时间US MST,时区调整不可行)

解决方案

思路

  1. 摒弃秒级冗余数据:仅存储轮班的start_time(当日08:00)和end_time(次日08:00),后续通过区间判断关联事件
  2. 模式化循环生成:将轮班的「3次出勤+4天休息」模式封装为函数,批量生成符合规则的出勤日期

完整代码

library(lubridate)

# 设置时区为美国山地时间
tz <- "America/Denver"

# ----------------------
# 处理结转A班(2022年1月1日、3日)
# ----------------------
carryover_A_dates <- ymd(c("2022-01-01", "2022-01-03"), tz = tz)
carryover_A <- data.frame(
  shift = "A",
  start_time = carryover_A_dates + hours(8),
  end_time = carryover_A_dates + days(1) + hours(8)
)

# ----------------------
# 封装轮班序列生成函数
# ----------------------
generate_shift_intervals <- function(start_date_str, end_date_str, shift_name, tz) {
  start_date <- ymd(start_date_str, tz = tz)
  end_date <- ymd(end_date_str, tz = tz)
  
  current_date <- start_date
  shift_dates <- c(current_date)
  
  # 按规则生成后续出勤日期:出勤→休息→出勤→休息→出勤→4天休息,循环
  while (current_date <= end_date) {
    # 第二个出勤日:间隔1天休息,+2天
    current_date <- current_date + days(2)
    if (current_date <= end_date) shift_dates <- c(shift_dates, current_date)
    # 第三个出勤日:再间隔1天休息,+2天
    current_date <- current_date + days(2)
    if (current_date <= end_date) shift_dates <- c(shift_dates, current_date)
    # 4天休息后回到出勤日:间隔5天(第三个出勤日到下一个出勤日差5天)
    current_date <- current_date + days(5)
  }
  
  # 生成每个出勤日的时间区间
  data.frame(
    shift = shift_name,
    start_time = shift_dates + hours(8),
    end_time = shift_dates + days(1) + hours(8)
  )
}

# 生成各轮班常规序列
df_A <- generate_shift_intervals("2022-01-08", "2022-12-30", "A", tz)
df_B <- generate_shift_intervals("2022-01-02", "2022-12-31", "B", tz)
df_C <- generate_shift_intervals("2022-01-05", "2023-01-01", "C", tz)

# 合并所有轮班数据并排序
df_all <- rbind(carryover_A, df_A, df_B, df_C)
df_all <- df_all[order(df_all$start_time), ]

事件关联方法

使用lubridate的%within%函数直接判断事件时间是否落在轮班区间内,无需秒级表:

# 示例事件表
events <- data.frame(
  event_id = 1:3,
  datetime = ymd_hms(c("2022-01-01 10:30:00", "2022-01-02 23:15:00", "2022-01-08 09:45:00"), tz = tz)
)

# 为事件匹配对应轮班
events$shift <- sapply(events$datetime, function(dt) {
  matches <- df_all$shift[dt %within% interval(df_all$start_time, df_all$end_time)]
  if (length(matches) == 0) NA else matches
})

方案优势

  • 数据量极小:仅存储区间起止时间,避免百万级秒级数据
  • 扩展性强:函数可快速适配其他年份或轮班规则
  • 关联高效:区间判断逻辑简单,无需时区转换即可处理跨午夜轮班

内容的提问来源于stack exchange,提问作者tbtvem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:30:18