diff --git a/gallery_dl/extractor/common.py b/gallery_dl/extractor/common.py index 048e0a34..2533ae5a 100644 --- a/gallery_dl/extractor/common.py +++ b/gallery_dl/extractor/common.py @@ -174,8 +174,7 @@ class Extractor(): elif until: if isinstance(until, datetime.datetime): # convert to UTC timestamp - epoch = datetime.datetime(1970, 1, 1) - until = (until - epoch) / datetime.timedelta(0, 1) + until = (until - util.EPOCH) / util.SECOND else: until = float(until) seconds = until - now diff --git a/gallery_dl/util.py b/gallery_dl/util.py index 12896e6e..f6827f9f 100644 --- a/gallery_dl/util.py +++ b/gallery_dl/util.py @@ -145,6 +145,14 @@ def to_string(value): return str(value) +def to_timestamp(dt): + """Convert naive datetime to UTC timestamp string""" + try: + return str((dt - EPOCH) // SECOND) + except Exception: + return "" + + def dump_json(obj, fp=sys.stdout, ensure_ascii=True, indent=4): """Serialize 'obj' as JSON and write it to 'fp'""" json.dump( @@ -370,6 +378,8 @@ class UniversalNone(): NONE = UniversalNone() +EPOCH = datetime.datetime(1970, 1, 1) +SECOND = datetime.timedelta(0, 1) WINDOWS = (os.name == "nt") SENTINEL = object() SPECIAL_EXTRACTORS = {"oauth", "recursive", "test"} @@ -536,6 +546,7 @@ class Formatter(): - "d": calls text.parse_timestamp - "U": calls urllib.parse.unquote - "S": calls util.to_string() + - "T": calls util.to_timestamü() - Example: {f!l} -> "example"; {f!u} -> "EXAMPLE" Extra Format Specifiers: @@ -566,6 +577,7 @@ class Formatter(): "c": str.capitalize, "C": string.capwords, "t": str.strip, + "T": to_timestamp, "d": text.parse_timestamp, "U": urllib.parse.unquote, "S": to_string, diff --git a/test/test_util.py b/test/test_util.py index d90d5adc..0b61d813 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -271,6 +271,7 @@ class TestFormatter(unittest.TestCase): "s": " \n\r\tSPACE ", "u": "%27%3C%20/%20%3E%27", "t": 1262304000, + "dt": datetime.datetime(2010, 1, 1), "name": "Name", "title1": "Title", "title2": "", @@ -295,6 +296,7 @@ class TestFormatter(unittest.TestCase): self._run_test("{n!S}", "") self._run_test("{t!d}", datetime.datetime(2010, 1, 1)) self._run_test("{t!d:%Y-%m-%d}", "2010-01-01") + self._run_test("{dt!T}", "1262304000") with self.assertRaises(KeyError): self._run_test("{a!q}", "hello world") @@ -601,6 +603,11 @@ class TestOther(unittest.TestCase): self.assertEqual(f(["a", "b", "c"]), "a, b, c") self.assertEqual(f([1, 2, 3]), "1, 2, 3") + def test_to_timestamp(self, f=util.to_timestamp): + self.assertEqual(f(util.EPOCH), "0") + self.assertEqual(f(datetime.datetime(2010, 1, 1)), "1262304000") + self.assertEqual(f(None), "") + def test_universal_none(self): obj = util.NONE