在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
答案 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的小值无关。 在分析之后,即使其他算法的速度提高了几毫秒:
原始性能和简单设计之间的交易是我愿意花费大部分时间的。
答案 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}