【问题标题】:Given two timestamps, how do I return the delta in terms of "business minutes"给定两个时间戳,我如何以“营业时间”的形式返回增量
【发布时间】:2016-10-27 00:35:27
【问题描述】:

为此寻找一个干净的函数,最好是在 Pandas/Numpy 中。我目前正在从 Pandas 的 CustomBusinessHour() 和 TimeDelta() 函数中构建一些混乱的东西,但我认为必须有更好的方法。如果 Pandas 有 CustomBusinessMinute() 功能,这将像 len(pd.date_range(timestamp1,timestamp,freq=CustomBusinessMinute())) 一样简单。

我所说的“商务会议纪要”是指符合特定标准的会议纪要。例如,在我的情况下,这意味着 1) 不在周末,2) 在上午 9 点到下午 5 点之间,以及 3) 不在联邦假日。

谢谢

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    考虑以下几点:

    您只需仔细检查开始日期和结束日期的各个方面。 IE 仔细计算这两天的工作时间。

    对于中间的每隔一个日期,您只需要知道一件事或几件事 (1) 如果是工作日,并且如果是:(2) 是联邦假日

    对于日期范围内的每个合格日期,您确切知道每天有多少“工作时间”:480 分钟。

    Pandas 提供了一种根据美国联邦假期获取工作日的方法。这可以解决最困难的部分。其余的应该很容易实现。

    可能有一种更优雅的方式,但可以从这里开始。大多数代码用于处理开始日期和结束日期。中间的所有分钟大约是 4 行。

    from dateutil.relativedelta import relativedelta
    import pandas as pd
    from pandas.tseries.offsets import CDay
    from pandas.tseries.holiday import USFederalHolidayCalendar
    
    business_day = CDay(calendar=USFederalHolidayCalendar())
    
    def is_weekday(dt):
        return dt.weekday() < 5
    
    def is_holiday(dt):
        return not len(pd.date_range(dt, dt, freq=business_day))
    
    def weekend_or_holiday(dt):
        '''helper function'''
        if not is_weekday(dt):
            return True
        if is_holiday(dt):
            return True
        return False
    
    def start_day_minutes(dt, end_of_day=None):
        '''returns number of business minutes left in the day given a start datetime'''
        if not end_of_day:
            end_of_day = dt.replace(hour=17, minute=0)
        if dt > end_of_day or weekend_or_holiday(dt):
            return 0
        num_of_minutes = (end_of_day - dt).seconds / 60
        return num_of_minutes
    
    def end_day_minutes(dt):
        '''like start_day_minutes, but for the ending day.'''
        start_of_day = dt.replace(hour=9, minute=0)
        if dt < start_of_day or weekend_or_holiday(dt):
            return 0
        num_of_minutes = (dt - start_of_day).seconds / 60
        return num_of_minutes
    
    def business_minutes(t1, t2):
        '''returns num of busniess minutes between t1 and t2'''
        start = t1.replace(hour=0, minute=0) + relativedelta(days=1)
        end = t2.replace(hour=0, minute=0) + relativedelta(days=-1)
        days_between = pd.date_range(start, end, freq=business_day)
        minutes_between = (len(days_between) * 480)
        if (t1.year, t1.day) == (t2.year, t2.day):
            start_end_minutes = start_day_minutes(t1, t2)
        else:
            start_end_minutes = start_day_minutes(t1) + end_day_minutes(t2)
    
        minutes = minutes_between + start_end_minutes
        return minutes
    

    例子:

    start=datetime(2016,1,1)
    end=datetime(2017,1,1)
    print(business_minutes(start,end))
    #120480
    

    【讨论】:

    • 感谢您的回复!我最终使用了适合我用例的不同解决方案,在此处发布
    【解决方案2】:

    我最终手动编码了我的假期,并基于 pd.date_range 编写了一个简单的函数

    def isDuringBiz(t):
    if (t.hour <= 8 or t.hour >= 17) or t.dayofweek in (5,6) or (t.day == 5 and t.month == 9):
        return False
    else:
        return True
    
    def getBizTimedelta(start, end):
    bizMinutes = 0
    minRange = pd.date_range(start,end,freq='1min')
    for min in minRange:
        if isDuringBiz(min):
            bizMinutes += 1
    return pd.Timedelta(minutes=bizMinutes)
    

    【讨论】:

      猜你喜欢
      • 2012-11-05
      • 2020-03-31
      • 2020-08-11
      • 1970-01-01
      • 1970-01-01
      • 2020-11-18
      • 1970-01-01
      • 2019-07-14
      • 1970-01-01
      相关资源
      最近更新 更多