merge branch 'dt': move datetime utils into separate module
- use 'datetime.fromisoformat()' when possible (#7671) - return a datetime-compatible object for invalid datetimes (instead of a 'str' value)
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
|
||||
gallery_dl = __import__("gallery_dl.extractor.2chen")
|
||||
_2chen = getattr(gallery_dl.extractor, "2chen")
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -18,7 +17,7 @@ __tests__ = (
|
||||
"#count" : ">= 179",
|
||||
|
||||
"board" : "tv",
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"hash" : r"re:[0-9a-f]{40}",
|
||||
"name" : "Anonymous",
|
||||
"no" : r"re:\d+",
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
gallery_dl = __import__("gallery_dl.extractor.4archive")
|
||||
_4archive = getattr(gallery_dl.extractor, "4archive")
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -19,7 +18,7 @@ __tests__ = (
|
||||
|
||||
"board" : "u",
|
||||
"com" : str,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"name" : "Anonymous",
|
||||
"no" : range(2397221, 2418158),
|
||||
"thread": 2397221,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import deviantart
|
||||
import datetime
|
||||
from gallery_dl import exception
|
||||
|
||||
|
||||
@@ -60,7 +59,7 @@ __tests__ = (
|
||||
"transparency": bool,
|
||||
"width" : int,
|
||||
},
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"deviationid" : str,
|
||||
"?download_filesize": int,
|
||||
"extension" : str,
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
from gallery_dl.extractor import facebook
|
||||
from gallery_dl import exception
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -191,7 +190,7 @@ __tests__ = (
|
||||
"#count" : 1,
|
||||
|
||||
"caption" : "They were on a break... #FriendsReunion #MoreTogether",
|
||||
"date" : datetime.datetime(2021, 5, 27, 21, 55, 19),
|
||||
"date" : "dt:2021-05-27 21:55:19",
|
||||
"filename" : "191053255_10160743390471729_9001965649022744000_n",
|
||||
"extension": "jpg",
|
||||
"id" : "10160743390456729",
|
||||
@@ -212,7 +211,7 @@ __tests__ = (
|
||||
"#count" : 1,
|
||||
|
||||
"caption" : "",
|
||||
"date" : datetime.datetime(2014, 5, 3, 0, 44, 47),
|
||||
"date" : "dt:2014-05-03 00:44:47",
|
||||
"filename" : str,
|
||||
"extension": "png",
|
||||
"id" : "10152716011076729",
|
||||
@@ -272,7 +271,7 @@ __tests__ = (
|
||||
"#class" : facebook.FacebookVideoExtractor,
|
||||
"#count" : 1,
|
||||
|
||||
"date" : datetime.datetime(2024, 4, 19, 17, 25, 48),
|
||||
"date" : "dt:2024-04-19 17:25:48",
|
||||
"filename" : str,
|
||||
"id" : "1165557851291824",
|
||||
"url" : str,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import hentaifoundry
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -190,7 +189,7 @@ Sorry for the bad quality, I made it on after effect because Flash works like sh
|
||||
"author" : "SnowWolf35",
|
||||
"chapters" : int,
|
||||
"comments" : int,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"description": str,
|
||||
"index" : int,
|
||||
"rating" : int,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import nijie
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -29,7 +28,7 @@ __tests__ = (
|
||||
|
||||
"artist_id" : 58000,
|
||||
"artist_name": "のえるわ",
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"description": str,
|
||||
"image_id" : int,
|
||||
"num" : int,
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
from gallery_dl.extractor import imgur
|
||||
from gallery_dl import exception
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -215,7 +214,7 @@ __tests__ = (
|
||||
},
|
||||
"account_id" : 0,
|
||||
"count" : 19,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"description": "",
|
||||
"ext" : "jpg",
|
||||
"has_sound" : False,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import inkbunny
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -16,7 +15,7 @@ __tests__ = (
|
||||
"#pattern" : r"https://[\w.]+\.metapix\.net/files/full/\d+/\d+_soina_.+",
|
||||
"#range" : "20-50",
|
||||
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"deleted" : bool,
|
||||
"file_id" : r"re:[0-9]+",
|
||||
"filename" : r"re:[0-9]+_soina_\w+",
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import luscious
|
||||
import datetime
|
||||
from gallery_dl import exception
|
||||
|
||||
|
||||
@@ -49,7 +48,7 @@ __tests__ = (
|
||||
"aspect_ratio" : r"re:\d+:\d+",
|
||||
"category" : "luscious",
|
||||
"created" : int,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"height" : int,
|
||||
"id" : int,
|
||||
"is_animated" : False,
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
from gallery_dl.extractor import mangadex
|
||||
from gallery_dl import exception
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -132,7 +131,7 @@ __tests__ = (
|
||||
"chapter" : 0,
|
||||
"chapter_minor": "",
|
||||
"chapter_id" : str,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"lang" : "iso:lang",
|
||||
"artist" : ["Arakawa Hiromu"],
|
||||
"author" : ["Arakawa Hiromu"],
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import mangafox
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -40,7 +39,7 @@ __tests__ = (
|
||||
"chapter" : int,
|
||||
"chapter_minor" : r"re:^(\.\d+)?$",
|
||||
"chapter_string": r"re:(v\d+/)?c\d+",
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"description" : "High school boy Naoya gets a confession from Momi, a cute and friendly girl. However, Naoya already has a girlfriend, Seki... but Momi is too good a catch to let go. Momi and Nagoya's goal becomes clear: convince Seki to accept being an item with the two of them. Will she budge?",
|
||||
"lang" : "en",
|
||||
"language" : "English",
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import mangapark
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -115,7 +114,7 @@ __tests__ = (
|
||||
"chapter" : int,
|
||||
"chapter_id" : r"re:\d+",
|
||||
"chapter_minor": str,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"lang" : "en",
|
||||
"language" : "English",
|
||||
"manga_id" : 114972,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import nijie
|
||||
import datetime
|
||||
from gallery_dl import exception
|
||||
|
||||
|
||||
@@ -32,7 +31,7 @@ __tests__ = (
|
||||
"artist_id" : 44,
|
||||
"artist_name": "ED",
|
||||
"count" : 1,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"description": str,
|
||||
"extension" : "jpg",
|
||||
"filename" : str,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import patreon
|
||||
import datetime
|
||||
from gallery_dl import exception
|
||||
|
||||
|
||||
@@ -21,7 +20,7 @@ __tests__ = (
|
||||
"comment_count": int,
|
||||
"content" : str,
|
||||
"creator" : dict,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"id" : int,
|
||||
"images" : list,
|
||||
"like_count" : int,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import photovogue
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -21,7 +20,7 @@ __tests__ = (
|
||||
"#class" : photovogue.PhotovogueUserExtractor,
|
||||
"#pattern" : "https://images.vogue.it/Photovogue/[^/]+_gallery.jpg",
|
||||
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"favorite_count" : int,
|
||||
"favorited" : list,
|
||||
"id" : int,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import picarto
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -16,7 +15,7 @@ __tests__ = (
|
||||
"#pattern" : r"https://images\.picarto\.tv/gallery/\d/\d\d/\d+/artwork/[0-9a-f-]+/large-[0-9a-f]+\.(jpg|png|gif)",
|
||||
"#count" : ">= 7",
|
||||
|
||||
"date": datetime.datetime,
|
||||
"date": "type:datetime",
|
||||
},
|
||||
|
||||
)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import pillowfort
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -24,7 +23,7 @@ __tests__ = (
|
||||
"content" : str,
|
||||
"count" : 4,
|
||||
"created_at" : str,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"deleted" : None,
|
||||
"deleted_at" : None,
|
||||
"deleted_by_mod" : None,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import pixeldrain
|
||||
import datetime
|
||||
|
||||
__tests__ = (
|
||||
{
|
||||
@@ -81,7 +80,7 @@ __tests__ = (
|
||||
"success" : True,
|
||||
"title" : "アルバム",
|
||||
},
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"description": "",
|
||||
"detail_href": r"re:/file/(yEK1n2Qc|jW9E6s4h)/info",
|
||||
"hash_sha256": r"re:\w{64}",
|
||||
|
||||
@@ -668,6 +668,8 @@ __tests__ = (
|
||||
"#class" : pixiv.PixivSketchExtractor,
|
||||
"#pattern" : r"https://img\-sketch\.pixiv\.net/uploads/medium/file/\d+/\d+\.(jpg|png)",
|
||||
"#count" : ">= 35",
|
||||
|
||||
"date": "type:datetime",
|
||||
},
|
||||
|
||||
)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import subscribestar
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -20,7 +19,7 @@ __tests__ = (
|
||||
"author_name": "subscribestar",
|
||||
"author_nick": "SubscribeStar",
|
||||
"content" : str,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"id" : int,
|
||||
"num" : int,
|
||||
"post_id" : int,
|
||||
@@ -38,7 +37,7 @@ __tests__ = (
|
||||
"#options" : {"metadata": True},
|
||||
"#range" : "1",
|
||||
|
||||
"date": datetime.datetime,
|
||||
"date": "type:datetime",
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# published by the Free Software Foundation.
|
||||
|
||||
from gallery_dl.extractor import toyhouse
|
||||
import datetime
|
||||
|
||||
|
||||
__tests__ = (
|
||||
@@ -19,7 +18,7 @@ __tests__ = (
|
||||
|
||||
"artists" : list,
|
||||
"characters": list,
|
||||
"date" : datetime.datetime,
|
||||
"date" : "type:datetime",
|
||||
"hash" : r"re:\w+",
|
||||
"id" : r"re:\d+",
|
||||
"url" : str,
|
||||
|
||||
167
test/test_dt.py
Normal file
167
test/test_dt.py
Normal file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- 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.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import datetime
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from gallery_dl import dt # noqa E402
|
||||
|
||||
|
||||
class TestDatetime(unittest.TestCase):
|
||||
|
||||
def test_convert(self, f=dt.convert):
|
||||
|
||||
def _assert(value, expected):
|
||||
result = f(value)
|
||||
self.assertIsInstance(result, datetime.datetime)
|
||||
self.assertEqual(result, expected, msg=repr(value))
|
||||
|
||||
d = datetime.datetime(2010, 1, 1)
|
||||
self.assertIs(f(d), d)
|
||||
|
||||
_assert(d , d)
|
||||
_assert(1262304000 , d)
|
||||
_assert(1262304000.0 , d)
|
||||
_assert(1262304000.123, d)
|
||||
_assert("1262304000" , d)
|
||||
|
||||
_assert("2010-01-01" , d)
|
||||
_assert("2010-01-01 00:00:00" , d)
|
||||
_assert("2010-01-01T00:00:00" , d)
|
||||
_assert("2010-01-01T00:00:00.123456" , d)
|
||||
_assert("2009-12-31T19:00:00-05:00" , d)
|
||||
_assert("2009-12-31T19:00:00.123456-05:00", d)
|
||||
_assert("2010-01-01T00:00:00Z" , d)
|
||||
_assert("2010-01-01T00:00:00.123456Z" , d)
|
||||
_assert("2009-12-31T19:00:00-0500" , d)
|
||||
_assert("2009-12-31T19:00:00.123456-0500" , d)
|
||||
|
||||
_assert(0 , dt.NONE)
|
||||
_assert("" , dt.NONE)
|
||||
_assert("foo", dt.NONE)
|
||||
_assert(None , dt.NONE)
|
||||
_assert(() , dt.NONE)
|
||||
_assert([] , dt.NONE)
|
||||
_assert({} , dt.NONE)
|
||||
_assert((1, 2, 3), dt.NONE)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x30b0000,
|
||||
"extended fromisoformat timezones")
|
||||
def test_convert_tz(self, f=dt.convert):
|
||||
|
||||
def _assert(value, expected):
|
||||
result = f(value)
|
||||
self.assertIsInstance(result, datetime.datetime)
|
||||
self.assertEqual(result, expected, msg=repr(value))
|
||||
|
||||
d = datetime.datetime(2010, 1, 1)
|
||||
_assert("2009-12-31T19:00:00-05" , d)
|
||||
_assert("2009-12-31T19:00:00.123456-05" , d)
|
||||
|
||||
def test_to_timestamp(self, f=dt.to_ts):
|
||||
self.assertEqual(f(dt.EPOCH), 0.0)
|
||||
self.assertEqual(f(datetime.datetime(2010, 1, 1)), 1262304000.0)
|
||||
self.assertEqual(f(datetime.datetime(2010, 1, 1, 0, 0, 0, 128000)),
|
||||
1262304000.128000)
|
||||
with self.assertRaises(TypeError):
|
||||
f(None)
|
||||
|
||||
def test_to_timestamp_string(self, f=dt.to_ts_string):
|
||||
self.assertEqual(f(dt.EPOCH), "0")
|
||||
self.assertEqual(f(datetime.datetime(2010, 1, 1)), "1262304000")
|
||||
self.assertEqual(f(None), "")
|
||||
|
||||
def test_from_timestamp(self, f=dt.from_ts):
|
||||
self.assertEqual(f(0.0), dt.EPOCH)
|
||||
self.assertEqual(f(1262304000.0), datetime.datetime(2010, 1, 1))
|
||||
self.assertEqual(f(1262304000.128000).replace(microsecond=0),
|
||||
datetime.datetime(2010, 1, 1, 0, 0, 0))
|
||||
|
||||
def test_now(self, f=dt.now):
|
||||
self.assertIsInstance(f(), datetime.datetime)
|
||||
|
||||
def test_parse_timestamp(self, f=dt.parse_ts):
|
||||
null = dt.from_ts(0)
|
||||
value = dt.from_ts(1555816235)
|
||||
|
||||
self.assertEqual(f(0) , null)
|
||||
self.assertEqual(f("0") , null)
|
||||
self.assertEqual(f(1555816235) , value)
|
||||
self.assertEqual(f("1555816235"), value)
|
||||
|
||||
for value in ((), [], {}, None, ""):
|
||||
self.assertEqual(f(value), dt.NONE)
|
||||
self.assertEqual(f(value, "foo"), "foo")
|
||||
|
||||
def test_parse(self, f=dt.parse):
|
||||
self.assertEqual(
|
||||
f("1970.01.01", "%Y.%m.%d"),
|
||||
dt.EPOCH,
|
||||
)
|
||||
self.assertEqual(
|
||||
f("May 7, 2019 9:33 am", "%B %d, %Y %I:%M %p"),
|
||||
datetime.datetime(2019, 5, 7, 9, 33, 0),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07T21:25:02.753+0900", "%Y-%m-%dT%H:%M:%S.%f%z"),
|
||||
datetime.datetime(2019, 5, 7, 12, 25, 2),
|
||||
)
|
||||
|
||||
for value in ((), [], {}, None, 1, 2.3):
|
||||
self.assertEqual(f(value, "%Y"), dt.NONE)
|
||||
|
||||
def test_parse_iso(self, f=dt.parse_iso):
|
||||
self.assertEqual(
|
||||
f("1970-01-01T00:00:00+00:00"),
|
||||
dt.from_ts(0),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07T21:25:02+09:00"),
|
||||
datetime.datetime(2019, 5, 7, 12, 25, 2),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07T12:25:02Z"),
|
||||
datetime.datetime(2019, 5, 7, 12, 25, 2),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07 21:25:02"),
|
||||
datetime.datetime(2019, 5, 7, 21, 25, 2),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("1970-01-01"),
|
||||
dt.EPOCH,
|
||||
)
|
||||
self.assertEqual(
|
||||
f("1970.01.01"),
|
||||
dt.NONE,
|
||||
)
|
||||
self.assertEqual(
|
||||
f("1970-01-01T00:00:00+0000"),
|
||||
dt.EPOCH,
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07T21:25:02.753+0900"),
|
||||
datetime.datetime(2019, 5, 7, 12, 25, 2),
|
||||
)
|
||||
|
||||
for value in ((), [], {}, None, 1, 2.3):
|
||||
self.assertEqual(f(value), dt.NONE)
|
||||
|
||||
def test_none(self):
|
||||
self.assertFalse(dt.NONE)
|
||||
self.assertIsInstance(dt.NONE, dt.datetime)
|
||||
self.assertEqual(str(dt.NONE), "[Invalid DateTime]")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -14,10 +14,9 @@ from unittest.mock import patch
|
||||
|
||||
import time
|
||||
import string
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from gallery_dl import extractor, util # noqa E402
|
||||
from gallery_dl import extractor, util, dt # noqa E402
|
||||
from gallery_dl.extractor import mastodon # noqa E402
|
||||
from gallery_dl.extractor.common import Extractor, Message # noqa E402
|
||||
from gallery_dl.extractor.directlink import DirectlinkExtractor # noqa E402
|
||||
@@ -233,8 +232,8 @@ class TestExtractorWait(unittest.TestCase):
|
||||
|
||||
def test_wait_until_datetime(self):
|
||||
extr = extractor.find("generic:https://example.org/")
|
||||
until = util.datetime_utcnow() + timedelta(seconds=5)
|
||||
until_local = datetime.now() + timedelta(seconds=5)
|
||||
until = dt.now() + dt.timedelta(seconds=5)
|
||||
until_local = dt.datetime.now() + dt.timedelta(seconds=5)
|
||||
|
||||
if not until.microsecond:
|
||||
until = until.replace(microsecond=until_local.microsecond)
|
||||
@@ -251,8 +250,8 @@ class TestExtractorWait(unittest.TestCase):
|
||||
self._assert_isotime(calls[0][1][1], until_local)
|
||||
|
||||
def _assert_isotime(self, output, until):
|
||||
if not isinstance(until, datetime):
|
||||
until = datetime.fromtimestamp(until)
|
||||
if not isinstance(until, dt.datetime):
|
||||
until = dt.datetime.fromtimestamp(until)
|
||||
o = self._isotime_to_seconds(output)
|
||||
u = self._isotime_to_seconds(until.time().isoformat()[:8])
|
||||
self.assertLessEqual(o-u, 1.0)
|
||||
|
||||
@@ -15,7 +15,7 @@ import datetime
|
||||
import tempfile
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from gallery_dl import formatter, text, util, config # noqa E402
|
||||
from gallery_dl import formatter, text, dt, util, config # noqa E402
|
||||
|
||||
try:
|
||||
import jinja2
|
||||
@@ -154,7 +154,7 @@ class TestFormatter(unittest.TestCase):
|
||||
self._run_test("{t}" , self.kwdict["t"] , None, int)
|
||||
self._run_test("{t}" , self.kwdict["t"] , None, util.identity)
|
||||
self._run_test("{dt}", self.kwdict["dt"], None, util.identity)
|
||||
self._run_test("{ds}", self.kwdict["dt"], None, text.parse_datetime)
|
||||
self._run_test("{ds}", self.kwdict["dt"], None, dt.parse_iso)
|
||||
self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z}", self.kwdict["dt"],
|
||||
None, util.identity)
|
||||
|
||||
@@ -271,8 +271,8 @@ class TestFormatter(unittest.TestCase):
|
||||
|
||||
def test_specifier_datetime(self):
|
||||
self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z}", "2010-01-01 00:00:00")
|
||||
self._run_test("{ds:D%Y}", "2010-01-01T01:00:00+01:00")
|
||||
self._run_test("{l:D%Y}", "None")
|
||||
self._run_test("{ds:D%Y}", "[Invalid DateTime]")
|
||||
self._run_test("{l2:D%Y}", "[Invalid DateTime]")
|
||||
|
||||
def test_specifier_offset(self):
|
||||
self._run_test("{dt:O 01:00}", "2010-01-01 01:00:00")
|
||||
|
||||
@@ -11,8 +11,6 @@ import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import datetime
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from gallery_dl import text, util # noqa E402
|
||||
|
||||
@@ -537,51 +535,6 @@ class TestText(unittest.TestCase):
|
||||
self.assertEqual(f({"ä&": "あと", "#": "?"}),
|
||||
"%C3%A4%26=%E3%81%82%E3%81%A8&%23=%3F")
|
||||
|
||||
def test_parse_timestamp(self, f=text.parse_timestamp):
|
||||
null = util.datetime_utcfromtimestamp(0)
|
||||
value = util.datetime_utcfromtimestamp(1555816235)
|
||||
|
||||
self.assertEqual(f(0) , null)
|
||||
self.assertEqual(f("0") , null)
|
||||
self.assertEqual(f(1555816235) , value)
|
||||
self.assertEqual(f("1555816235"), value)
|
||||
|
||||
for value in INVALID_ALT:
|
||||
self.assertEqual(f(value), None)
|
||||
self.assertEqual(f(value, "foo"), "foo")
|
||||
|
||||
def test_parse_datetime(self, f=text.parse_datetime):
|
||||
null = util.datetime_utcfromtimestamp(0)
|
||||
|
||||
self.assertEqual(f("1970-01-01T00:00:00+00:00"), null)
|
||||
self.assertEqual(f("1970-01-01T00:00:00+0000") , null)
|
||||
self.assertEqual(f("1970.01.01", "%Y.%m.%d") , null)
|
||||
|
||||
self.assertEqual(
|
||||
f("2019-05-07T21:25:02+09:00"),
|
||||
datetime.datetime(2019, 5, 7, 12, 25, 2),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07T21:25:02+0900"),
|
||||
datetime.datetime(2019, 5, 7, 12, 25, 2),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07T21:25:02.753+0900", "%Y-%m-%dT%H:%M:%S.%f%z"),
|
||||
datetime.datetime(2019, 5, 7, 12, 25, 2),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07T21:25:02", "%Y-%m-%dT%H:%M:%S", utcoffset=9),
|
||||
datetime.datetime(2019, 5, 7, 12, 25, 2),
|
||||
)
|
||||
self.assertEqual(
|
||||
f("2019-05-07 21:25:02"),
|
||||
"2019-05-07 21:25:02",
|
||||
)
|
||||
|
||||
for value in INVALID:
|
||||
self.assertEqual(f(value), None)
|
||||
self.assertEqual(f("1970.01.01"), "1970.01.01")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -406,89 +406,6 @@ def hash(value):
|
||||
self.assertEqual(expr(value), result)
|
||||
|
||||
|
||||
class TestDatetime(unittest.TestCase):
|
||||
|
||||
def test_to_datetime(self, f=util.to_datetime):
|
||||
|
||||
def _assert(value, expected):
|
||||
result = f(value)
|
||||
self.assertIsInstance(result, datetime.datetime)
|
||||
self.assertEqual(result, expected, msg=repr(value))
|
||||
|
||||
dt = datetime.datetime(2010, 1, 1)
|
||||
self.assertIs(f(dt), dt)
|
||||
|
||||
_assert(dt , dt)
|
||||
_assert(1262304000 , dt)
|
||||
_assert(1262304000.0 , dt)
|
||||
_assert(1262304000.123, dt)
|
||||
_assert("1262304000" , dt)
|
||||
|
||||
_assert("2010-01-01" , dt)
|
||||
_assert("2010-01-01 00:00:00" , dt)
|
||||
_assert("2010-01-01T00:00:00" , dt)
|
||||
_assert("2010-01-01T00:00:00.123456" , dt)
|
||||
_assert("2009-12-31T19:00:00-05:00" , dt)
|
||||
_assert("2009-12-31T19:00:00.123456-05:00", dt)
|
||||
_assert("2010-01-01T00:00:00Z" , dt)
|
||||
_assert("2010-01-01T00:00:00.123456Z" , dt)
|
||||
|
||||
_assert(0 , util.EPOCH)
|
||||
_assert("" , util.EPOCH)
|
||||
_assert("foo", util.EPOCH)
|
||||
_assert(None , util.EPOCH)
|
||||
_assert(() , util.EPOCH)
|
||||
_assert([] , util.EPOCH)
|
||||
_assert({} , util.EPOCH)
|
||||
_assert((1, 2, 3), util.EPOCH)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x30b0000,
|
||||
"extended fromisoformat timezones")
|
||||
def test_to_datetime_tz(self, f=util.to_datetime):
|
||||
|
||||
def _assert(value, expected):
|
||||
result = f(value)
|
||||
self.assertIsInstance(result, datetime.datetime)
|
||||
self.assertEqual(result, expected, msg=repr(value))
|
||||
|
||||
dt = datetime.datetime(2010, 1, 1)
|
||||
|
||||
_assert("2009-12-31T19:00:00-05" , dt)
|
||||
_assert("2009-12-31T19:00:00-0500" , dt)
|
||||
_assert("2009-12-31T19:00:00.123456-05" , dt)
|
||||
_assert("2009-12-31T19:00:00.123456-0500" , dt)
|
||||
|
||||
def test_datetime_to_timestamp(self, f=util.datetime_to_timestamp):
|
||||
self.assertEqual(f(util.EPOCH), 0.0)
|
||||
self.assertEqual(f(datetime.datetime(2010, 1, 1)), 1262304000.0)
|
||||
self.assertEqual(f(datetime.datetime(2010, 1, 1, 0, 0, 0, 128000)),
|
||||
1262304000.128000)
|
||||
with self.assertRaises(TypeError):
|
||||
f(None)
|
||||
|
||||
def test_datetime_to_timestamp_string(
|
||||
self, f=util.datetime_to_timestamp_string):
|
||||
self.assertEqual(f(util.EPOCH), "0")
|
||||
self.assertEqual(f(datetime.datetime(2010, 1, 1)), "1262304000")
|
||||
self.assertEqual(f(None), "")
|
||||
|
||||
def test_datetime_from_timestamp(
|
||||
self, f=util.datetime_from_timestamp):
|
||||
self.assertEqual(f(0.0), util.EPOCH)
|
||||
self.assertEqual(f(1262304000.0), datetime.datetime(2010, 1, 1))
|
||||
self.assertEqual(f(1262304000.128000).replace(microsecond=0),
|
||||
datetime.datetime(2010, 1, 1, 0, 0, 0))
|
||||
|
||||
def test_datetime_utcfromtimestamp(
|
||||
self, f=util.datetime_utcfromtimestamp):
|
||||
self.assertEqual(f(0.0), util.EPOCH)
|
||||
self.assertEqual(f(1262304000.0), datetime.datetime(2010, 1, 1))
|
||||
|
||||
def test_datetime_utcnow(
|
||||
self, f=util.datetime_utcnow):
|
||||
self.assertIsInstance(f(), datetime.datetime)
|
||||
|
||||
|
||||
class TestOther(unittest.TestCase):
|
||||
|
||||
def test_bencode(self):
|
||||
|
||||
Reference in New Issue
Block a user