代码之家  ›  专栏  ›  技术社区  ›  nmr

根据日期查找上个月的第一个工作日和最后一个工作日

  •  -1
  • nmr  · 技术社区  · 2 年前

    我在Python中有这样一个用例:根据日期查找上个月的第一个工作日和最后一个工作日。例如,如果日期为 2024-06-10

    first_business_day = '2024-05-01'
    last_business_day = '2024-05-31'
    

    我试过如下

    run_date = '2024-06-10'
    from datetime import datetime, timedelta
    
    d = datetime.strptime(run_date, '%Y-%m-%d').date()
    previous_month_first_business_day = (d - timedelta(days=d.day)).replace(day=1).strftime("%Y-%m-%d")
    previous_month_last_business_day = (d - timedelta(days=d.day)).strftime("%Y-%m-%d")
    

    后果

    previous_month_first_business_day = '2024-05-01'
    previous_month_last_business_day = '2024-05-31'
    

    这个月运行良好 也许 ,但当我想要相同的结果时 六月 ,然后使用上面的内容:

    previous_month_first_business_day = '2024-06-01' # This should be '2024-06-03'
    previous_month_last_business_day = '2024-06-30' # This should be '2024-06-29'
    

    我应该怎么做才能达到正确的结果?

    1 回复  |  直到 2 年前
        1
  •  2
  •   ti7    2 年前

    看看内置 calendar 而不是 datetime

    import calendar
    import datetime
    
    def month_start_end_work(date_src, fmt_date="%Y-%m-%d"):
        dt = datetime.datetime.strptime(date_src, fmt_date)
    
        # roll around January -> December
        month = 12 if dt.month == 1 else (dt.month - 1)
        year = dt.year if month != 12 else (dt.year - 1)
    
        # discover last day of last month
        for day in (31, 30, 29, 28):  # handle Feb cases
            try:  # already the correct year for leap
                month_start = calendar.weekday(year, month, day)
            except ValueError:  # day is out of range for month
                continue  # month has fewer days (always decreases)
            if month_start == calendar.SATURDAY:
                day -= 1
            elif month_start == calendar.SUNDAY:
                day -= 2
            break  # last day name to be used
        else:  # did not solve and break
            raise RuntimeError("BUG: impossible code path reached")
        day_last = (year, month, day)  # TODO may want to make a datetime.datetime
        
        # discover first day of last month
        day = 1  # all months begin at 1
        month_start = calendar.weekday(year, month, day)
        if month_start == calendar.SATURDAY:
            day += 2
        elif month_start == calendar.SUNDAY:
            day += 1
        day_first = (year, month, day)
    
        return day_first, day_last
    
    >>> month_start_end_work("2024-06-10")
    ((2024, 5, 1), (2024, 5, 31))
    >>> month_start_end_work("2024-07-10")
    ((2024, 6, 3), (2024, 6, 28))
    >>> month_start_end_work("2022-01-01")
    ((2021, 12, 1), (2021, 12, 31))
    

    如果你有特殊的休息日(可能每年6-12天),把它们收集到一个列表中,然后不断递减/递增以获得准确的匹配