I often work with time series data and find it useful to have a variety of ways to randomly generate dates. This particular example is great for evenly distributed date partitions. Running the script below with the default arguments will output a list of random dates, one for each month of the year.
[datetime.date(2024, 1, 18), datetime.date(2024, 2, 20)...]
import calendar
from random import randint
from datetime import date
# the default arguments
year = 2024
num = 1
def generate_random_date(year: int, month: int) -> date:
""" Return a random date in a given year and month """
days_in_month = calendar.monthrange(year, month)[1]
random_day = randint(1, days_in_month)
return date(year, month, random_day)
def generate_random_days_each_month(year: int, n: int = 1) -> list[date]:
""" Return a list of 'n' random dates for every month in the given year """
r_dates = [generate_random_date(year, i) for i in range(1, 13) for _ in range(n)]
return r_dates
if __name__ == "__main__":
r_dates = generate_random_days_each_month(year, num)
print(r_dates)
There are interesting aspects in this script that are worthy of further breakdown.
First, the generate_random_date() function takes in year and month parameters and returns a random date within that range. The calendar standard library includes the monthrange() function which provides an elegant way to find the number of days in a month. Here is an example of how it works:
import calendar
year = 2024
month = 6
result = calendar.monthrange(year, month)
# > (weekday of first day of the month, number of days in month)
# > (calendar.SATURDAY, 30)
Isolating the second element of the tuple calendar.monthrange(year, month)[1], cleanly extracts the number of days in the month to pass to randint(1, days_in_month), which correlate to the first and last day of the month.
Then, the generate_random_days_each_month() function iterates over each month, n number of times, to generate a random date from generate_random_date(). Including a list comprehension [generate_random_date(year, i) for i in range(1, 13) for _ in range(n)] to iterate over both loops is a slick one-liner of code.
def generate_random_days_each_month(year: int, n: int = 1) -> list[date]:
""" Return a list of 'n' random dates for every month in the given year """
r_dates = [generate_random_date(year, i) for i in range(1, 13) for _ in range(n)]
return r_dates
To illustrate the behavior of the list comprehension, I’ve rewritten the code as a standard for loop:
r_dates = []
for i in range(1, 13):
for _ in range(n):
r_dates.append(generate_random_date(year, i))
The list comprehension is simplified and compact – a great feature of Python.
To generate the data you need, the process is simple. Determine the desired number of rows per partition, fill in the parameters, and execute.
Further Reading