mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-22 03:33:08 +00:00
Improve parsing to datetime and add error handling (#1203)
* Improve parsing to datetime and add error handling * Fix utils.millisecondToHumanstr for days and negatives * Update tests for millisecondToHumanstr
This commit is contained in:
parent
a7d29a3638
commit
35008908fc
2 changed files with 29 additions and 17 deletions
|
@ -11,13 +11,13 @@ import unicodedata
|
||||||
import warnings
|
import warnings
|
||||||
import zipfile
|
import zipfile
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from getpass import getpass
|
from getpass import getpass
|
||||||
from threading import Event, Thread
|
from threading import Event, Thread
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
from requests.status_codes import _codes as codes
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from requests.status_codes import _codes as codes
|
||||||
|
|
||||||
from plexapi.exceptions import BadRequest, NotFound, Unauthorized
|
from plexapi.exceptions import BadRequest, NotFound, Unauthorized
|
||||||
|
|
||||||
|
@ -313,33 +313,39 @@ def toDatetime(value, format=None):
|
||||||
value (str): value to return as a datetime
|
value (str): value to return as a datetime
|
||||||
format (str): Format to pass strftime (optional; if value is a str).
|
format (str): Format to pass strftime (optional; if value is a str).
|
||||||
"""
|
"""
|
||||||
if value and value is not None:
|
if value is not None:
|
||||||
if format:
|
if format:
|
||||||
try:
|
try:
|
||||||
value = datetime.strptime(value, format)
|
return datetime.strptime(value, format)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
log.info('Failed to parse %s to datetime, defaulting to None', value)
|
log.info('Failed to parse "%s" to datetime as format "%s", defaulting to None', value, format)
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
# https://bugs.python.org/issue30684
|
try:
|
||||||
# And platform support for before epoch seems to be flaky.
|
return datetime.utcfromtimestamp(0) + timedelta(seconds=int(value))
|
||||||
# Also limit to max 32-bit integer
|
except ValueError:
|
||||||
value = min(max(int(value), 86400), 2**31 - 1)
|
log.info('Failed to parse "%s" to datetime as timestamp, defaulting to None', value)
|
||||||
value = datetime.fromtimestamp(int(value))
|
return None
|
||||||
|
except OverflowError:
|
||||||
|
log.info('Failed to parse "%s" to datetime as timestamp (out-of-bounds), defaulting to None', value)
|
||||||
|
return None
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def millisecondToHumanstr(milliseconds):
|
def millisecondToHumanstr(milliseconds):
|
||||||
""" Returns human readable time duration from milliseconds.
|
""" Returns human readable time duration [D day[s], ]HH:MM:SS.UUU from milliseconds.
|
||||||
HH:MM:SS:MMMM
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
milliseconds (str,int): time duration in milliseconds.
|
milliseconds (str, int): time duration in milliseconds.
|
||||||
"""
|
"""
|
||||||
milliseconds = int(milliseconds)
|
milliseconds = int(milliseconds)
|
||||||
r = datetime.utcfromtimestamp(milliseconds / 1000)
|
if milliseconds < 0:
|
||||||
f = r.strftime("%H:%M:%S.%f")
|
return '-' + millisecondToHumanstr(abs(milliseconds))
|
||||||
return f[:-2]
|
secs, ms = divmod(milliseconds, 1000)
|
||||||
|
mins, secs = divmod(secs, 60)
|
||||||
|
hours, mins = divmod(mins, 60)
|
||||||
|
days, hours = divmod(hours, 24)
|
||||||
|
return ('' if days == 0 else f'{days} day{"s" if days > 1 else ""}, ') + f'{hours:02d}:{mins:02d}:{secs:02d}.{ms:03d}'
|
||||||
|
|
||||||
|
|
||||||
def toList(value, itemcast=None, delim=','):
|
def toList(value, itemcast=None, delim=','):
|
||||||
|
|
|
@ -90,7 +90,13 @@ def test_utils_download(plex, episode):
|
||||||
|
|
||||||
def test_millisecondToHumanstr():
|
def test_millisecondToHumanstr():
|
||||||
res = utils.millisecondToHumanstr(1000)
|
res = utils.millisecondToHumanstr(1000)
|
||||||
assert res == "00:00:01.0000"
|
assert res == "00:00:01.000"
|
||||||
|
res = utils.millisecondToHumanstr(-1000)
|
||||||
|
assert res == "-00:00:01.000"
|
||||||
|
res = utils.millisecondToHumanstr(123456789)
|
||||||
|
assert res == "1 day, 10:17:36.789"
|
||||||
|
res = utils.millisecondToHumanstr(-123456789)
|
||||||
|
assert res == "-1 day, 10:17:36.789"
|
||||||
|
|
||||||
|
|
||||||
def test_toJson(movie):
|
def test_toJson(movie):
|
||||||
|
|
Loading…
Reference in a new issue