diff options
Diffstat (limited to 'gallery_dl/dt.py')
| -rw-r--r-- | gallery_dl/dt.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/gallery_dl/dt.py b/gallery_dl/dt.py new file mode 100644 index 0000000..b37ebf3 --- /dev/null +++ b/gallery_dl/dt.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- + +# Copyright 2025 Mike Fährmann +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. + +"""Date/Time utilities""" + +import sys +import time +from datetime import datetime, date, timedelta, timezone # noqa F401 + + +class NullDatetime(datetime): + + def __bool__(self): + return False + + def __str__(self): + return "[Invalid DateTime]" + + def __format__(self, format_spec): + return "[Invalid DateTime]" + + +NONE = NullDatetime(1, 1, 1) +EPOCH = datetime(1970, 1, 1) +SECOND = timedelta(0, 1) + + +def normalize(dt): + # if (o := dt.utcoffset()) is not None: + # return dt.replace(tzinfo=None, microsecond=0) - o + if dt.tzinfo is not None: + return dt.astimezone(timezone.utc).replace(tzinfo=None, microsecond=0) + if dt.microsecond: + return dt.replace(microsecond=0) + return dt + + +def convert(value): + """Convert 'value' to a naive UTC datetime object""" + if not value: + return NONE + if isinstance(value, datetime): + return normalize(value) + if isinstance(value, str) and (dt := parse_iso(value)) is not NONE: + return dt + return parse_ts(value) + + +def parse(dt_string, format): + """Parse 'dt_string' according to 'format'""" + try: + return normalize(datetime.strptime(dt_string, format)) + except Exception: + return NONE + + +if sys.hexversion < 0x30c0000: + # Python <= 3.11 + def parse_iso(dt_string): + """Parse 'dt_string' as ISO 8601 value""" + try: + if dt_string[-1] == "Z": + # compat for Python < 3.11 + dt_string = dt_string[:-1] + elif dt_string[-5] in "+-": + # compat for Python < 3.11 + dt_string = f"{dt_string[:-2]}:{dt_string[-2:]}" + return normalize(datetime.fromisoformat(dt_string)) + except Exception: + return NONE + + from_ts = datetime.utcfromtimestamp + now = datetime.utcnow + +else: + # Python >= 3.12 + def parse_iso(dt_string): + """Parse 'dt_string' as ISO 8601 value""" + try: + return normalize(datetime.fromisoformat(dt_string)) + except Exception: + return NONE + + def from_ts(ts=None): + """Convert Unix timestamp to naive UTC datetime""" + Y, m, d, H, M, S, _, _, _ = time.gmtime(ts) + return datetime(Y, m, d, H, M, S) + + now = from_ts + + +def parse_ts(ts, default=NONE): + """Create a datetime object from a Unix timestamp""" + try: + return from_ts(int(ts)) + except Exception: + return default + + +def to_ts(dt): + """Convert naive UTC datetime to Unix timestamp""" + return (dt - EPOCH) / SECOND + + +def to_ts_string(dt): + """Convert naive UTC datetime to Unix timestamp string""" + try: + return str((dt - EPOCH) // SECOND) + except Exception: + return "" |
