pull/11902/merge
Mozi 6 days ago committed by GitHub
commit 9371f1ebe2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -99,11 +99,13 @@ from yt_dlp.utils import (
remove_start,
render_table,
replace_extension,
datetime_round,
rot47,
sanitize_filename,
sanitize_path,
sanitize_url,
shell_quote,
strftime_or_none,
smuggle_url,
str_to_int,
strip_jsonp,
@ -407,6 +409,23 @@ class TestUtil(unittest.TestCase):
self.assertEqual(datetime_from_str('now+1day', precision='hour'), datetime_from_str('now+24hours', precision='auto'))
self.assertEqual(datetime_from_str('now+23hours', precision='hour'), datetime_from_str('now+23hours', precision='auto'))
def test_datetime_round(self):
self.assertEqual(datetime_round(dt.datetime.strptime('1820-05-12T01:23:45Z', '%Y-%m-%dT%H:%M:%SZ')),
dt.datetime(1820, 5, 12, tzinfo=dt.timezone.utc))
self.assertEqual(datetime_round(dt.datetime.strptime('1969-12-31T23:34:45Z', '%Y-%m-%dT%H:%M:%SZ'), 'hour'),
dt.datetime(1970, 1, 1, 0, tzinfo=dt.timezone.utc))
self.assertEqual(datetime_round(dt.datetime.strptime('2024-12-25T01:23:45Z', '%Y-%m-%dT%H:%M:%SZ'), 'minute'),
dt.datetime(2024, 12, 25, 1, 24, tzinfo=dt.timezone.utc))
self.assertEqual(datetime_round(dt.datetime.strptime('2024-12-25T01:23:45.123Z', '%Y-%m-%dT%H:%M:%S.%fZ'), 'second'),
dt.datetime(2024, 12, 25, 1, 23, 45, tzinfo=dt.timezone.utc))
self.assertEqual(datetime_round(dt.datetime.strptime('2024-12-25T01:23:45.678Z', '%Y-%m-%dT%H:%M:%S.%fZ'), 'second'),
dt.datetime(2024, 12, 25, 1, 23, 46, tzinfo=dt.timezone.utc))
def test_strftime_or_none(self):
self.assertEqual(strftime_or_none(-4722192000), '18200512')
self.assertEqual(strftime_or_none(0), '19700101')
self.assertEqual(strftime_or_none(1735084800), '20241225')
def test_daterange(self):
_20century = DateRange('19000101', '20000101')
self.assertFalse('17890714' in _20century)

@ -2692,11 +2692,7 @@ class YoutubeDL:
('modified_timestamp', 'modified_date'),
):
if info_dict.get(date_key) is None and info_dict.get(ts_key) is not None:
# Working around out-of-range timestamp values (e.g. negative ones on Windows,
# see http://bugs.python.org/issue1646728)
with contextlib.suppress(ValueError, OverflowError, OSError):
upload_date = dt.datetime.fromtimestamp(info_dict[ts_key], dt.timezone.utc)
info_dict[date_key] = upload_date.strftime('%Y%m%d')
info_dict[date_key] = strftime_or_none(info_dict[ts_key])
if not info_dict.get('release_year'):
info_dict['release_year'] = traverse_obj(info_dict, ('release_date', {lambda x: int(x[:4])}))

@ -1369,6 +1369,13 @@ def datetime_add_months(dt_, months):
return dt_.replace(year, month, day)
def datetime_from_timestamp(timestamp):
# Calling dt.datetime.fromtimestamp with negative timestamps throws error in Windows
# Ref: https://github.com/yt-dlp/yt-dlp/issues/5185, https://github.com/python/cpython/issues/94414,
# https://github.com/yt-dlp/yt-dlp/issues/6706#issuecomment-1496842642
return (dt.datetime.fromtimestamp(0, dt.timezone.utc) + dt.timedelta(seconds=timestamp))
def datetime_round(dt_, precision='day'):
"""
Round a datetime object's time to a specific precision
@ -1376,6 +1383,7 @@ def datetime_round(dt_, precision='day'):
if precision == 'microsecond':
return dt_
time_scale = 1_000_000
unit_seconds = {
'day': 86400,
'hour': 3600,
@ -1383,8 +1391,8 @@ def datetime_round(dt_, precision='day'):
'second': 1,
}
roundto = lambda x, n: ((x + n / 2) // n) * n
timestamp = roundto(calendar.timegm(dt_.timetuple()), unit_seconds[precision])
return dt.datetime.fromtimestamp(timestamp, dt.timezone.utc)
timestamp = roundto(calendar.timegm(dt_.timetuple()) + dt_.microsecond / time_scale, unit_seconds[precision])
return datetime_from_timestamp(timestamp)
def hyphenate_date(date_str):
@ -2051,12 +2059,7 @@ def strftime_or_none(timestamp, date_format='%Y%m%d', default=None):
datetime_object = None
try:
if isinstance(timestamp, (int, float)): # unix timestamp
# Using naive datetime here can break timestamp() in Windows
# Ref: https://github.com/yt-dlp/yt-dlp/issues/5185, https://github.com/python/cpython/issues/94414
# Also, dt.datetime.fromtimestamp breaks for negative timestamps
# Ref: https://github.com/yt-dlp/yt-dlp/issues/6706#issuecomment-1496842642
datetime_object = (dt.datetime.fromtimestamp(0, dt.timezone.utc)
+ dt.timedelta(seconds=timestamp))
datetime_object = datetime_from_timestamp(timestamp)
elif isinstance(timestamp, str): # assume YYYYMMDD
datetime_object = dt.datetime.strptime(timestamp, '%Y%m%d')
date_format = re.sub( # Support %s on windows

Loading…
Cancel
Save