两个日期之间每个工作日发生的次数

时间:2014-12-10 00:07:48

标签: python datetime

在Python中,我们说有两个日期:

date_from = datetime.date(2014,02,8)
date_to   = datetime.date(2014,12,9)

我们需要计算这两天之间每周工作日的次数。什么是解决这个问题的好方法?

例如,如果我们有:

date_from = datetime.date(2014,11,30) # Sunday
date_to   = datetime.date(2014,12,9)  # Tuesday

我正在寻找的答案是(以字符串或数字形式的星期几):

'Sunday': 2
'Monday': 2
'Tuesday': 2
'Wednesday': 1
'Thursday': 1
'Friday': 1
'Saturday': 1

5 个答案:

答案 0 :(得分:3)

试试这个:

>>> from collections import Counter
>>> weekdays = Counter()

>>> date_from = datetime.date(2014,11,30) # Sunday
>>> date_to   = datetime.date(2014,12,9)  # Tuesday

>>> for i in range((date_to - date_from).days+1):
...    weekdays[(date_from + datetime.timedelta(i))\
...                                  .strftime('%a')] += 1

>>> weekdays
Counter({'Sun': 2, 'Tue': 2, 'Mon': 2, 'Wed': 1, 'Fri': 1, 
         'Thu': 1, 'Sat': 1})

另一种观点:

def dates_between(start, end):
    while start <= end:
        yield start
        start += datetime.timedelta(1)

def count_weekday(start, end):
    counter = Counter()
    for date in dates_between(start, end):
        counter[date.strftime('%a')] += 1
    return counter

然后:

>>> count_weekday(date_from, date_to)
Counter({
    'Sun': 2, 
    'Tue': 2, 
    'Mon': 2, 
    'Wed': 1, 
    'Fri': 1, 
    'Thu': 1, 
    'Sat': 1
})

[更新]

Mark Ransom评论道:

  

真的没有必要每个人单独计算。 ......我已经给那些做得更好的人提供了投票。

我确信还有很多其他方法可以达到相同的效果,但有什么意义呢?也许有人担心表现。我不是 - 因为:

  • O(n)O(n log n)之间的差异与n的小值无关。
  • 正如古老的唐纳德·克努特所说:&#34;过早的优化是所有邪恶的根源&#34;。
  • 关于表现的问题的答案总是&#34;描述它&#34; - 不止一次,我对结果的不直观感到惊讶。

在分析之后,即使其他算法的速度提高了几毫秒:

  • 是与应用程序相关的性能差异吗?
  • 代码更易于推理吗?
  • 你能确保所有角落案件都被覆盖吗?

原始性能和简单设计之间的交易是我愿意花费大部分时间的。

答案 1 :(得分:2)

对于你的问题,我会使用@JonKiparsky的答案。他说了你需要的任何东西:

>>> date_from = datetime.date(2014,02,8)
>>> date_to   = datetime.date(2014,12,9)
>>> td = date_to - date_from
>>> td.days
304
>>> 

你只需要理性地使用它:在这个delta中你有304天,它是304/7 = 43整周和3天以上。因此,前3天(date_from 1和2)将被计为44,其他为43。

它可能比2x2更容易!:

days = {
    0: 0,
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
    6: 0,
}
full_weeks = 304 / 7   # 43
remainder = 304 % 7    # 3
first_day = date_from.weekday()
for day in days.keys():
    days[day] = full_weeks
for i in range(0, remainder):
    days[(first_day + i) % 7] += 1

答案 2 :(得分:1)

更正回答:

从date_to中减去date_from以获得总天数。除以七来得到周数 - 显然是每周每天一周。然后添加任何剩余的工作日:

>>> total_days = (date_to-date_from).days
>>> total_days
304
>>> weeks = total_days/7
>>> weeks
43
>>> days_of_week = {i:weeks for i in range (7)}
>>> if date_to.weekday() > date_from.weekday():
...   end_date = date_to.weekday()
... else:
...   end_date = date_to.weekday() +7
... 
>>> for i in range (date_from.weekday(), end_date + 1):
...   days_of_week[i %7] +=1
... 
>>> days_of_week
{0: 44, 1: 44, 2: 43, 3: 43, 4: 43, 5: 44, 6: 44}

答案 3 :(得分:1)

另一种选择,不使用Counter将是:

days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
        'Sunday']
day_counts = dict(zip(days, [0]*7))
this_day = date_from
td = datetime.timedelta(days=1)
while this_day <= date_to:
    day_counts[days[this_day.weekday()]] += 1
    this_day += td

>>> day_counts
{'Monday': 44, 'Tuesday': 44, 'Friday': 43, 'Wednesday': 43, 'Thursday': 43,
 'Sunday': 44, 'Saturday': 44}

答案 4 :(得分:1)

开始结束日期,有一个跟踪星期几,一天一天的计数器。

from datetime import datetime, timedelta
from collections import Counter

start=datetime(2014, 11, 30)
until=datetime(2014, 12, 9)
differences = [start + timedelta(i) for i in xrange((until - start).days + 1)]
print dict(Counter(d.strftime('%A') for d in differences))

输出结果为:

{'Sunday': 2, 'Monday': 2, 'Tuesday': 2, 'Friday': 1, 'Wednesday': 1, 'Thursday': 1, 'Saturday': 1}