R 如何在两个不同的时间值之间提取营业时间
对于帮助台处理的票据评估,我想知道票据的有效工作时间。我可以很容易地减去时间,得到总小时数。但唯一应该计算的时间是08:30到18:00之间 例如:如果在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
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