astrXbian/.install/.kodi/addons/plugin.video.youtube/resources/lib/youtube_plugin/kodion/utils/datetime_parser.py

190 lines
7.8 KiB
Python
Raw Normal View History

2020-12-17 21:52:17 +01:00
# -*- coding: utf-8 -*-
"""
Copyright (C) 2014-2016 bromix (plugin.video.youtube)
Copyright (C) 2016-2018 plugin.video.youtube
SPDX-License-Identifier: GPL-2.0-only
See LICENSES/GPL-2.0-only for more information.
"""
import re
import time
from datetime import date, datetime, timedelta
from datetime import time as dt_time
from six import PY2
from six import text_type
from ..exceptions import KodionException
__RE_MATCH_TIME_ONLY__ = re.compile(r'^(?P<hour>[0-9]{2})([:]?(?P<minute>[0-9]{2})([:]?(?P<second>[0-9]{2}))?)?$')
__RE_MATCH_DATE_ONLY__ = re.compile(r'^(?P<year>[0-9]{4})[-]?(?P<month>[0-9]{2})[-]?(?P<day>[0-9]{2})$')
__RE_MATCH_DATETIME__ = re.compile(r'^(?P<year>[0-9]{4})[-]?(?P<month>[0-9]{2})[-]?(?P<day>[0-9]{2})["T ](?P<hour>[0-9]{2})[:]?(?P<minute>[0-9]{2})[:]?(?P<second>[0-9]{2})')
__RE_MATCH_PERIOD__ = re.compile(r'P((?P<years>\d+)Y)?((?P<months>\d+)M)?((?P<days>\d+)D)?(T((?P<hours>\d+)H)?((?P<minutes>\d+)M)?((?P<seconds>\d+)S)?)?')
__RE_MATCH_ABBREVIATED__ = re.compile(r'(\w+), (?P<day>\d+) (?P<month>\w+) (?P<year>\d+) (?P<hour>\d+):(?P<minute>\d+):(?P<second>\d+)')
now = datetime.now
def py2_utf8(text):
result = text
if PY2 and isinstance(result, text_type):
return result.encode('utf-8', 'ignore')
return result
def parse(datetime_string, localize=True):
_utc_to_local = utc_to_local if localize else lambda x: x
def _to_int(value):
if value is None:
return 0
return int(value)
# match time only '00:45:10'
time_only_match = __RE_MATCH_TIME_ONLY__.match(datetime_string)
if time_only_match:
return _utc_to_local(datetime.combine(date.today(),
dt_time(hour=_to_int(time_only_match.group('hour')),
minute=_to_int(time_only_match.group('minute')),
second=_to_int(time_only_match.group('second'))))
).time()
# match date only '2014-11-08'
date_only_match = __RE_MATCH_DATE_ONLY__.match(datetime_string)
if date_only_match:
return _utc_to_local(date(_to_int(date_only_match.group('year')),
_to_int(date_only_match.group('month')),
_to_int(date_only_match.group('day'))))
# full date time
date_time_match = __RE_MATCH_DATETIME__.match(datetime_string)
if date_time_match:
return _utc_to_local(datetime(_to_int(date_time_match.group('year')),
_to_int(date_time_match.group('month')),
_to_int(date_time_match.group('day')),
_to_int(date_time_match.group('hour')),
_to_int(date_time_match.group('minute')),
_to_int(date_time_match.group('second'))))
# period - at the moment we support only hours, minutes and seconds (e.g. videos and audio)
period_match = __RE_MATCH_PERIOD__.match(datetime_string)
if period_match:
return timedelta(hours=_to_int(period_match.group('hours')),
minutes=_to_int(period_match.group('minutes')),
seconds=_to_int(period_match.group('seconds')))
# abbreviated match
abbreviated_match = __RE_MATCH_ABBREVIATED__.match(datetime_string)
if abbreviated_match:
month = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'June': 6, 'Jun': 6, 'July': 7, 'Jul': 7, 'Aug': 8,
'Sept': 9, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
return _utc_to_local(datetime(year=_to_int(abbreviated_match.group('year')),
month=month[abbreviated_match.group('month')],
day=_to_int(abbreviated_match.group('day')),
hour=_to_int(abbreviated_match.group('hour')),
minute=_to_int(abbreviated_match.group('minute')),
second=_to_int(abbreviated_match.group('second'))))
raise KodionException("Could not parse iso 8601 timestamp '%s'" % datetime_string)
def get_scheduled_start(datetime_object, localize=True):
start_hour = '{:02d}'.format(datetime_object.hour)
start_minute = '{:<02d}'.format(datetime_object.minute)
start_time = ':'.join([start_hour, start_minute])
start_date = str(datetime_object.date())
if localize:
now = datetime.now()
else:
now = datetime.utcnow()
start_date = start_date.replace(str(now.year), '').lstrip('-')
start_date = start_date.replace('-'.join(['{:02d}'.format(now.month), '{:02d}'.format(now.day)]), '')
return start_date, start_time
local_timezone_offset = None
def utc_to_local(dt):
global local_timezone_offset
if local_timezone_offset is None:
now = time.time()
local_timezone_offset = datetime.fromtimestamp(now) - datetime.utcfromtimestamp(now)
return dt + local_timezone_offset
def datetime_to_since(context, dt):
now = datetime.now()
diff = now - dt
yesterday = now - timedelta(days=1)
yyesterday = now - timedelta(days=2)
use_yesterday = total_seconds(now - yesterday) > 10800
today = now.date()
tomorrow = today + timedelta(days=1)
seconds = total_seconds(diff)
if seconds > 0:
if seconds < 60:
return py2_utf8(context.localize('30676'))
elif 60 <= seconds < 120:
return py2_utf8(context.localize('30677'))
elif 120 <= seconds < 3600:
return py2_utf8(context.localize('30678'))
elif 3600 <= seconds < 7200:
return py2_utf8(context.localize('30679'))
elif 7200 <= seconds < 10800:
return py2_utf8(context.localize('30680'))
elif 10800 <= seconds < 14400:
return py2_utf8(context.localize('30681'))
elif use_yesterday and dt.date() == yesterday.date():
return ' '.join([py2_utf8(context.localize('30682')), context.format_time(dt)])
elif dt.date() == yyesterday.date():
return py2_utf8(context.localize('30683'))
elif 5400 <= seconds < 86400:
return ' '.join([py2_utf8(context.localize('30684')), context.format_time(dt)])
elif 86400 <= seconds < 172800:
return ' '.join([py2_utf8(context.localize('30682')), context.format_time(dt)])
else:
seconds *= -1
if seconds < 60:
return py2_utf8(context.localize('30691'))
elif 60 <= seconds < 120:
return py2_utf8(context.localize('30692'))
elif 120 <= seconds < 3600:
return py2_utf8(context.localize('30693'))
elif 3600 <= seconds < 7200:
return py2_utf8(context.localize('30694'))
elif 7200 <= seconds < 10800:
return py2_utf8(context.localize('30695'))
elif dt.date() == today:
return ' '.join([py2_utf8(context.localize('30696')), context.format_time(dt)])
elif dt.date() == tomorrow:
return ' '.join([py2_utf8(context.localize('30697')), context.format_time(dt)])
return ' '.join([context.format_date_short(dt), context.format_time(dt)])
def strptime(s, fmt='%Y-%m-%dT%H:%M:%S.%fZ'):
# noinspection PyUnresolvedReferences
ms_precision = '.' in s[-5:-1]
if fmt == '%Y-%m-%dT%H:%M:%S.%fZ' and not ms_precision:
fmt = '%Y-%m-%dT%H:%M:%SZ'
elif fmt == '%Y-%m-%dT%H:%M:%SZ' and ms_precision:
fmt = '%Y-%m-%dT%H:%M:%S.%fZ'
import _strptime
try:
time.strptime('01 01 2012', '%d %m %Y') # dummy call
except:
pass
return datetime(*time.strptime(s, fmt)[:6])
def total_seconds(t_delta): # required for python 2.6 which doesn't have datetime.timedelta.total_seconds
return 24 * 60 * 60 * t_delta.days + t_delta.seconds + (t_delta.microseconds // 1000000.)