Fundamentals 9 min read

Python Date and Workday Utilities: Calculating Workdays, Weeks, and Date Offsets

This article explains how to use Python's time and datetime modules to calculate workdays between two dates, determine week counts, and retrieve dates offset by a given number of days or months, providing reusable utility scripts with clear code examples.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Python Date and Workday Utilities: Calculating Workdays, Weeks, and Date Offsets

The article introduces a set of Python utilities for handling dates, especially for calculating workdays and date offsets, which are useful for task statistics in a company.

Dependencies : the standard time and datetime modules are required.

workDays.py defines a workDays class that:

import datetime

class workDays():
    def __init__(self, start_date, end_date, days_off=None):
        """days_off:休息日,默认周六日, 以0(星期一)开始,到6(星期天)结束, 传入tupple
        没有包含法定节假日,
        """
        self.start_date = start_date
        self.end_date = end_date
        self.days_off = days_off
        if self.start_date > self.end_date:
            self.start_date, self.end_date = self.end_date, self.start_date
        if days_off is None:
            self.days_off = 5, 6
        self.days_work = [x for x in range(7) if x not in self.days_off]

    def workDays(self):
        """实现工作日的 iter, 从start_date 到 end_date , 如果在工作日内,yield 日期"""
        tag_date = self.start_date
        while True:
            if tag_date > self.end_date:
                break
            if tag_date.weekday() in self.days_work:
                yield tag_date
            tag_date += datetime.timedelta(days=1)

    def daysCount(self):
        """工作日统计,返回数字"""
        return len(list(self.workDays()))

    def weeksCount(self, day_start=0):
        """统计所有跨越的周数,返回数字
        默认周从星期一开始计算
        """
        day_nextweek = self.start_date
        while True:
            if day_nextweek.weekday() == day_start:
                break
            day_nextweek += datetime.timedelta(days=1)
        if day_nextweek > self.end_date:
            return 1
        weeks = ((self.end_date - day_nextweek).days + 1) / 7
        weeks = int(weeks)
        if ((self.end_date - day_nextweek).days + 1) % 7:
            weeks += 1
        if self.start_date < day_nextweek:
            weeks += 1
        return weeks

get_day.py provides a collection of helper functions for obtaining today’s date, formatted strings, and calculating dates relative to today (days, months, first/last day of month, etc.).

from time import strftime, localtime
from datetime import timedelta, date
import calendar

year = strftime("%Y", localtime())
mon = strftime("%m", localtime())
day = strftime("%d", localtime())
hour = strftime("%H", localtime())
min = strftime("%M", localtime())
sec = strftime("%S", localtime())

def today():
    '''
    get today,date format="YYYY-MM-DD"
    '''
    return date.today()

def todaystr():
    '''
    get date string, date format="YYYYMMDD"
    '''
    return year + mon + day

def datetime():
    '''
    get datetime,format="YYYY-MM-DD HH:MM:SS"
    '''
    return strftime("%Y-%m-%d %H:%M:%S", localtime())

def datetimestr():
    '''
    get datetime string
    date format="YYYYMMDDHHMMSS"
    '''
    return year + mon + day + hour + min + sec

def get_day_of_day(n=0):
    '''
    if n>=0,date is larger than today
    if n<0,date is less than today
    date format = "YYYY-MM-DD"
    '''
    if n < 0:
        n = abs(n)
        return date.today() - timedelta(days=n)
    else:
        return date.today() + timedelta(days=n)

def get_days_of_month(year, mon):
    '''
    get days of month
    '''
    return calendar.monthrange(year, mon)[1]

def get_firstday_of_month(year, mon):
    '''
    get the first day of month
    date format = "YYYY-MM-DD"
    '''
    days = "01"
    if int(mon) < 10:
        mon = "0" + str(int(mon))
    arr = (year, mon, days)
    return "-".join("%s" % i for i in arr)

def get_lastday_of_month(year, mon):
    '''
    get the last day of month
    date format = "YYYY-MM-DD"
    '''
    days = calendar.monthrange(year, mon)[1]
    mon = addzero(mon)
    arr = (year, mon, days)
    return "-".join("%s" % i for i in arr)

def get_firstday_month(n=0):
    '''
    get the first day of month from today
    n is how many months
    '''
    (y, m, d) = getyearandmonth(n)
    d = "01"
    arr = (y, m, d)
    return "-".join("%s" % i for i in arr)

def get_lastday_month(n=0):
    '''
    get the last day of month from today
    n is how many months
    '''
    return "-".join("%s" % i for i in getyearandmonth(n))

def getyearandmonth(n=0):
    '''
    get the year,month,days from today
    before or after n months
    '''
    thisyear = int(year)
    thismon = int(mon)
    totalmon = thismon + n
    if n >= 0:
        if totalmon <= 12:
            days = str(get_days_of_month(thisyear, totalmon))
            totalmon = addzero(totalmon)
            return (year, totalmon, days)
        else:
            i = totalmon / 12
            j = totalmon % 12
            if j == 0:
                i -= 1
                j = 12
            thisyear += i
            days = str(get_days_of_month(thisyear, j))
            j = addzero(j)
            return (str(thisyear), str(j), days)
    else:
        if 0 < totalmon < 12:
            days = str(get_days_of_month(thisyear, totalmon))
            totalmon = addzero(totalmon)
            return (year, totalmon, days)
        else:
            i = totalmon / 12
            j = totalmon % 12
            if j == 0:
                i -= 1
                j = 12
            thisyear += i
            days = str(get_days_of_month(thisyear, j))
            j = addzero(j)
            return (str(thisyear), str(j), days)

def addzero(n):
    '''
    add 0 before 0-9
    return 01-09
    '''
    nabs = abs(int(n))
    if nabs < 10:
        return "0" + str(nabs)
    else:
        return nabs

def get_today_month(n=0):
    '''
    获取当前日期前后N月的日期
    if n>0, 获取当前日期前N月的日期
    if n<0, 获取当前日期后N月的日期
    date format = "YYYY-MM-DD"
    '''
    (y, m, d) = getyearandmonth(n)
    arr = (y, m, d)
    if int(day) < int(d):
        arr = (y, m, day)
    return "-".join("%s" % i for i in arr)

run_main.py demonstrates how to combine the utilities to obtain a list of workday dates for the next fifteen days (or any range) and print them.

from two_weeks.get_day import *
from two_weeks.workDays import *
#获取当天日期
startdate = today()
#获取15天之内的日期
enddate = get_day_of_day(15)  # 正数为今天之后的日期,负数为今天之前的日期
work = workDays(startdate, enddate)  # 需要传入两个datetime格式日期
towWeeks_workDay = []
for i in work.workDays():
    towWeeks_workDay.append(i.strftime("%Y-%m-%d"))
print(towWeeks_workDay)

The provided scripts can be directly used or adapted for any Python project that requires date calculations, workday counting, or generating date ranges.

DateTimecalendarutilitiesDateWorkday
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.