【问题标题】:Print all thursdays between date range打印日期范围之间的所有星期四
【发布时间】:2021-06-08 07:35:57
【问题描述】:

我想打印这些日期范围之间的所有星期四

from datetime import date, timedelta
sdate = date(2015, 1, 7)   # start date
edate = date(2015, 12, 31)   # end date

最好的pythonic方法是什么?

【问题讨论】:

标签: python python-3.x python-2.7


【解决方案1】:

使用您的sdate.weekday() # returns int between 0 (mon) and 6 (sun):

sdate = ...
while sdate < edate:
    if sdate.weekday() != 3:  # not thursday
        sdate += timedelta(days=1)
        continue
    # It is thursday
    print(sdate)
    sdate += timedelta(days=7)  #  next week

【讨论】:

    【解决方案2】:

    计算从开始日期到星期四的天数:

    days_to_thursday = (3 - sdate.weekday()) % 7
    

    计算两个日期之间的星期四数:

    week_diff = ((edate - sdate).days - days_to_thursday ) // 7
    

    获取日期范围内的所有星期四:

    thursdays = [sdate + timedelta(days=days_to_thursday + 7 * more_weeks) \
        for more_weeks in range(week_diff + 1) ]
    

    如果需要,请打印:

    for t in thursdays:
        print(t)
    

    【讨论】:

    • 感谢您指出将负数除以正数的余数技巧。以前不知道,很有用的属性。
    【解决方案3】:

    大多数人每天都在迭代,这是一种浪费。也可能有助于延迟计算星期四,直到您真正需要它们。为此,您可以使用生成器。

    def get_days(start, day_index, end=None):
        # set the start as the next valid day
        start += timedelta(days=(day_index - start.weekday()) % 7)
        week = timedelta(days=7)
        while end and start < end or not end:
            yield start
            start += week
    

    这会延迟获得第二天,直到您需要它,如果您不指定和结束日期,则允许无限天。

    thursday_generator = get_days(date(2015, 1, 7), 3, date(2015, 12, 31))
    print(list(thursday_generator))
    
    """
    [datetime.date(2015, 1, 8), datetime.date(2015, 1, 15), datetime.date(2015, 1, 22), ...]
    """
    

    您可以轻松地转储为字符串:

    print("\n".join(map(str, thursday_generator)))
    
    """
    2015-01-08
    2015-01-15
    2015-01-22
    ...
    """
    

    您还可以使用 f-strings 进行自定义字符串格式化:

    print("\n".join(f"{day:%A %x}" for day in thursday_generator))
    
    """
    Thursday 01/08/15
    Thursday 01/15/15
    Thursday 01/22/15
    ...
    """
    

    如果您不指定结束日期,它将永远持续下去。

    In [28]: thursday_generator = get_days(date(2015, 1, 7), 3)
        ...: print(len(list(thursday_generator)))
    ---------------------------------------------------------------------------
    OverflowError                             Traceback (most recent call last)
    <ipython-input-28-b161cdcccc75> in <module>
          1 thursday_generator = get_days(date(2015, 1, 7), 3)
    ----> 2 print(len(list(thursday_generator)))
    
    <ipython-input-16-0691db329606> in get_days(start, day_index, end)
          5     while end and start < end or not end:
          6         yield start
    ----> 7         start += week
          8
    
    OverflowError: date value out of range
    

    【讨论】:

      【解决方案4】:

      您可以尝试列表推导来获取两个日期之间的星期四。

      此代码实际上将日期输出为格式化字符串,但您可以通过删除 strftime 来获取实际日期。

      from datetime import date, timedelta
      sdate = date(2015, 1, 7)   # start date
      edate = date(2015, 12, 31)   # end date
      
      thursdays = [(sdate+timedelta(days=d)).strftime('%A %Y-%m-%d') for d in range(0, (edate-sdate).days+1) 
                   if (sdate+timedelta(days=d)).weekday() ==3]
      
      print('\n'.join(thursdays))
      
      """ Example output
      Thursday 2015-01-08
      Thursday 2015-01-15
      Thursday 2015-01-22
      Thursday 2015-01-29
      Thursday 2015-02-05
      Thursday 2015-02-12
      """"
      

      【讨论】:

        【解决方案5】:
        import datetime
        import calendar
        
        def weekday_count(start, end, day):
            start_date  = datetime.datetime.strptime(start, '%d/%m/%Y')
            end_date    = datetime.datetime.strptime(end, '%d/%m/%Y')
            day_count = []
            
            for i in range((end_date - start_date).days):
                if calendar.day_name[(start_date + datetime.timedelta(days=i+1)).weekday()] == day:
                    print(str(start_date + datetime.timedelta(days=i+1)).split()[0])
        
        weekday_count("01/01/2017", "31/01/2017", "Thursday")
        
        # prints result
        # 2017-01-05
        # 2017-01-12
        # 2017-01-19
        # 2017-01-26
        
        

        【讨论】:

        • 我想打印日期范围之间的星期四
        • 我不需要打印星期四的总数,而是星期四的日期
        • 如果我不想要时间并且只需要打印日期怎么办
        • 您可以尝试从 deltatime 对象中提取日期或将其转换为 str,然后进行拆分和索引(如编辑后的答案所示)
        【解决方案6】:

        简单的解决方案:

        from datetime import date, timedelta
        
        sdate = date(2015, 1, 7)   # start date
        edate = date(2015, 12, 31)   # end date
        
        delta = edate - sdate
        
        for day in range(delta.days + 1):
            day_obj = sdate + timedelta(days=day)
            if day_obj.weekday() == 3:  # Thursday
                print(day_obj)
        
        # 2015-01-08
        # 2015-01-15
        # ...
        # 2015-12-24
        # 2015-12-31
        

        最有效的解决方案:

        from datetime import date, timedelta
        
        sdate = date(2015, 1, 7)   # start date
        edate = date(2015, 12, 31)   # end date
        
        day_index = 3  # Thursday
        delta = (day_index - sdate.weekday()) % 7
        match = sdate + timedelta(days=delta)
        
        while match <= edate:  # Change this to `<` to ignore the last one
            print(match) # Can be easily converted to a generator with `yield`
            match += timedelta(days=7)
        
        # 2015-01-08
        # 2015-01-15
        # ...
        # 2015-12-24
        # 2015-12-31
        

        文档:

        【讨论】:

        • abs 函数使此解决方案对于任何工作日大于 3 的日期都不正确。它分别给出1, 2 or 3 的增量而不是6, 5 or 4。
        • 非常感谢!固定。
        • 2016 年的星期四打印不正确
        • @sam 看起来确实会打印 2016 年的所有星期四:replit.com/@sobolevn/CarefulConcreteListener#main.py
        猜你喜欢
        • 2017-12-08
        • 2015-08-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-29
        • 1970-01-01
        • 1970-01-01
        • 2011-11-08
        相关资源
        最近更新 更多