datetime.date has a .replace() method that returns a copy with some values changed. This can be used to get the date 18 years ago.
end_date = date.today() start_date = end_date.replace(year=end_date.year - 18)
datetime.date.toordinal returns an integer corresponding to the date. The ordinals for the start and stop date can be used in random.randint() to pick a random ordinal, which can then be converted back into a date with date.fromordinal().
random_date = date.fromordinal(random.randint(start_date.toordinal(), end_date.toordinal()))
date.isoformat() returns a date a as YYYY-MM-DD. Or use date.strftime() for more control over the date format. In an f-string, a date is converted to ISO format, or a format string can be used: f"{random_date:%a, %b %d, %Y}" -> 'Sat, Dec 14, 2013'.
If you want to generate a list of dates in the range, use random.sample() with a range object.
NUMBER_OF_DATES = 10 date_range = range(start_date.toordinal(), end_date.toordinal()) random_dates = [date.fromordinal(o) for o in random.sample(date_range, NUMBER_OF_DATES)]