首页 文章

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

提问于
浏览
1

在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 回答

  • 2

    试试这个:

    >>> 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的小值无关 .
      正如古老的唐纳德·克努特所说的_999_:"Premature optimization is the root of all evil" .

    • 关于表现的问题的答案总是"profile it" - 不止一次我对结果的不直观感到惊讶 .

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

    • 是与应用程序相关的性能差异?

    • 代码更容易推理?

    • 你能确保所有角落案件都被覆盖吗?

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

  • 1

    对于你的问题,我会使用@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
    
  • 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}
    
  • 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

    有一个计数器跟踪一周中的哪一天,从开始到结束日期一次一天 .

    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}
    

相关问题