R 如何在两个不同的时间值之间提取营业时间

R 如何在两个不同的时间值之间提取营业时间,r,datetime,time,R,Datetime,Time,对于帮助台处理的票据评估,我想知道票据的有效工作时间。我可以很容易地减去时间,得到总小时数。但唯一应该计算的时间是08:30到18:00之间 例如:如果在11/23/2015 10:20创建了一张票据,并在11/24/2015 17:20完成,则31个“正常”小时已经过去。我只对已经过去的营业时间(8:30到18:00)感兴趣;在这种情况下,16小时30分钟库(lubridate) library(lubridate) tickets <- data.frame(open = as

对于帮助台处理的票据评估,我想知道票据的有效工作时间。我可以很容易地减去时间,得到总小时数。但唯一应该计算的时间是08:30到18:00之间

例如:如果在
11/23/2015 10:20
创建了一张票据,并在
11/24/2015 17:20
完成,则31个“正常”小时已经过去。我只对已经过去的营业时间(8:30到18:00)感兴趣;在这种情况下,
16小时30分钟

库(lubridate)
library(lubridate)

   tickets <- data.frame(open = as.POSIXct(strptime(df$open, "%m/%d/%Y %H:%M")), 
                      closed = as.POSIXct(strptime(df$closed, "%m/%d/%Y %H:%M"))


excludeDayCount <- Vectorize(function(open, close) {

   # Check if the ticket was open and closed on the same day
   if (identical(as.Date(open), as.Date(close))) return (0)

   # All the holidays to be excluded need to be put here
   holidays <- as.POSIXct(strptime(c("12/24/2015", "12/25/2015"), 
                                  "%m/%d/%Y"))

   # Dates between open and close  
   day_seq <- floor_date(seq(open + days(1), close, by = "days"), "day")

   # Count holidays / weekend days
   return(sum(day_seq %in% holidays | wday(day_seq) %in% c(1,7)))

})

bizHrDiff <- function(open, close) {

    # Hours from the end of one work day until the start of another
    hours_between_days <- dhours(6) + dhours(8.5)

    # Number of days to exclude
    excl_days <- excludeDayCount(open, close)  
    # Number of days in include
    reg_days <- as.integer(as.Date(close) - as.Date(open)) - excl_days 



    # Total duration between dates
      span <- as.duration(interval(open, close))
      # Remove the number of holidays and weekends
      span <- span - ddays(excl_days)
      # Remove out of office hours
      span <- span - (reg_days * hours_between_days)




     # Return in hours
      return(time_length(span, unit = "hour"))


}

bizHrDiff(tickets$open, tickets$closed)

tickets我最近遇到了类似的需求,并基于上面@mvan的脚本创建了一个包。
输入需要与POSIX时间相同。
输出以秒为单位。
通过参数指定帮助台的开放时间
工作时间=c(8.5,18)


额外的holliday日尚未实施。

我已经尝试了@mvan和@Steffan Jansson的解决方案。不幸的是,它们都不适合我的需要。第一个返回不正确的信息。后者是为了满足我的需求而减速,并且没有考虑夏令时

我创建了一个更快的功能,并且考虑了夏令时。您可以指定工作时间和假日

用法

library(lubridate)


biz_hrs <- Vectorize(function(start, end, starting_time = '9:00', ending_time = '17:00', holidays = NULL){


      if(end < start){

        return(NA)

      } else {

        start_datetime <- as.POSIXct(paste0(substr(start,1,11), starting_time, ':00'))
        end_datetime <- as.POSIXct(paste0(substr(end,1,11), ending_time, ':00'))

        if(as.Date(start) == as.Date(end) & !as.Date(start) %in% holidays & !format(as.Date(start), "%u") %in% c(6,7)){ #if starting time stamp is on same day as ending time stamp and if day is not a holiday or weekend

          if(start > start_datetime & end < end_datetime){ #if starting time stamp is later than start business hour and ending time stamp is earlier then ending business hour.
            return(as.numeric(difftime(end, start), units = 'hours'))
          } else if(start > start_datetime & end > end_datetime & start < end_datetime){ #if starting time stamp is later than end business hour and ending time stamp is earlier then ending business hour.
            return(as.numeric(difftime(as.POSIXct(paste0(substr(start,1,11), ending_time, ':00')), start), units = 'hours'))
          } else if(start < start_datetime & end < end_datetime & end > start_datetime){ #if starting time stamp is earlier than end business hour and ending time stamp is later than starting business hour.
            return(as.numeric(difftime(end, start_datetime), units = 'hours'))
          } else if(start > end_datetime & end > end_datetime){ #if starting time stamp is later than end business hour and ending time stamp is later than ending business hour.
            return(0)
          } else if(start < start_datetime & end < start_datetime){ #if starting time stamp is earlier than start business hour and ending time stamp is earlier than starting business hour.
            return(0)
          } else {
            return(as.numeric(difftime(end_datetime, start_datetime), units = 'hours'))
          }

        } else { #if starting time stamp and ending time stamp occured on a different day.

          business_hrs <- as.numeric(difftime(as.POSIXct(paste0('2017-01-01', ending_time, ':00')),
                                              as.POSIXct(paste0('2017-01-01', starting_time, ':00')) #calculate business hours range by specified parameters
          ), units = 'hours')

          start_day_hrs <- ifelse(start < as.POSIXct(paste0(substr(start,1,11), ending_time, ':00')) & !as.Date(start) %in% holidays & !format(as.Date(start), "%u") %in% c(6,7), #if start time stamp is earlier than specified ending time
                                  as.numeric(difftime(as.POSIXct(paste0(substr(start,1,11), ending_time, ':00')), start), units = 'hours'), #calculate time between time stamp and specified ending time
                                  0 #else set zero
          ) #calculate amount of time on starting day
          start_day_hrs <- pmin(start_day_hrs, business_hrs) #cap the maximum amount of hours dertermined by the specified business hours
          start_day_hrs
          end_day_hrs <- ifelse(end > as.POSIXct(paste0(substr(end,1,11), starting_time, ':00')) & !as.Date(end) %in% holidays & !format(as.Date(end), "%u") %in% c(6,7), #if end time stamp is later than specified starting time
                                as.numeric(difftime(end, as.POSIXct(paste0(substr(end,1,11), starting_time, ':00'))), units = 'hours'), #calculate time between time stamp and specified starting time
                                0) #calculate amount of time on ending day
          end_day_hrs <- pmin(end_day_hrs, business_hrs) #cap the maximum amount of hours dertermined by the specified business hours
          days_between <- seq(as.Date(start), as.Date(end), by = 1) #create a vector of dates (from and up to including) the starting time stamp and ending time stamp
          business_days <- days_between[!days_between %in% c(as.Date(start), as.Date(end)) & !days_between %in% holidays & !format(as.Date(days_between), "%u") %in% c(6,7)] #remove weekends and holidays from vector of dates

          return(as.numeric(((length(business_days) * business_hrs) + start_day_hrs + end_day_hrs))) #multiply the remaining number of days in the vector (business days) by the amount of business hours and add hours from the starting and end day. Return the result

        }

      }


    })
该函数接受5个参数。其中3个是可选的

  • 开始时间戳(POSIXct)
  • 结束时间戳(POSIXct)
  • 工作日的开始时间(字符串:“00:00”到“24:00”)
  • 工作日的结束时间(字符串:“00:00”到“24:00”)
  • 假日列表(日期列表(as.Date))
  • 示例:

    start <- as.POSIXct('2014-09-27 10:12:37', tz = 'Europe/Amsterdam')
    end <- as.POSIXct('2016-12-10 20:04:18', tz = 'Europe/Amsterdam')
    
    biz_hrs(start, end, '10:00', '17:00')
    
    start-end_-datetime&end>end_-datetime){如果开始时间戳晚于结束营业时间,而结束时间戳晚于结束营业时间。
    返回(0)
    }else if(开始<开始_datetime&结束<开始_datetime){如果开始时间戳早于开始营业时间,而结束时间戳早于开始营业时间。
    返回(0)
    }否则{
    返回值(如.numeric(difftime(end\u datetime,start\u datetime),单位='hours'))
    }
    }否则{#如果开始时间戳和结束时间戳发生在不同的一天。
    
    营业时间您应该给我们一些数据和预期输出。假设一张票是在2015年11月23日10:20创建的,并在2015年11月24日17:20完成的。31个“正常”时间已经过去了。但我只对已经过去的营业时间感兴趣。因此,在本例中为16小时30分钟。我目前有一个.csv文件,其中包含创建的colums日期和日期te以此处使用的格式完成。感谢mvan提供的脚本。我问问题时可能不够透彻。因为我们的服务台在周末和国定假日关闭。查看您的脚本时,我还有一个问题。当我将csv文件添加到数据框时,此脚本是否会计算所有ti在文件中自动检查工作时间?@M.Vennemans尝试此更新的代码。您可能希望为所有即将出现的紧急情况构建单元测试。我还假设您不会在办公时间之外打开/关闭票据,这需要更多的调整。再次感谢您的脚本。当我运行您的cod时确实,它工作得很好。但是因为我有很多罚单,我无法在代码中逐个输入它们,所以我将csv文件加载到R中。但是当我再次执行代码时,它不会返回任何内容。你可能知道我做错了什么吗?过去两天我一直在玩它,但到目前为止我无法解决问题。(我对R还是一个新手,所以非常感谢所有的帮助:)@m.Vennemans抱歉,我需要更多的信息。你得到了什么错误?你能分享文件的几行吗?我怀疑你需要使用类似
    df$open的东西来转换包含日期的列。这是我用来读取两个变量的数据帧(341 obs.)的内容(打开,关闭)。数据帧称为“TicketOpenClose”。TicketOpenClose