2

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

规则:
员工在每个季度后的第二天累积 8 小时的带薪休假。宿舍,具体为:

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

问题
使用 python,我需要定义以下函数的内容:

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

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

我假设使用 DateTime 对象,可能还有 dateutil 模块,在这里会有所帮助,但由于某种原因,我的大脑并没有解决这个问题。

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

“从 start_date 到 end_date 有多少小时的带薪休假?” 鉴于上述“规则”。
4

5 回答 5

5

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

“从 X 日到 Y 日,有多少小时的带薪休假?”

我同意,我会以最直接和直接的方式计算,例如:

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))

直接公式当然会更快,但如果没有错误,可能会很棘手——如果没有别的,这个“通过检查纠正”示例可以通过检查它们是否同意大量样本来自动校准更快的公式日期对(确保在后者中包括所有极端情况,例如季度的第一天和最后一天)。

于 2010-06-15T00:34:33.693 回答
1

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

每次对数据进行修改时,都要从头开始再次运行模拟。

这种方法的优点是它可以检测到新事件在当时有效但导致空闲天数下降的情况,从而导致之前有效的后来的事件现在变得无效。

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

于 2010-06-14T21:48:49.013 回答
1

这可以用普通的旧整数数学来完成:

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
于 2010-06-14T23:13:43.760 回答
0

我会计算相关日期之前的所有空闲天数,然后减去之前使用的天数,以获得允许的最大天数。

于 2010-06-14T21:50:13.173 回答
0

为每个日期范围设置一个元组(我们将它们称为Quarters)。在元组中存储季度(作为基数索引,或作为开始日期)、一个季度的最大累积小时数以及一个季度的使用小时数。您将需要一组经过排序的元组以使其正常工作,因此简单的列表可能不是您的最佳选择。字典可能是解决此问题的更好方法,将季度作为键,在元组中返回最大/使用的条目,因为它可以“排序”。

(注:我查看了原始解释并重写了我的答案)

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

如果累计时间加上为请求的季度分配的时间少于请求的小时数,则立即失败并拒绝请求。否则,继续迭代到您的任务的四分之一。

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

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

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

于 2010-06-14T22:04:55.340 回答