Why not override datetime.datetime.__new__ in a subclass?
Notice how the method datetime.datetime.__new__ checks the timezone argument before creating new instances by calling the module level function:
# cpython/Lib/datetime.py
def _check_tzinfo_arg(tz):
if tz is not None and not isinstance(tz, tzinfo):
raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
So we can invoke a similar check before calling datetime.datetime.__new__ in our subclass
import datetime
class AwareDate(datetime.datetime):
def __new__(cls, *args, **kwargs):
if not isinstance(kwargs.get('tzinfo', None), datetime.tzinfo):
raise ValueError('MUST BE TZ AWARE !')
return datetime.datetime.__new__(cls, *args, **kwargs)
Some quick tests
normaldate = datetime.datetime(2020, 12, 20, tzinfo=datetime.timezone.utc)
awaredate = AwareDate(2020, 12, 20, tzinfo=datetime.timezone.utc)
assert awaredate == normaldate
normaldate = datetime.datetime(2020, 12, 20)
awaredate = AwareDate(2020, 12, 20) # ValueError: MUST BE TZ AWARE!