mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-08 06:00:51 -07:00
Update Arrow to 0.10.0
This commit is contained in:
parent
bbca0b3b42
commit
960e147e10
7 changed files with 469 additions and 87 deletions
|
@ -4,5 +4,5 @@ from .arrow import Arrow
|
||||||
from .factory import ArrowFactory
|
from .factory import ArrowFactory
|
||||||
from .api import get, now, utcnow
|
from .api import get, now, utcnow
|
||||||
|
|
||||||
__version__ = '0.7.0'
|
__version__ = '0.10.0'
|
||||||
VERSION = __version__
|
VERSION = __version__
|
||||||
|
|
|
@ -51,5 +51,5 @@ def factory(type):
|
||||||
return ArrowFactory(type)
|
return ArrowFactory(type)
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['get', 'utcnow', 'now', 'factory', 'iso']
|
__all__ = ['get', 'utcnow', 'now', 'factory']
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ from dateutil import tz as dateutil_tz
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
import calendar
|
import calendar
|
||||||
import sys
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
from arrow import util, locales, parser, formatter
|
from arrow import util, locales, parser, formatter
|
||||||
|
|
||||||
|
@ -45,6 +47,7 @@ class Arrow(object):
|
||||||
|
|
||||||
_ATTRS = ['year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond']
|
_ATTRS = ['year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond']
|
||||||
_ATTRS_PLURAL = ['{0}s'.format(a) for a in _ATTRS]
|
_ATTRS_PLURAL = ['{0}s'.format(a) for a in _ATTRS]
|
||||||
|
_MONTHS_PER_QUARTER = 3
|
||||||
|
|
||||||
def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0,
|
def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0,
|
||||||
tzinfo=None):
|
tzinfo=None):
|
||||||
|
@ -306,6 +309,9 @@ class Arrow(object):
|
||||||
if name == 'week':
|
if name == 'week':
|
||||||
return self.isocalendar()[1]
|
return self.isocalendar()[1]
|
||||||
|
|
||||||
|
if name == 'quarter':
|
||||||
|
return int((self.month-1)/self._MONTHS_PER_QUARTER) + 1
|
||||||
|
|
||||||
if not name.startswith('_'):
|
if not name.startswith('_'):
|
||||||
value = getattr(self._datetime, name, None)
|
value = getattr(self._datetime, name, None)
|
||||||
|
|
||||||
|
@ -378,16 +384,16 @@ class Arrow(object):
|
||||||
>>> arw.replace(year=2014, month=6)
|
>>> arw.replace(year=2014, month=6)
|
||||||
<Arrow [2014-06-11T22:27:34.787885+00:00]>
|
<Arrow [2014-06-11T22:27:34.787885+00:00]>
|
||||||
|
|
||||||
Use plural property names to shift their current value relatively:
|
|
||||||
|
|
||||||
>>> arw.replace(years=1, months=-1)
|
|
||||||
<Arrow [2014-04-11T22:27:34.787885+00:00]>
|
|
||||||
|
|
||||||
You can also provide a timezone expression can also be replaced:
|
You can also provide a timezone expression can also be replaced:
|
||||||
|
|
||||||
>>> arw.replace(tzinfo=tz.tzlocal())
|
>>> arw.replace(tzinfo=tz.tzlocal())
|
||||||
<Arrow [2013-05-11T22:27:34.787885-07:00]>
|
<Arrow [2013-05-11T22:27:34.787885-07:00]>
|
||||||
|
|
||||||
|
Use plural property names to shift their current value relatively (**deprecated**):
|
||||||
|
|
||||||
|
>>> arw.replace(years=1, months=-1)
|
||||||
|
<Arrow [2014-04-11T22:27:34.787885+00:00]>
|
||||||
|
|
||||||
Recognized timezone expressions:
|
Recognized timezone expressions:
|
||||||
|
|
||||||
- A ``tzinfo`` object.
|
- A ``tzinfo`` object.
|
||||||
|
@ -398,21 +404,29 @@ class Arrow(object):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
absolute_kwargs = {}
|
absolute_kwargs = {}
|
||||||
relative_kwargs = {}
|
relative_kwargs = {} # TODO: DEPRECATED; remove in next release
|
||||||
|
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
|
|
||||||
if key in self._ATTRS:
|
if key in self._ATTRS:
|
||||||
absolute_kwargs[key] = value
|
absolute_kwargs[key] = value
|
||||||
elif key in self._ATTRS_PLURAL or key == 'weeks':
|
elif key in self._ATTRS_PLURAL or key in ['weeks', 'quarters']:
|
||||||
|
# TODO: DEPRECATED
|
||||||
|
warnings.warn("replace() with plural property to shift value"
|
||||||
|
"is deprecated, use shift() instead",
|
||||||
|
DeprecationWarning)
|
||||||
relative_kwargs[key] = value
|
relative_kwargs[key] = value
|
||||||
elif key == 'week':
|
elif key in ['week', 'quarter']:
|
||||||
raise AttributeError('setting absolute week is not supported')
|
raise AttributeError('setting absolute {0} is not supported'.format(key))
|
||||||
elif key !='tzinfo':
|
elif key !='tzinfo':
|
||||||
raise AttributeError()
|
raise AttributeError('unknown attribute: "{0}"'.format(key))
|
||||||
|
|
||||||
|
# core datetime does not support quarters, translate to months.
|
||||||
|
relative_kwargs.setdefault('months', 0)
|
||||||
|
relative_kwargs['months'] += relative_kwargs.pop('quarters', 0) * self._MONTHS_PER_QUARTER
|
||||||
|
|
||||||
current = self._datetime.replace(**absolute_kwargs)
|
current = self._datetime.replace(**absolute_kwargs)
|
||||||
current += relativedelta(**relative_kwargs)
|
current += relativedelta(**relative_kwargs) # TODO: DEPRECATED
|
||||||
|
|
||||||
tzinfo = kwargs.get('tzinfo')
|
tzinfo = kwargs.get('tzinfo')
|
||||||
|
|
||||||
|
@ -422,9 +436,41 @@ class Arrow(object):
|
||||||
|
|
||||||
return self.fromdatetime(current)
|
return self.fromdatetime(current)
|
||||||
|
|
||||||
|
def shift(self, **kwargs):
|
||||||
|
''' Returns a new :class:`Arrow <arrow.arrow.Arrow>` object with attributes updated
|
||||||
|
according to inputs.
|
||||||
|
|
||||||
|
Use plural property names to shift their current value relatively:
|
||||||
|
|
||||||
|
>>> import arrow
|
||||||
|
>>> arw = arrow.utcnow()
|
||||||
|
>>> arw
|
||||||
|
<Arrow [2013-05-11T22:27:34.787885+00:00]>
|
||||||
|
>>> arw.shift(years=1, months=-1)
|
||||||
|
<Arrow [2014-04-11T22:27:34.787885+00:00]>
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
relative_kwargs = {}
|
||||||
|
|
||||||
|
for key, value in kwargs.items():
|
||||||
|
|
||||||
|
if key in self._ATTRS_PLURAL or key in ['weeks', 'quarters']:
|
||||||
|
relative_kwargs[key] = value
|
||||||
|
else:
|
||||||
|
raise AttributeError()
|
||||||
|
|
||||||
|
# core datetime does not support quarters, translate to months.
|
||||||
|
relative_kwargs.setdefault('months', 0)
|
||||||
|
relative_kwargs['months'] += relative_kwargs.pop('quarters', 0) * self._MONTHS_PER_QUARTER
|
||||||
|
|
||||||
|
current = self._datetime + relativedelta(**relative_kwargs)
|
||||||
|
|
||||||
|
return self.fromdatetime(current)
|
||||||
|
|
||||||
def to(self, tz):
|
def to(self, tz):
|
||||||
''' Returns a new :class:`Arrow <arrow.arrow.Arrow>` object, converted to the target
|
''' Returns a new :class:`Arrow <arrow.arrow.Arrow>` object, converted
|
||||||
timezone.
|
to the target timezone.
|
||||||
|
|
||||||
:param tz: an expression representing a timezone.
|
:param tz: an expression representing a timezone.
|
||||||
|
|
||||||
|
@ -587,6 +633,7 @@ class Arrow(object):
|
||||||
Defaults to now in the current :class:`Arrow <arrow.arrow.Arrow>` object's timezone.
|
Defaults to now in the current :class:`Arrow <arrow.arrow.Arrow>` object's timezone.
|
||||||
:param locale: (optional) a ``str`` specifying a locale. Defaults to 'en_us'.
|
:param locale: (optional) a ``str`` specifying a locale. Defaults to 'en_us'.
|
||||||
:param only_distance: (optional) returns only time difference eg: "11 seconds" without "in" or "ago" part.
|
:param only_distance: (optional) returns only time difference eg: "11 seconds" without "in" or "ago" part.
|
||||||
|
|
||||||
Usage::
|
Usage::
|
||||||
|
|
||||||
>>> earlier = arrow.utcnow().replace(hours=-2)
|
>>> earlier = arrow.utcnow().replace(hours=-2)
|
||||||
|
@ -651,7 +698,8 @@ class Arrow(object):
|
||||||
elif diff < 29808000:
|
elif diff < 29808000:
|
||||||
self_months = self._datetime.year * 12 + self._datetime.month
|
self_months = self._datetime.year * 12 + self._datetime.month
|
||||||
other_months = dt.year * 12 + dt.month
|
other_months = dt.year * 12 + dt.month
|
||||||
months = sign * abs(other_months - self_months)
|
|
||||||
|
months = sign * int(max(abs(other_months - self_months), 2))
|
||||||
|
|
||||||
return locale.describe('months', months, only_distance=only_distance)
|
return locale.describe('months', months, only_distance=only_distance)
|
||||||
|
|
||||||
|
@ -676,7 +724,7 @@ class Arrow(object):
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
|
|
||||||
if isinstance(other, timedelta):
|
if isinstance(other, (timedelta, relativedelta)):
|
||||||
return self.fromdatetime(self._datetime - other, self._datetime.tzinfo)
|
return self.fromdatetime(self._datetime - other, self._datetime.tzinfo)
|
||||||
|
|
||||||
elif isinstance(other, datetime):
|
elif isinstance(other, datetime):
|
||||||
|
@ -688,7 +736,11 @@ class Arrow(object):
|
||||||
raise TypeError()
|
raise TypeError()
|
||||||
|
|
||||||
def __rsub__(self, other):
|
def __rsub__(self, other):
|
||||||
return self.__sub__(other)
|
|
||||||
|
if isinstance(other, datetime):
|
||||||
|
return other - self._datetime
|
||||||
|
|
||||||
|
raise TypeError()
|
||||||
|
|
||||||
|
|
||||||
# comparisons
|
# comparisons
|
||||||
|
@ -702,8 +754,6 @@ class Arrow(object):
|
||||||
if not isinstance(other, (Arrow, datetime)):
|
if not isinstance(other, (Arrow, datetime)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
other = self._get_datetime(other)
|
|
||||||
|
|
||||||
return self._datetime == self._get_datetime(other)
|
return self._datetime == self._get_datetime(other)
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
|
@ -882,7 +932,9 @@ class Arrow(object):
|
||||||
return cls.max, limit
|
return cls.max, limit
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return end, sys.maxsize
|
if limit is None:
|
||||||
|
return end, sys.maxsize
|
||||||
|
return end, limit
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_timestamp_from_input(timestamp):
|
def _get_timestamp_from_input(timestamp):
|
||||||
|
|
|
@ -94,7 +94,7 @@ class DateTimeFormatter(object):
|
||||||
tz = dateutil_tz.tzutc() if dt.tzinfo is None else dt.tzinfo
|
tz = dateutil_tz.tzutc() if dt.tzinfo is None else dt.tzinfo
|
||||||
total_minutes = int(util.total_seconds(tz.utcoffset(dt)) / 60)
|
total_minutes = int(util.total_seconds(tz.utcoffset(dt)) / 60)
|
||||||
|
|
||||||
sign = '+' if total_minutes > 0 else '-'
|
sign = '+' if total_minutes >= 0 else '-'
|
||||||
total_minutes = abs(total_minutes)
|
total_minutes = abs(total_minutes)
|
||||||
hour, minute = divmod(total_minutes, 60)
|
hour, minute = divmod(total_minutes, 60)
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ import sys
|
||||||
|
|
||||||
|
|
||||||
def get_locale(name):
|
def get_locale(name):
|
||||||
'''Returns an appropriate :class:`Locale <locale.Locale>` corresponding
|
'''Returns an appropriate :class:`Locale <arrow.locales.Locale>`
|
||||||
to an inpute locale name.
|
corresponding to an inpute locale name.
|
||||||
|
|
||||||
:param name: the name of the locale.
|
:param name: the name of the locale.
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ class Locale(object):
|
||||||
|
|
||||||
class EnglishLocale(Locale):
|
class EnglishLocale(Locale):
|
||||||
|
|
||||||
names = ['en', 'en_us', 'en_gb', 'en_au', 'en_be', 'en_jp', 'en_za']
|
names = ['en', 'en_us', 'en_gb', 'en_au', 'en_be', 'en_jp', 'en_za', 'en_ca']
|
||||||
|
|
||||||
past = '{0} ago'
|
past = '{0} ago'
|
||||||
future = 'in {0}'
|
future = 'in {0}'
|
||||||
|
@ -263,10 +263,10 @@ class ItalianLocale(Locale):
|
||||||
day_names = ['', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato', 'domenica']
|
day_names = ['', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato', 'domenica']
|
||||||
day_abbreviations = ['', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab', 'dom']
|
day_abbreviations = ['', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab', 'dom']
|
||||||
|
|
||||||
ordinal_day_re = r'((?P<value>[1-3]?[0-9](?=°))°)'
|
ordinal_day_re = r'((?P<value>[1-3]?[0-9](?=[ºª]))[ºª])'
|
||||||
|
|
||||||
def _ordinal_number(self, n):
|
def _ordinal_number(self, n):
|
||||||
return '{0}°'.format(n)
|
return '{0}º'.format(n)
|
||||||
|
|
||||||
|
|
||||||
class SpanishLocale(Locale):
|
class SpanishLocale(Locale):
|
||||||
|
@ -297,10 +297,10 @@ class SpanishLocale(Locale):
|
||||||
day_names = ['', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo']
|
day_names = ['', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo']
|
||||||
day_abbreviations = ['', 'lun', 'mar', 'mie', 'jue', 'vie', 'sab', 'dom']
|
day_abbreviations = ['', 'lun', 'mar', 'mie', 'jue', 'vie', 'sab', 'dom']
|
||||||
|
|
||||||
ordinal_day_re = r'((?P<value>[1-3]?[0-9](?=°))°)'
|
ordinal_day_re = r'((?P<value>[1-3]?[0-9](?=[ºª]))[ºª])'
|
||||||
|
|
||||||
def _ordinal_number(self, n):
|
def _ordinal_number(self, n):
|
||||||
return '{0}°'.format(n)
|
return '{0}º'.format(n)
|
||||||
|
|
||||||
|
|
||||||
class FrenchLocale(Locale):
|
class FrenchLocale(Locale):
|
||||||
|
@ -379,7 +379,7 @@ class JapaneseLocale(Locale):
|
||||||
|
|
||||||
timeframes = {
|
timeframes = {
|
||||||
'now': '現在',
|
'now': '現在',
|
||||||
'seconds': '秒',
|
'seconds': '数秒',
|
||||||
'minute': '1分',
|
'minute': '1分',
|
||||||
'minutes': '{0}分',
|
'minutes': '{0}分',
|
||||||
'hour': '1時間',
|
'hour': '1時間',
|
||||||
|
@ -559,8 +559,8 @@ class KoreanLocale(Locale):
|
||||||
|
|
||||||
timeframes = {
|
timeframes = {
|
||||||
'now': '지금',
|
'now': '지금',
|
||||||
'seconds': '몇초',
|
'seconds': '몇 초',
|
||||||
'minute': '일 분',
|
'minute': '1분',
|
||||||
'minutes': '{0}분',
|
'minutes': '{0}분',
|
||||||
'hour': '1시간',
|
'hour': '1시간',
|
||||||
'hours': '{0}시간',
|
'hours': '{0}시간',
|
||||||
|
@ -1034,7 +1034,7 @@ class TurkishLocale(Locale):
|
||||||
'days': '{0} gün',
|
'days': '{0} gün',
|
||||||
'month': 'bir ay',
|
'month': 'bir ay',
|
||||||
'months': '{0} ay',
|
'months': '{0} ay',
|
||||||
'year': 'a yıl',
|
'year': 'yıl',
|
||||||
'years': '{0} yıl',
|
'years': '{0} yıl',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,6 +1047,37 @@ class TurkishLocale(Locale):
|
||||||
day_abbreviations = ['', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt', 'Paz']
|
day_abbreviations = ['', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt', 'Paz']
|
||||||
|
|
||||||
|
|
||||||
|
class AzerbaijaniLocale(Locale):
|
||||||
|
|
||||||
|
names = ['az', 'az_az']
|
||||||
|
|
||||||
|
past = '{0} əvvəl'
|
||||||
|
future = '{0} sonra'
|
||||||
|
|
||||||
|
timeframes = {
|
||||||
|
'now': 'indi',
|
||||||
|
'seconds': 'saniyə',
|
||||||
|
'minute': 'bir dəqiqə',
|
||||||
|
'minutes': '{0} dəqiqə',
|
||||||
|
'hour': 'bir saat',
|
||||||
|
'hours': '{0} saat',
|
||||||
|
'day': 'bir gün',
|
||||||
|
'days': '{0} gün',
|
||||||
|
'month': 'bir ay',
|
||||||
|
'months': '{0} ay',
|
||||||
|
'year': 'il',
|
||||||
|
'years': '{0} il',
|
||||||
|
}
|
||||||
|
|
||||||
|
month_names = ['', 'Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun', 'İyul',
|
||||||
|
'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr']
|
||||||
|
month_abbreviations = ['', 'Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq',
|
||||||
|
'Sen', 'Okt', 'Noy', 'Dek']
|
||||||
|
|
||||||
|
day_names = ['', 'Bazar ertəsi', 'Çərşənbə axşamı', 'Çərşənbə', 'Cümə axşamı', 'Cümə', 'Şənbə', 'Bazar']
|
||||||
|
day_abbreviations = ['', 'Ber', 'Çax', 'Çər', 'Cax', 'Cüm', 'Şnb', 'Bzr']
|
||||||
|
|
||||||
|
|
||||||
class ArabicLocale(Locale):
|
class ArabicLocale(Locale):
|
||||||
|
|
||||||
names = ['ar', 'ar_eg']
|
names = ['ar', 'ar_eg']
|
||||||
|
@ -1205,11 +1236,11 @@ class HindiLocale(Locale):
|
||||||
future = '{0} बाद'
|
future = '{0} बाद'
|
||||||
|
|
||||||
timeframes = {
|
timeframes = {
|
||||||
'now': 'अभि',
|
'now': 'अभी',
|
||||||
'seconds': 'सेकंड्',
|
'seconds': 'सेकंड्',
|
||||||
'minute': 'एक मिनट ',
|
'minute': 'एक मिनट ',
|
||||||
'minutes': '{0} मिनट ',
|
'minutes': '{0} मिनट ',
|
||||||
'hour': 'एक घंट',
|
'hour': 'एक घंटा',
|
||||||
'hours': '{0} घंटे',
|
'hours': '{0} घंटे',
|
||||||
'day': 'एक दिन',
|
'day': 'एक दिन',
|
||||||
'days': '{0} दिन',
|
'days': '{0} दिन',
|
||||||
|
@ -1226,8 +1257,8 @@ class HindiLocale(Locale):
|
||||||
'PM': 'शाम',
|
'PM': 'शाम',
|
||||||
}
|
}
|
||||||
|
|
||||||
month_names = ['', 'जनवरी', 'फ़रवरी', 'मार्च', 'अप्रैल ', 'मई', 'जून', 'जुलाई',
|
month_names = ['', 'जनवरी', 'फरवरी', 'मार्च', 'अप्रैल ', 'मई', 'जून', 'जुलाई',
|
||||||
'आगस्त', 'सितम्बर', 'अकतूबर', 'नवेम्बर', 'दिसम्बर']
|
'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर']
|
||||||
month_abbreviations = ['', 'जन', 'फ़र', 'मार्च', 'अप्रै', 'मई', 'जून', 'जुलाई', 'आग',
|
month_abbreviations = ['', 'जन', 'फ़र', 'मार्च', 'अप्रै', 'मई', 'जून', 'जुलाई', 'आग',
|
||||||
'सित', 'अकत', 'नवे', 'दिस']
|
'सित', 'अकत', 'नवे', 'दिस']
|
||||||
|
|
||||||
|
@ -1284,7 +1315,8 @@ class CzechLocale(Locale):
|
||||||
|
|
||||||
|
|
||||||
def _format_timeframe(self, timeframe, delta):
|
def _format_timeframe(self, timeframe, delta):
|
||||||
'''Czech aware time frame format function, takes into account the differences between past and future forms.'''
|
'''Czech aware time frame format function, takes into account
|
||||||
|
the differences between past and future forms.'''
|
||||||
form = self.timeframes[timeframe]
|
form = self.timeframes[timeframe]
|
||||||
if isinstance(form, dict):
|
if isinstance(form, dict):
|
||||||
if delta == 0:
|
if delta == 0:
|
||||||
|
@ -1303,6 +1335,78 @@ class CzechLocale(Locale):
|
||||||
|
|
||||||
return form.format(delta)
|
return form.format(delta)
|
||||||
|
|
||||||
|
|
||||||
|
class SlovakLocale(Locale):
|
||||||
|
names = ['sk', 'sk_sk']
|
||||||
|
|
||||||
|
timeframes = {
|
||||||
|
'now': 'Teraz',
|
||||||
|
'seconds': {
|
||||||
|
'past': 'pár sekundami',
|
||||||
|
'future': ['{0} sekundy', '{0} sekúnd']
|
||||||
|
},
|
||||||
|
'minute': {'past': 'minútou', 'future': 'minútu', 'zero': '{0} minút'},
|
||||||
|
'minutes': {
|
||||||
|
'past': '{0} minútami',
|
||||||
|
'future': ['{0} minúty', '{0} minút']
|
||||||
|
},
|
||||||
|
'hour': {'past': 'hodinou', 'future': 'hodinu', 'zero': '{0} hodín'},
|
||||||
|
'hours': {
|
||||||
|
'past': '{0} hodinami',
|
||||||
|
'future': ['{0} hodiny', '{0} hodín']
|
||||||
|
},
|
||||||
|
'day': {'past': 'dňom', 'future': 'deň', 'zero': '{0} dní'},
|
||||||
|
'days': {
|
||||||
|
'past': '{0} dňami',
|
||||||
|
'future': ['{0} dni', '{0} dní']
|
||||||
|
},
|
||||||
|
'month': {'past': 'mesiacom', 'future': 'mesiac', 'zero': '{0} mesiacov'},
|
||||||
|
'months': {
|
||||||
|
'past': '{0} mesiacmi',
|
||||||
|
'future': ['{0} mesiace', '{0} mesiacov']
|
||||||
|
},
|
||||||
|
'year': {'past': 'rokom', 'future': 'rok', 'zero': '{0} rokov'},
|
||||||
|
'years': {
|
||||||
|
'past': '{0} rokmi',
|
||||||
|
'future': ['{0} roky', '{0} rokov']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
past = 'Pred {0}'
|
||||||
|
future = 'O {0}'
|
||||||
|
|
||||||
|
month_names = ['', 'január', 'február', 'marec', 'apríl', 'máj', 'jún',
|
||||||
|
'júl', 'august', 'september', 'október', 'november', 'december']
|
||||||
|
month_abbreviations = ['', 'jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl',
|
||||||
|
'aug', 'sep', 'okt', 'nov', 'dec']
|
||||||
|
|
||||||
|
day_names = ['', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok',
|
||||||
|
'sobota', 'nedeľa']
|
||||||
|
day_abbreviations = ['', 'po', 'ut', 'st', 'št', 'pi', 'so', 'ne']
|
||||||
|
|
||||||
|
|
||||||
|
def _format_timeframe(self, timeframe, delta):
|
||||||
|
'''Slovak aware time frame format function, takes into account
|
||||||
|
the differences between past and future forms.'''
|
||||||
|
form = self.timeframes[timeframe]
|
||||||
|
if isinstance(form, dict):
|
||||||
|
if delta == 0:
|
||||||
|
form = form['zero'] # And *never* use 0 in the singular!
|
||||||
|
elif delta > 0:
|
||||||
|
form = form['future']
|
||||||
|
else:
|
||||||
|
form = form['past']
|
||||||
|
delta = abs(delta)
|
||||||
|
|
||||||
|
if isinstance(form, list):
|
||||||
|
if 2 <= delta % 10 <= 4 and (delta % 100 < 10 or delta % 100 >= 20):
|
||||||
|
form = form[0]
|
||||||
|
else:
|
||||||
|
form = form[1]
|
||||||
|
|
||||||
|
return form.format(delta)
|
||||||
|
|
||||||
|
|
||||||
class FarsiLocale(Locale):
|
class FarsiLocale(Locale):
|
||||||
|
|
||||||
names = ['fa', 'fa_ir']
|
names = ['fa', 'fa_ir']
|
||||||
|
@ -1475,10 +1579,10 @@ def _map_locales():
|
||||||
|
|
||||||
return locales
|
return locales
|
||||||
|
|
||||||
class CatalaLocale(Locale):
|
class CatalanLocale(Locale):
|
||||||
names = ['ca', 'ca_ca']
|
names = ['ca', 'ca_es', 'ca_ad', 'ca_fr', 'ca_it']
|
||||||
past = 'Fa {0}'
|
past = 'Fa {0}'
|
||||||
future = '{0}' # I don't know what's the right phrase in catala for the future.
|
future = 'En {0}'
|
||||||
|
|
||||||
timeframes = {
|
timeframes = {
|
||||||
'now': 'Ara mateix',
|
'now': 'Ara mateix',
|
||||||
|
@ -1490,15 +1594,15 @@ class CatalaLocale(Locale):
|
||||||
'day': 'un dia',
|
'day': 'un dia',
|
||||||
'days': '{0} dies',
|
'days': '{0} dies',
|
||||||
'month': 'un mes',
|
'month': 'un mes',
|
||||||
'months': '{0} messos',
|
'months': '{0} mesos',
|
||||||
'year': 'un any',
|
'year': 'un any',
|
||||||
'years': '{0} anys',
|
'years': '{0} anys',
|
||||||
}
|
}
|
||||||
|
|
||||||
month_names = ['', 'Jener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Decembre']
|
month_names = ['', 'Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre']
|
||||||
month_abbreviations = ['', 'Jener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Decembre']
|
month_abbreviations = ['', 'Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre']
|
||||||
day_names = ['', 'Dilluns', 'Dimars', 'Dimecres', 'Dijous', 'Divendres', 'Disabte', 'Diumenge']
|
day_names = ['', 'Dilluns', 'Dimarts', 'Dimecres', 'Dijous', 'Divendres', 'Dissabte', 'Diumenge']
|
||||||
day_abbreviations = ['', 'Dilluns', 'Dimars', 'Dimecres', 'Dijous', 'Divendres', 'Disabte', 'Diumenge']
|
day_abbreviations = ['', 'Dilluns', 'Dimarts', 'Dimecres', 'Dijous', 'Divendres', 'Dissabte', 'Diumenge']
|
||||||
|
|
||||||
class BasqueLocale(Locale):
|
class BasqueLocale(Locale):
|
||||||
names = ['eu', 'eu_eu']
|
names = ['eu', 'eu_eu']
|
||||||
|
@ -1587,6 +1691,50 @@ class HungarianLocale(Locale):
|
||||||
return form.format(abs(delta))
|
return form.format(abs(delta))
|
||||||
|
|
||||||
|
|
||||||
|
class EsperantoLocale(Locale):
|
||||||
|
names = ['eo', 'eo_xx']
|
||||||
|
past = 'antaŭ {0}'
|
||||||
|
future = 'post {0}'
|
||||||
|
|
||||||
|
timeframes = {
|
||||||
|
'now': 'nun',
|
||||||
|
'seconds': 'kelkaj sekundoj',
|
||||||
|
'minute': 'unu minuto',
|
||||||
|
'minutes': '{0} minutoj',
|
||||||
|
'hour': 'un horo',
|
||||||
|
'hours': '{0} horoj',
|
||||||
|
'day': 'unu tago',
|
||||||
|
'days': '{0} tagoj',
|
||||||
|
'month': 'unu monato',
|
||||||
|
'months': '{0} monatoj',
|
||||||
|
'year': 'unu jaro',
|
||||||
|
'years': '{0} jaroj',
|
||||||
|
}
|
||||||
|
|
||||||
|
month_names = ['', 'januaro', 'februaro', 'marto', 'aprilo', 'majo',
|
||||||
|
'junio', 'julio', 'aŭgusto', 'septembro', 'oktobro',
|
||||||
|
'novembro', 'decembro']
|
||||||
|
month_abbreviations = ['', 'jan', 'feb', 'mar', 'apr', 'maj', 'jun',
|
||||||
|
'jul', 'aŭg', 'sep', 'okt', 'nov', 'dec']
|
||||||
|
|
||||||
|
day_names = ['', 'lundo', 'mardo', 'merkredo', 'ĵaŭdo', 'vendredo',
|
||||||
|
'sabato', 'dimanĉo']
|
||||||
|
day_abbreviations = ['', 'lun', 'mar', 'mer', 'ĵaŭ', 'ven',
|
||||||
|
'sab', 'dim']
|
||||||
|
|
||||||
|
meridians = {
|
||||||
|
'am': 'atm',
|
||||||
|
'pm': 'ptm',
|
||||||
|
'AM': 'ATM',
|
||||||
|
'PM': 'PTM',
|
||||||
|
}
|
||||||
|
|
||||||
|
ordinal_day_re = r'((?P<value>[1-3]?[0-9](?=a))a)'
|
||||||
|
|
||||||
|
def _ordinal_number(self, n):
|
||||||
|
return '{0}a'.format(n)
|
||||||
|
|
||||||
|
|
||||||
class ThaiLocale(Locale):
|
class ThaiLocale(Locale):
|
||||||
|
|
||||||
names = ['th', 'th_th']
|
names = ['th', 'th_th']
|
||||||
|
@ -1700,4 +1848,164 @@ class BengaliLocale(Locale):
|
||||||
return '{0}ষ্ঠ'.format(n)
|
return '{0}ষ্ঠ'.format(n)
|
||||||
|
|
||||||
|
|
||||||
|
class RomanshLocale(Locale):
|
||||||
|
|
||||||
|
names = ['rm', 'rm_ch']
|
||||||
|
|
||||||
|
past = 'avant {0}'
|
||||||
|
future = 'en {0}'
|
||||||
|
|
||||||
|
timeframes = {
|
||||||
|
'now': 'en quest mument',
|
||||||
|
'seconds': 'secundas',
|
||||||
|
'minute': 'ina minuta',
|
||||||
|
'minutes': '{0} minutas',
|
||||||
|
'hour': 'in\'ura',
|
||||||
|
'hours': '{0} ura',
|
||||||
|
'day': 'in di',
|
||||||
|
'days': '{0} dis',
|
||||||
|
'month': 'in mais',
|
||||||
|
'months': '{0} mais',
|
||||||
|
'year': 'in onn',
|
||||||
|
'years': '{0} onns',
|
||||||
|
}
|
||||||
|
|
||||||
|
month_names = [
|
||||||
|
'', 'schaner', 'favrer', 'mars', 'avrigl', 'matg', 'zercladur',
|
||||||
|
'fanadur', 'avust', 'settember', 'october', 'november', 'december'
|
||||||
|
]
|
||||||
|
|
||||||
|
month_abbreviations = [
|
||||||
|
'', 'schan', 'fav', 'mars', 'avr', 'matg', 'zer', 'fan', 'avu',
|
||||||
|
'set', 'oct', 'nov', 'dec'
|
||||||
|
]
|
||||||
|
|
||||||
|
day_names = [
|
||||||
|
'', 'glindesdi', 'mardi', 'mesemna', 'gievgia', 'venderdi',
|
||||||
|
'sonda', 'dumengia'
|
||||||
|
]
|
||||||
|
|
||||||
|
day_abbreviations = [
|
||||||
|
'', 'gli', 'ma', 'me', 'gie', 've', 'so', 'du'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class SwissLocale(Locale):
|
||||||
|
|
||||||
|
names = ['de', 'de_ch']
|
||||||
|
|
||||||
|
past = 'vor {0}'
|
||||||
|
future = 'in {0}'
|
||||||
|
|
||||||
|
timeframes = {
|
||||||
|
'now': 'gerade eben',
|
||||||
|
'seconds': 'Sekunden',
|
||||||
|
'minute': 'einer Minute',
|
||||||
|
'minutes': '{0} Minuten',
|
||||||
|
'hour': 'einer Stunde',
|
||||||
|
'hours': '{0} Stunden',
|
||||||
|
'day': 'einem Tag',
|
||||||
|
'days': '{0} Tage',
|
||||||
|
'month': 'einem Monat',
|
||||||
|
'months': '{0} Monaten',
|
||||||
|
'year': 'einem Jahr',
|
||||||
|
'years': '{0} Jahren',
|
||||||
|
}
|
||||||
|
|
||||||
|
month_names = [
|
||||||
|
'', 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
|
||||||
|
'August', 'September', 'Oktober', 'November', 'Dezember'
|
||||||
|
]
|
||||||
|
|
||||||
|
month_abbreviations = [
|
||||||
|
'', 'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep',
|
||||||
|
'Okt', 'Nov', 'Dez'
|
||||||
|
]
|
||||||
|
|
||||||
|
day_names = [
|
||||||
|
'', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag',
|
||||||
|
'Samstag', 'Sonntag'
|
||||||
|
]
|
||||||
|
|
||||||
|
day_abbreviations = [
|
||||||
|
'', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class RomanianLocale(Locale):
|
||||||
|
names = ['ro', 'ro_ro']
|
||||||
|
|
||||||
|
past = '{0} în urmă'
|
||||||
|
future = 'peste {0}'
|
||||||
|
|
||||||
|
timeframes = {
|
||||||
|
'now': 'acum',
|
||||||
|
'seconds': 'câteva secunde',
|
||||||
|
'minute': 'un minut',
|
||||||
|
'minutes': '{0} minute',
|
||||||
|
'hour': 'o oră',
|
||||||
|
'hours': '{0} ore',
|
||||||
|
'day': 'o zi',
|
||||||
|
'days': '{0} zile',
|
||||||
|
'month': 'o lună',
|
||||||
|
'months': '{0} luni',
|
||||||
|
'year': 'un an',
|
||||||
|
'years': '{0} ani',
|
||||||
|
}
|
||||||
|
|
||||||
|
month_names = ['', 'ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie', 'iulie',
|
||||||
|
'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie']
|
||||||
|
month_abbreviations = ['', 'ian', 'febr', 'mart', 'apr', 'mai', 'iun', 'iul', 'aug', 'sept', 'oct', 'nov', 'dec']
|
||||||
|
|
||||||
|
day_names = ['', 'luni', 'marți', 'miercuri', 'joi', 'vineri', 'sâmbătă', 'duminică']
|
||||||
|
day_abbreviations = ['', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm', 'Dum']
|
||||||
|
|
||||||
|
|
||||||
|
class SlovenianLocale(Locale):
|
||||||
|
names = ['sl', 'sl_si']
|
||||||
|
|
||||||
|
past = 'pred {0}'
|
||||||
|
future = 'čez {0}'
|
||||||
|
|
||||||
|
timeframes = {
|
||||||
|
'now': 'zdaj',
|
||||||
|
'seconds': 'sekund',
|
||||||
|
'minute': 'minuta',
|
||||||
|
'minutes': '{0} minutami',
|
||||||
|
'hour': 'uro',
|
||||||
|
'hours': '{0} ur',
|
||||||
|
'day': 'dan',
|
||||||
|
'days': '{0} dni',
|
||||||
|
'month': 'mesec',
|
||||||
|
'months': '{0} mesecev',
|
||||||
|
'year': 'leto',
|
||||||
|
'years': '{0} let',
|
||||||
|
}
|
||||||
|
|
||||||
|
meridians = {
|
||||||
|
'am': '',
|
||||||
|
'pm': '',
|
||||||
|
'AM': '',
|
||||||
|
'PM': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
month_names = [
|
||||||
|
'', 'Januar', 'Februar', 'Marec', 'April', 'Maj', 'Junij', 'Julij',
|
||||||
|
'Avgust', 'September', 'Oktober', 'November', 'December'
|
||||||
|
]
|
||||||
|
|
||||||
|
month_abbreviations = [
|
||||||
|
'', 'Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg',
|
||||||
|
'Sep', 'Okt', 'Nov', 'Dec'
|
||||||
|
]
|
||||||
|
|
||||||
|
day_names = [
|
||||||
|
'', 'Ponedeljek', 'Torek', 'Sreda', 'Četrtek', 'Petek', 'Sobota', 'Nedelja'
|
||||||
|
]
|
||||||
|
|
||||||
|
day_abbreviations = [
|
||||||
|
'', 'Pon', 'Tor', 'Sre', 'Čet', 'Pet', 'Sob', 'Ned'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
_locales = _map_locales()
|
_locales = _map_locales()
|
||||||
|
|
|
@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from dateutil import tz
|
from dateutil import tz
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from arrow import locales
|
from arrow import locales
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,16 +14,14 @@ class ParserError(RuntimeError):
|
||||||
|
|
||||||
class DateTimeParser(object):
|
class DateTimeParser(object):
|
||||||
|
|
||||||
_FORMAT_RE = re.compile('(YYY?Y?|MM?M?M?|Do|DD?D?D?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X)')
|
_FORMAT_RE = re.compile('(YYY?Y?|MM?M?M?|Do|DD?D?D?|d?d?d?d|HH?|hh?|mm?|ss?|S+|ZZ?Z?|a|A|X)')
|
||||||
|
_ESCAPE_RE = re.compile('\[[^\[\]]*\]')
|
||||||
|
|
||||||
_ONE_THROUGH_SIX_DIGIT_RE = re.compile('\d{1,6}')
|
_ONE_OR_MORE_DIGIT_RE = re.compile('\d+')
|
||||||
_ONE_THROUGH_FIVE_DIGIT_RE = re.compile('\d{1,5}')
|
|
||||||
_ONE_THROUGH_FOUR_DIGIT_RE = re.compile('\d{1,4}')
|
|
||||||
_ONE_TWO_OR_THREE_DIGIT_RE = re.compile('\d{1,3}')
|
|
||||||
_ONE_OR_TWO_DIGIT_RE = re.compile('\d{1,2}')
|
_ONE_OR_TWO_DIGIT_RE = re.compile('\d{1,2}')
|
||||||
_FOUR_DIGIT_RE = re.compile('\d{4}')
|
_FOUR_DIGIT_RE = re.compile('\d{4}')
|
||||||
_TWO_DIGIT_RE = re.compile('\d{2}')
|
_TWO_DIGIT_RE = re.compile('\d{2}')
|
||||||
_TZ_RE = re.compile('[+\-]?\d{2}:?\d{2}')
|
_TZ_RE = re.compile('[+\-]?\d{2}:?(\d{2})?')
|
||||||
_TZ_NAME_RE = re.compile('\w[\w+\-/]+')
|
_TZ_NAME_RE = re.compile('\w[\w+\-/]+')
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,12 +44,7 @@ class DateTimeParser(object):
|
||||||
'ZZZ': _TZ_NAME_RE,
|
'ZZZ': _TZ_NAME_RE,
|
||||||
'ZZ': _TZ_RE,
|
'ZZ': _TZ_RE,
|
||||||
'Z': _TZ_RE,
|
'Z': _TZ_RE,
|
||||||
'SSSSSS': _ONE_THROUGH_SIX_DIGIT_RE,
|
'S': _ONE_OR_MORE_DIGIT_RE,
|
||||||
'SSSSS': _ONE_THROUGH_FIVE_DIGIT_RE,
|
|
||||||
'SSSS': _ONE_THROUGH_FOUR_DIGIT_RE,
|
|
||||||
'SSS': _ONE_TWO_OR_THREE_DIGIT_RE,
|
|
||||||
'SS': _ONE_OR_TWO_DIGIT_RE,
|
|
||||||
'S': re.compile('\d'),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MARKERS = ['YYYY', 'MM', 'DD']
|
MARKERS = ['YYYY', 'MM', 'DD']
|
||||||
|
@ -67,6 +59,10 @@ class DateTimeParser(object):
|
||||||
'MMM': self._choice_re(self.locale.month_abbreviations[1:],
|
'MMM': self._choice_re(self.locale.month_abbreviations[1:],
|
||||||
re.IGNORECASE),
|
re.IGNORECASE),
|
||||||
'Do': re.compile(self.locale.ordinal_day_re),
|
'Do': re.compile(self.locale.ordinal_day_re),
|
||||||
|
'dddd': self._choice_re(self.locale.day_names[1:], re.IGNORECASE),
|
||||||
|
'ddd': self._choice_re(self.locale.day_abbreviations[1:],
|
||||||
|
re.IGNORECASE),
|
||||||
|
'd' : re.compile("[1-7]"),
|
||||||
'a': self._choice_re(
|
'a': self._choice_re(
|
||||||
(self.locale.meridians['am'], self.locale.meridians['pm'])
|
(self.locale.meridians['am'], self.locale.meridians['pm'])
|
||||||
),
|
),
|
||||||
|
@ -88,11 +84,10 @@ class DateTimeParser(object):
|
||||||
time_parts = re.split('[+-]', time_string, 1)
|
time_parts = re.split('[+-]', time_string, 1)
|
||||||
has_tz = len(time_parts) > 1
|
has_tz = len(time_parts) > 1
|
||||||
has_seconds = time_parts[0].count(':') > 1
|
has_seconds = time_parts[0].count(':') > 1
|
||||||
has_subseconds = '.' in time_parts[0]
|
has_subseconds = re.search('[.,]', time_parts[0])
|
||||||
|
|
||||||
if has_subseconds:
|
if has_subseconds:
|
||||||
subseconds_token = 'S' * min(len(re.split('\D+', time_parts[0].split('.')[1], 1)[0]), 6)
|
formats = ['YYYY-MM-DDTHH:mm:ss%sS' % has_subseconds.group()]
|
||||||
formats = ['YYYY-MM-DDTHH:mm:ss.%s' % subseconds_token]
|
|
||||||
elif has_seconds:
|
elif has_seconds:
|
||||||
formats = ['YYYY-MM-DDTHH:mm:ss']
|
formats = ['YYYY-MM-DDTHH:mm:ss']
|
||||||
else:
|
else:
|
||||||
|
@ -123,10 +118,18 @@ class DateTimeParser(object):
|
||||||
# we construct a new string by replacing each
|
# we construct a new string by replacing each
|
||||||
# token by its pattern:
|
# token by its pattern:
|
||||||
# 'YYYY-MM-DD' -> '(?P<YYYY>\d{4})-(?P<MM>\d{2})-(?P<DD>\d{2})'
|
# 'YYYY-MM-DD' -> '(?P<YYYY>\d{4})-(?P<MM>\d{2})-(?P<DD>\d{2})'
|
||||||
fmt_pattern = fmt
|
|
||||||
tokens = []
|
tokens = []
|
||||||
offset = 0
|
offset = 0
|
||||||
for m in self._FORMAT_RE.finditer(fmt):
|
|
||||||
|
# Extract the bracketed expressions to be reinserted later.
|
||||||
|
escaped_fmt = re.sub(self._ESCAPE_RE, "#" , fmt)
|
||||||
|
# Any number of S is the same as one.
|
||||||
|
escaped_fmt = re.sub('S+', 'S', escaped_fmt)
|
||||||
|
escaped_data = re.findall(self._ESCAPE_RE, fmt)
|
||||||
|
|
||||||
|
fmt_pattern = escaped_fmt
|
||||||
|
|
||||||
|
for m in self._FORMAT_RE.finditer(escaped_fmt):
|
||||||
token = m.group(0)
|
token = m.group(0)
|
||||||
try:
|
try:
|
||||||
input_re = self._input_re_map[token]
|
input_re = self._input_re_map[token]
|
||||||
|
@ -140,9 +143,20 @@ class DateTimeParser(object):
|
||||||
# are returned in the order found by finditer.
|
# are returned in the order found by finditer.
|
||||||
fmt_pattern = fmt_pattern[:m.start() + offset] + input_pattern + fmt_pattern[m.end() + offset:]
|
fmt_pattern = fmt_pattern[:m.start() + offset] + input_pattern + fmt_pattern[m.end() + offset:]
|
||||||
offset += len(input_pattern) - (m.end() - m.start())
|
offset += len(input_pattern) - (m.end() - m.start())
|
||||||
match = re.search(fmt_pattern, string, flags=re.IGNORECASE)
|
|
||||||
|
final_fmt_pattern = ""
|
||||||
|
a = fmt_pattern.split("#")
|
||||||
|
b = escaped_data
|
||||||
|
|
||||||
|
# Due to the way Python splits, 'a' will always be longer
|
||||||
|
for i in range(len(a)):
|
||||||
|
final_fmt_pattern += a[i]
|
||||||
|
if i < len(b):
|
||||||
|
final_fmt_pattern += b[i][1:-1]
|
||||||
|
|
||||||
|
match = re.search(final_fmt_pattern, string, flags=re.IGNORECASE)
|
||||||
if match is None:
|
if match is None:
|
||||||
raise ParserError('Failed to match \'{0}\' when parsing \'{1}\''.format(fmt_pattern, string))
|
raise ParserError('Failed to match \'{0}\' when parsing \'{1}\''.format(final_fmt_pattern, string))
|
||||||
parts = {}
|
parts = {}
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
if token == 'Do':
|
if token == 'Do':
|
||||||
|
@ -181,18 +195,22 @@ class DateTimeParser(object):
|
||||||
elif token in ['ss', 's']:
|
elif token in ['ss', 's']:
|
||||||
parts['second'] = int(value)
|
parts['second'] = int(value)
|
||||||
|
|
||||||
elif token == 'SSSSSS':
|
|
||||||
parts['microsecond'] = int(value)
|
|
||||||
elif token == 'SSSSS':
|
|
||||||
parts['microsecond'] = int(value) * 10
|
|
||||||
elif token == 'SSSS':
|
|
||||||
parts['microsecond'] = int(value) * 100
|
|
||||||
elif token == 'SSS':
|
|
||||||
parts['microsecond'] = int(value) * 1000
|
|
||||||
elif token == 'SS':
|
|
||||||
parts['microsecond'] = int(value) * 10000
|
|
||||||
elif token == 'S':
|
elif token == 'S':
|
||||||
parts['microsecond'] = int(value) * 100000
|
# We have the *most significant* digits of an arbitrary-precision integer.
|
||||||
|
# We want the six most significant digits as an integer, rounded.
|
||||||
|
# FIXME: add nanosecond support somehow?
|
||||||
|
value = value.ljust(7, str('0'))
|
||||||
|
|
||||||
|
# floating-point (IEEE-754) defaults to half-to-even rounding
|
||||||
|
seventh_digit = int(value[6])
|
||||||
|
if seventh_digit == 5:
|
||||||
|
rounding = int(value[5]) % 2
|
||||||
|
elif seventh_digit > 5:
|
||||||
|
rounding = 1
|
||||||
|
else:
|
||||||
|
rounding = 0
|
||||||
|
|
||||||
|
parts['microsecond'] = int(value[:6]) + rounding
|
||||||
|
|
||||||
elif token == 'X':
|
elif token == 'X':
|
||||||
parts['timestamp'] = int(value)
|
parts['timestamp'] = int(value)
|
||||||
|
@ -242,7 +260,7 @@ class DateTimeParser(object):
|
||||||
try:
|
try:
|
||||||
_datetime = self.parse(string, fmt)
|
_datetime = self.parse(string, fmt)
|
||||||
break
|
break
|
||||||
except:
|
except ParserError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if _datetime is None:
|
if _datetime is None:
|
||||||
|
@ -273,7 +291,7 @@ class DateTimeParser(object):
|
||||||
|
|
||||||
class TzinfoParser(object):
|
class TzinfoParser(object):
|
||||||
|
|
||||||
_TZINFO_RE = re.compile('([+\-])?(\d\d):?(\d\d)')
|
_TZINFO_RE = re.compile('([+\-])?(\d\d):?(\d\d)?')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, string):
|
def parse(cls, string):
|
||||||
|
@ -292,6 +310,8 @@ class TzinfoParser(object):
|
||||||
|
|
||||||
if iso_match:
|
if iso_match:
|
||||||
sign, hours, minutes = iso_match.groups()
|
sign, hours, minutes = iso_match.groups()
|
||||||
|
if minutes is None:
|
||||||
|
minutes = 0
|
||||||
seconds = int(hours) * 3600 + int(minutes) * 60
|
seconds = int(hours) * 3600 + int(minutes) * 60
|
||||||
|
|
||||||
if sign == '-':
|
if sign == '-':
|
||||||
|
@ -303,6 +323,6 @@ class TzinfoParser(object):
|
||||||
tzinfo = tz.gettz(string)
|
tzinfo = tz.gettz(string)
|
||||||
|
|
||||||
if tzinfo is None:
|
if tzinfo is None:
|
||||||
raise ParserError('Could not parse timezone expression "{0}"', string)
|
raise ParserError('Could not parse timezone expression "{0}"'.format(string))
|
||||||
|
|
||||||
return tzinfo
|
return tzinfo
|
||||||
|
|
|
@ -22,6 +22,8 @@ else: # pragma: no cover
|
||||||
total_seconds = _total_seconds_27
|
total_seconds = _total_seconds_27
|
||||||
|
|
||||||
def is_timestamp(value):
|
def is_timestamp(value):
|
||||||
|
if type(value) == bool:
|
||||||
|
return False
|
||||||
try:
|
try:
|
||||||
float(value)
|
float(value)
|
||||||
return True
|
return True
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue