Looping through ("Spanning across") dates in Python with variable months and years?

My requirement is to loop through calendar dates in python in 2-day increments capturing every date across multiple months or years without repeating any dates.

I’m sure that sounds confusing so I’ve posted some reference visuals to demonstrate.

I have written Python code that successfully achieves my desired result (also attached), but it is clunky and gross code. I’m wondering if someone has a more elegant solution?

The reason I need this loop is to "span" the main function and capture either 1 whole month, multiple whole months, or even multiple years with multiple whole months (which I set by changing the years and months variables at the top of the code). These variable give me control over what years and months I want to span with the main function.

Example:
First Loop Iteration: start_date = 1/1/2021 end_date = 1/2/2021
Second Loop Iteration: start_date = 1/3/2021 end_date = 1/4/2021
….
Fifteenth Loop Iteration: start_date = 1/29/2021 end_date = 1/30/2021
Sixteenth Loop Iteration: start_date = 1/31/2021 end_date = 1/31/2021
Seventeenth Loop Iteration: start_date = 2/1/2021 end_date = 2/2/2021
Eighteenth Loop Iteration: start_date = 2/3/2021 end_date = 2/4/2021

Visualization of Example of Desired Loop

Here is the code that works to accomplish this task:

# Set date range to loop through
years = [2021, 2022]
months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
days_in_month = {1: 31, 2: 28, 3: 31, 4: 30, 5: 31,
                 6: 30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31}
clients = ["client1", "client2"]
# Loop through clients list and date range
combined_records = []
for client in clients:
    for target_year in years:
        for target_month in months:
            start_day = 1
            end_day = 2
            # Even number days in a month
            if days_in_month[target_month] % 2 == 0:
                while end_day <= days_in_month[target_month]:
                    # Arguments for main function: main(client, start_date, end_date)
                    list_of_records = main(client, date(target_year, target_month, start_day),
                                           date(target_year, target_month, end_day))
                    for record in list_of_records:
                        combined_records.append(record)
                    # Increment date range
                    start_day += 2
                    end_day += 2
            # Odd number days in a month
            else:
                while end_day <= 32:
                    if end_day < 32:
                        # Arguments for main function: main(client, start_date, end_date)
                        list_of_records = main(client, date(target_year, target_month, start_day),
                                               date(target_year, target_month, end_day))
                        for record in list_of_records:
                            combined_records.append(record)
                        # Increment date range
                        start_day += 2
                        end_day += 2
                    else:
                        end_day = 31
                        # Arguments for main function: main(client, start_date, end_date)
                        list_of_records = main(client, date(target_year, target_month, start_day),
                                               date(target_year, target_month, end_day))
                        for record in list_of_records:
                            combined_records.append(record)
                        # Increment date range
                        start_day += 2
                        end_day += 2

    print(f"CLIENT COMPLETE: {client}")

>Solution :

You can use numpy’s datetime64 to create an array of evenly spaced dates and then just iterate through that single array.

dates = np.arange(np.datetime64('2021-01-01'), np.datetime64('2022-12-31'), np.timedelta64(2, 'D'))

for date in dates:
    # code here

Leave a Reply