代码之家  ›  专栏  ›  技术社区  ›  anonymous coward

(python)日期范围中的“Passing Go”

  •  2
  • anonymous coward  · 技术社区  · 14 年前

    更新以删除无关文本和歧义。


    员工在每个季度的次日累计8小时带薪休假。四分之一,特别是:

    • 1月1日至3月31日
    • 4月1日-6月30日
    • 7月1日-9月30日
    • 10月1日-12月31日

    问题

    def acrued_hours_between(start_date, end_date): 
        # stuff
        return integer
    

    我目前正在使用Python,并且想知道这样做的正确方法是什么。

    更新
    我认为计算有点简单,因为问题是:

    “从开始日期到结束日期累计多少小时的带薪休假?”根据上述“规则”。
    5 回复  |  直到 11 年前
        1
  •  5
  •   Alex Martelli    14 年前

    OP的编辑提到真正的潜在问题是:

    “有多少小时的带薪休假

    import datetime
    import itertools
    
    accrual_months_days = (1,1), (4,1), (7,1), (10,1)
    
    def accruals(begin_date, end_date, hours_per=8):
      """Vacation accrued between begin_date and end_date included."""
      cur_year = begin_date.year - 1
      result = 0
      for m, d in itertools.cycle(accrual_months_days):
        if m == 1: cur_year += 1
        d = datetime.date(cur_year, m, d)
        if d < begin_date: continue
        if d > end_date: return result
        result += hours_per
    
    if __name__ == '__main__':  # examples
      print accruals(datetime.date(2010, 1, 12), datetime.date(2010, 9, 20))
      print accruals(datetime.date(2010, 4, 20), datetime.date(2012, 12, 21))
      print accruals(datetime.date(2010, 12, 21), datetime.date(2012, 4, 20))
    

    一个直接的公式当然会更快,但是如果没有错误的话,这个“通过检查纠正”的例子可以自动校准更快的公式,通过检查他们在大量的日期对样本中是否一致(确保在后者中包括所有角落的情况,例如季度的第一天和最后一天)。

        2
  •  1
  •   Mark Byers    14 年前

    我会按时间顺序对某个特定员工的所有事件进行排序,并按该顺序模拟事件,检查可用的带薪休假天数从不低于零。带薪休假请求是一个值为-(小时数)的事件。1月1日有一个值为+8小时的活动。

    每次对数据进行修改时,请从头开始重新运行模拟。

    这可以通过将中间结果存储在缓存中来优化,但是由于每个员工可能只有几百个事件,所以这种优化可能没有必要。

        3
  •  1
  •   intuited    14 年前

    这可以通过简单的旧整数数学来实现:

    from datetime import date
    
    def hours_accrued(start, end):
        '''hours_accrued(date, date) -> int
    
        Answers the question "How many hours of Paid Time Off
          are accrued from X-date to Y-date?"
    
        >>> hours_accrued(date(2010, 4, 20), date(2012, 12, 21))
        80
        >>> hours_accrued(date(2010, 12, 21), date(2012, 4, 20))
        48
        '''
        return ( 4*(end.year - start.year)
            + ((end.month-1)/3 - (start.month-1)/3) ) * 8
    
        4
  •  0
  •   Ignacio Vazquez-Abrams    14 年前

        5
  •  0
  •   Avery Payne    14 年前

    住处 ). 在元组中存储季度(作为基数索引或开始日期)、一个季度的最大累计小时数和一个季度的已用小时数。您需要一组元组来进行排序,这样才能正常工作,所以简单的列表可能不是您的最佳选择。字典可能是一个更好的方法来处理这个问题,以季度作为键,在元组中返回max/used条目,因为它可以“排序”。

    (注:我看了原来的解释,改写了我的答案)

    获取给定员工的所有季度的副本,按季度日期排序。迭代每个季度,将每个季度分配的最大休假时间与该季度“花费”的时间之差相加,直到到达请求日期所在的季度。这给了累积的时间。

    如果有足够的累积时间,继续迭代复制的集合,每季度计算一次新的可用时间,从初始计算的剩余时间开始。

    如果任何季度的计算时间低于零,则立即失败并拒绝请求。否则,继续,直到你用完四分之一。

    如果计算了所有季度,则使用副本更新原始数据集并批准请求。