mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-07 21:51:14 -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 .api import get, now, utcnow
|
||||
|
||||
__version__ = '0.7.0'
|
||||
__version__ = '0.10.0'
|
||||
VERSION = __version__
|
||||
|
|
|
@ -51,5 +51,5 @@ def factory(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
|
||||
import calendar
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
|
||||
from arrow import util, locales, parser, formatter
|
||||
|
||||
|
@ -45,6 +47,7 @@ class Arrow(object):
|
|||
|
||||
_ATTRS = ['year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond']
|
||||
_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,
|
||||
tzinfo=None):
|
||||
|
@ -306,6 +309,9 @@ class Arrow(object):
|
|||
if name == 'week':
|
||||
return self.isocalendar()[1]
|
||||
|
||||
if name == 'quarter':
|
||||
return int((self.month-1)/self._MONTHS_PER_QUARTER) + 1
|
||||
|
||||
if not name.startswith('_'):
|
||||
value = getattr(self._datetime, name, None)
|
||||
|
||||
|
@ -378,16 +384,16 @@ class Arrow(object):
|
|||
>>> arw.replace(year=2014, month=6)
|
||||
<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:
|
||||
|
||||
>>> arw.replace(tzinfo=tz.tzlocal())
|
||||
<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:
|
||||
|
||||
- A ``tzinfo`` object.
|
||||
|
@ -398,21 +404,29 @@ class Arrow(object):
|
|||
'''
|
||||
|
||||
absolute_kwargs = {}
|
||||
relative_kwargs = {}
|
||||
relative_kwargs = {} # TODO: DEPRECATED; remove in next release
|
||||
|
||||
for key, value in kwargs.items():
|
||||
|
||||
if key in self._ATTRS:
|
||||
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
|
||||
elif key == 'week':
|
||||
raise AttributeError('setting absolute week is not supported')
|
||||
elif key in ['week', 'quarter']:
|
||||
raise AttributeError('setting absolute {0} is not supported'.format(key))
|
||||
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 += relativedelta(**relative_kwargs)
|
||||
current += relativedelta(**relative_kwargs) # TODO: DEPRECATED
|
||||
|
||||
tzinfo = kwargs.get('tzinfo')
|
||||
|
||||
|
@ -422,9 +436,41 @@ class Arrow(object):
|
|||
|
||||
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):
|
||||
''' Returns a new :class:`Arrow <arrow.arrow.Arrow>` object, converted to the target
|
||||
timezone.
|
||||
''' Returns a new :class:`Arrow <arrow.arrow.Arrow>` object, converted
|
||||
to the target 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.
|
||||
: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.
|
||||
|
||||
Usage::
|
||||
|
||||
>>> earlier = arrow.utcnow().replace(hours=-2)
|
||||
|
@ -651,7 +698,8 @@ class Arrow(object):
|
|||
elif diff < 29808000:
|
||||
self_months = self._datetime.year * 12 + self._datetime.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)
|
||||
|
||||
|
@ -676,7 +724,7 @@ class Arrow(object):
|
|||
|
||||
def __sub__(self, other):
|
||||
|
||||
if isinstance(other, timedelta):
|
||||
if isinstance(other, (timedelta, relativedelta)):
|
||||
return self.fromdatetime(self._datetime - other, self._datetime.tzinfo)
|
||||
|
||||
elif isinstance(other, datetime):
|
||||
|
@ -688,7 +736,11 @@ class Arrow(object):
|
|||
raise TypeError()
|
||||
|
||||
def __rsub__(self, other):
|
||||
return self.__sub__(other)
|
||||
|
||||
if isinstance(other, datetime):
|
||||
return other - self._datetime
|
||||
|
||||
raise TypeError()
|
||||
|
||||
|
||||
# comparisons
|
||||
|
@ -702,8 +754,6 @@ class Arrow(object):
|
|||
if not isinstance(other, (Arrow, datetime)):
|
||||
return False
|
||||
|
||||
other = self._get_datetime(other)
|
||||
|
||||
return self._datetime == self._get_datetime(other)
|
||||
|
||||
def __ne__(self, other):
|
||||
|
@ -882,7 +932,9 @@ class Arrow(object):
|
|||
return cls.max, limit
|
||||
|
||||
else:
|
||||
if limit is None:
|
||||
return end, sys.maxsize
|
||||
return end, limit
|
||||
|
||||
@staticmethod
|
||||
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
|
||||
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)
|
||||
hour, minute = divmod(total_minutes, 60)
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ import sys
|
|||
|
||||
|
||||
def get_locale(name):
|
||||
'''Returns an appropriate :class:`Locale <locale.Locale>` corresponding
|
||||
to an inpute locale name.
|
||||
'''Returns an appropriate :class:`Locale <arrow.locales.Locale>`
|
||||
corresponding to an inpute locale name.
|
||||
|
||||
:param name: the name of the locale.
|
||||
|
||||
|
@ -186,7 +186,7 @@ class Locale(object):
|
|||
|
||||
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'
|
||||
future = 'in {0}'
|
||||
|
@ -263,10 +263,10 @@ class ItalianLocale(Locale):
|
|||
day_names = ['', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato', 'domenica']
|
||||
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):
|
||||
return '{0}°'.format(n)
|
||||
return '{0}º'.format(n)
|
||||
|
||||
|
||||
class SpanishLocale(Locale):
|
||||
|
@ -297,10 +297,10 @@ class SpanishLocale(Locale):
|
|||
day_names = ['', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo']
|
||||
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):
|
||||
return '{0}°'.format(n)
|
||||
return '{0}º'.format(n)
|
||||
|
||||
|
||||
class FrenchLocale(Locale):
|
||||
|
@ -379,7 +379,7 @@ class JapaneseLocale(Locale):
|
|||
|
||||
timeframes = {
|
||||
'now': '現在',
|
||||
'seconds': '秒',
|
||||
'seconds': '数秒',
|
||||
'minute': '1分',
|
||||
'minutes': '{0}分',
|
||||
'hour': '1時間',
|
||||
|
@ -560,7 +560,7 @@ class KoreanLocale(Locale):
|
|||
timeframes = {
|
||||
'now': '지금',
|
||||
'seconds': '몇 초',
|
||||
'minute': '일 분',
|
||||
'minute': '1분',
|
||||
'minutes': '{0}분',
|
||||
'hour': '1시간',
|
||||
'hours': '{0}시간',
|
||||
|
@ -1034,7 +1034,7 @@ class TurkishLocale(Locale):
|
|||
'days': '{0} gün',
|
||||
'month': 'bir ay',
|
||||
'months': '{0} ay',
|
||||
'year': 'a yıl',
|
||||
'year': 'yıl',
|
||||
'years': '{0} yıl',
|
||||
}
|
||||
|
||||
|
@ -1047,6 +1047,37 @@ class TurkishLocale(Locale):
|
|||
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):
|
||||
|
||||
names = ['ar', 'ar_eg']
|
||||
|
@ -1205,11 +1236,11 @@ class HindiLocale(Locale):
|
|||
future = '{0} बाद'
|
||||
|
||||
timeframes = {
|
||||
'now': 'अभि',
|
||||
'now': 'अभी',
|
||||
'seconds': 'सेकंड्',
|
||||
'minute': 'एक मिनट ',
|
||||
'minutes': '{0} मिनट ',
|
||||
'hour': 'एक घंट',
|
||||
'hour': 'एक घंटा',
|
||||
'hours': '{0} घंटे',
|
||||
'day': 'एक दिन',
|
||||
'days': '{0} दिन',
|
||||
|
@ -1226,8 +1257,8 @@ class HindiLocale(Locale):
|
|||
'PM': 'शाम',
|
||||
}
|
||||
|
||||
month_names = ['', 'जनवरी', 'फ़रवरी', 'मार्च', 'अप्रैल ', 'मई', 'जून', 'जुलाई',
|
||||
'आगस्त', 'सितम्बर', 'अकतूबर', 'नवेम्बर', 'दिसम्बर']
|
||||
month_names = ['', 'जनवरी', 'फरवरी', 'मार्च', 'अप्रैल ', 'मई', 'जून', 'जुलाई',
|
||||
'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर']
|
||||
month_abbreviations = ['', 'जन', 'फ़र', 'मार्च', 'अप्रै', 'मई', 'जून', 'जुलाई', 'आग',
|
||||
'सित', 'अकत', 'नवे', 'दिस']
|
||||
|
||||
|
@ -1284,7 +1315,8 @@ class CzechLocale(Locale):
|
|||
|
||||
|
||||
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]
|
||||
if isinstance(form, dict):
|
||||
if delta == 0:
|
||||
|
@ -1303,6 +1335,78 @@ class CzechLocale(Locale):
|
|||
|
||||
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):
|
||||
|
||||
names = ['fa', 'fa_ir']
|
||||
|
@ -1475,10 +1579,10 @@ def _map_locales():
|
|||
|
||||
return locales
|
||||
|
||||
class CatalaLocale(Locale):
|
||||
names = ['ca', 'ca_ca']
|
||||
class CatalanLocale(Locale):
|
||||
names = ['ca', 'ca_es', 'ca_ad', 'ca_fr', 'ca_it']
|
||||
past = 'Fa {0}'
|
||||
future = '{0}' # I don't know what's the right phrase in catala for the future.
|
||||
future = 'En {0}'
|
||||
|
||||
timeframes = {
|
||||
'now': 'Ara mateix',
|
||||
|
@ -1490,15 +1594,15 @@ class CatalaLocale(Locale):
|
|||
'day': 'un dia',
|
||||
'days': '{0} dies',
|
||||
'month': 'un mes',
|
||||
'months': '{0} messos',
|
||||
'months': '{0} mesos',
|
||||
'year': 'un any',
|
||||
'years': '{0} anys',
|
||||
}
|
||||
|
||||
month_names = ['', 'Jener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Decembre']
|
||||
month_abbreviations = ['', 'Jener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Decembre']
|
||||
day_names = ['', 'Dilluns', 'Dimars', 'Dimecres', 'Dijous', 'Divendres', 'Disabte', 'Diumenge']
|
||||
day_abbreviations = ['', 'Dilluns', 'Dimars', 'Dimecres', 'Dijous', 'Divendres', 'Disabte', 'Diumenge']
|
||||
month_names = ['', 'Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre']
|
||||
month_abbreviations = ['', 'Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre']
|
||||
day_names = ['', 'Dilluns', 'Dimarts', 'Dimecres', 'Dijous', 'Divendres', 'Dissabte', 'Diumenge']
|
||||
day_abbreviations = ['', 'Dilluns', 'Dimarts', 'Dimecres', 'Dijous', 'Divendres', 'Dissabte', 'Diumenge']
|
||||
|
||||
class BasqueLocale(Locale):
|
||||
names = ['eu', 'eu_eu']
|
||||
|
@ -1587,6 +1691,50 @@ class HungarianLocale(Locale):
|
|||
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):
|
||||
|
||||
names = ['th', 'th_th']
|
||||
|
@ -1700,4 +1848,164 @@ class BengaliLocale(Locale):
|
|||
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()
|
||||
|
|
|
@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
|||
from datetime import datetime
|
||||
from dateutil import tz
|
||||
import re
|
||||
|
||||
from arrow import locales
|
||||
|
||||
|
||||
|
@ -15,16 +14,14 @@ class ParserError(RuntimeError):
|
|||
|
||||
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_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_MORE_DIGIT_RE = re.compile('\d+')
|
||||
_ONE_OR_TWO_DIGIT_RE = re.compile('\d{1,2}')
|
||||
_FOUR_DIGIT_RE = re.compile('\d{4}')
|
||||
_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+\-/]+')
|
||||
|
||||
|
||||
|
@ -47,12 +44,7 @@ class DateTimeParser(object):
|
|||
'ZZZ': _TZ_NAME_RE,
|
||||
'ZZ': _TZ_RE,
|
||||
'Z': _TZ_RE,
|
||||
'SSSSSS': _ONE_THROUGH_SIX_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'),
|
||||
'S': _ONE_OR_MORE_DIGIT_RE,
|
||||
}
|
||||
|
||||
MARKERS = ['YYYY', 'MM', 'DD']
|
||||
|
@ -67,6 +59,10 @@ class DateTimeParser(object):
|
|||
'MMM': self._choice_re(self.locale.month_abbreviations[1:],
|
||||
re.IGNORECASE),
|
||||
'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(
|
||||
(self.locale.meridians['am'], self.locale.meridians['pm'])
|
||||
),
|
||||
|
@ -88,11 +84,10 @@ class DateTimeParser(object):
|
|||
time_parts = re.split('[+-]', time_string, 1)
|
||||
has_tz = len(time_parts) > 1
|
||||
has_seconds = time_parts[0].count(':') > 1
|
||||
has_subseconds = '.' in time_parts[0]
|
||||
has_subseconds = re.search('[.,]', time_parts[0])
|
||||
|
||||
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.%s' % subseconds_token]
|
||||
formats = ['YYYY-MM-DDTHH:mm:ss%sS' % has_subseconds.group()]
|
||||
elif has_seconds:
|
||||
formats = ['YYYY-MM-DDTHH:mm:ss']
|
||||
else:
|
||||
|
@ -123,10 +118,18 @@ class DateTimeParser(object):
|
|||
# we construct a new string by replacing each
|
||||
# token by its pattern:
|
||||
# 'YYYY-MM-DD' -> '(?P<YYYY>\d{4})-(?P<MM>\d{2})-(?P<DD>\d{2})'
|
||||
fmt_pattern = fmt
|
||||
tokens = []
|
||||
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)
|
||||
try:
|
||||
input_re = self._input_re_map[token]
|
||||
|
@ -140,9 +143,20 @@ class DateTimeParser(object):
|
|||
# are returned in the order found by finditer.
|
||||
fmt_pattern = fmt_pattern[:m.start() + offset] + input_pattern + fmt_pattern[m.end() + offset:]
|
||||
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:
|
||||
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 = {}
|
||||
for token in tokens:
|
||||
if token == 'Do':
|
||||
|
@ -181,18 +195,22 @@ class DateTimeParser(object):
|
|||
elif token in ['ss', 's']:
|
||||
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':
|
||||
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':
|
||||
parts['timestamp'] = int(value)
|
||||
|
@ -242,7 +260,7 @@ class DateTimeParser(object):
|
|||
try:
|
||||
_datetime = self.parse(string, fmt)
|
||||
break
|
||||
except:
|
||||
except ParserError:
|
||||
pass
|
||||
|
||||
if _datetime is None:
|
||||
|
@ -273,7 +291,7 @@ class DateTimeParser(object):
|
|||
|
||||
class TzinfoParser(object):
|
||||
|
||||
_TZINFO_RE = re.compile('([+\-])?(\d\d):?(\d\d)')
|
||||
_TZINFO_RE = re.compile('([+\-])?(\d\d):?(\d\d)?')
|
||||
|
||||
@classmethod
|
||||
def parse(cls, string):
|
||||
|
@ -292,6 +310,8 @@ class TzinfoParser(object):
|
|||
|
||||
if iso_match:
|
||||
sign, hours, minutes = iso_match.groups()
|
||||
if minutes is None:
|
||||
minutes = 0
|
||||
seconds = int(hours) * 3600 + int(minutes) * 60
|
||||
|
||||
if sign == '-':
|
||||
|
@ -303,6 +323,6 @@ class TzinfoParser(object):
|
|||
tzinfo = tz.gettz(string)
|
||||
|
||||
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
|
||||
|
|
|
@ -22,6 +22,8 @@ else: # pragma: no cover
|
|||
total_seconds = _total_seconds_27
|
||||
|
||||
def is_timestamp(value):
|
||||
if type(value) == bool:
|
||||
return False
|
||||
try:
|
||||
float(value)
|
||||
return True
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue