Make bundle portable by bundling third party packages we need
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
SCRIPT_PATH = os.path.realpath(__file__)
|
||||
SCRIPT_DIR = os.path.dirname(SCRIPT_PATH)
|
||||
sys.path.append(os.path.join(SCRIPT_DIR, "third_party"))
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import foundation
|
||||
|
@@ -1,9 +1,12 @@
|
||||
import json
|
||||
import multiprocessing
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from third_party import cpuinfo
|
||||
# Usually comes from third_party
|
||||
import cpuinfo
|
||||
import cpu_cores
|
||||
|
||||
|
||||
def _getBlenderDeviceInfo(ctx):
|
||||
@@ -55,28 +58,7 @@ def getBlenderVersion(ctx):
|
||||
return info
|
||||
|
||||
|
||||
def getNumPhysicalCPUs_Linux():
|
||||
ids = set()
|
||||
with open("/proc/cpuinfo") as f:
|
||||
for line in f.readlines():
|
||||
if line.startswith("physical id"):
|
||||
id = int(line.split(":", 1)[1])
|
||||
ids.add(id)
|
||||
return len(ids)
|
||||
|
||||
|
||||
def getNumPhysicalCPUs():
|
||||
if sys.platform == 'linux':
|
||||
return getNumPhysicalCPUs_Linux()
|
||||
elif sys.platform == 'win32':
|
||||
# TODO(sergey): Currently all WIndows machines here are single socket.
|
||||
return 1
|
||||
else:
|
||||
raise Exception("Needs implementation")
|
||||
|
||||
|
||||
def gatherSystemInfo(ctx):
|
||||
import psutil
|
||||
system_info = {}
|
||||
system_info['bitness'] = platform.architecture()[0]
|
||||
system_info['machine'] = platform.machine()
|
||||
@@ -88,10 +70,11 @@ def gatherSystemInfo(ctx):
|
||||
# system_info['libc_version'] = "-".join(platform.libc_ver())
|
||||
# TODO(sergey): Make this to work on Windows and macOS
|
||||
cpu_info = cpuinfo.get_cpu_info()
|
||||
cores_info = cpu_cores.CPUCoresCounter.factory()
|
||||
system_info['cpu_brand'] = cpu_info['brand']
|
||||
system_info["num_cpu_cores"] = psutil.cpu_count(logical=False)
|
||||
system_info["num_cpu_threads"] = psutil.cpu_count(logical=True)
|
||||
system_info["num_cpu_sockets"] = getNumPhysicalCPUs()
|
||||
system_info["num_cpu_cores"] = cores_info.get_physical_cores_count()
|
||||
system_info["num_cpu_threads"] = multiprocessing.cpu_count()
|
||||
system_info["num_cpu_sockets"] = cores_info.get_physical_processors_count()
|
||||
system_info['devices'] = _getBlenderDeviceInfo(ctx)
|
||||
# TODO(sergey): query number of CPUs and threads.
|
||||
return system_info
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import foundation
|
||||
from foundation import progress
|
||||
import dateutil
|
||||
import os
|
||||
import requests
|
||||
import tarfile
|
||||
@@ -133,7 +134,6 @@ def blenderCommitUnixTimestamp(commit_date, commit_time):
|
||||
"""
|
||||
Convert commit build time and time to unix timestamp
|
||||
"""
|
||||
import dateutil
|
||||
date_time = commit_date + " " + commit_time
|
||||
return dateutil.parser.parse(date_time)
|
||||
|
||||
|
@@ -1,5 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
SCRIPT_PATH = os.path.realpath(__file__)
|
||||
SCRIPT_DIR = os.path.dirname(SCRIPT_PATH)
|
||||
sys.path.append(os.path.join(SCRIPT_DIR, "third_party"))
|
||||
|
||||
import argparse
|
||||
import foundation
|
||||
from foundation import (benchrunner,
|
||||
@@ -79,21 +86,21 @@ def _printFullResult(ctx, results):
|
||||
for scene in ctx.scenes:
|
||||
if scene not in stats:
|
||||
continue
|
||||
stats = stats[scene]
|
||||
scene_stats = stats[scene]
|
||||
print(" {}:" . format(scene))
|
||||
print(" - Engine render time: {}" . format(
|
||||
util.humanReadableTimeDifference(
|
||||
stats.total_render_time)))
|
||||
scene_stats.total_render_time)))
|
||||
print(" - Render time without sync: {}" . format(
|
||||
util.humanReadableTimeDifference(
|
||||
stats.render_time_no_sync)))
|
||||
scene_stats.render_time_no_sync)))
|
||||
print(" - Total render time: {}" . format(
|
||||
util.humanReadableTimeDifference(
|
||||
stats.pipeline_render_time)))
|
||||
scene_stats.pipeline_render_time)))
|
||||
print(" - Peak memory used on device: {}" . format(
|
||||
util.humanReadableSize(stats.device_peak_memory)))
|
||||
util.humanReadableSize(scene_stats.device_peak_memory)))
|
||||
print(" - Memory used on device during rendering: {}" . format(
|
||||
util.humanReadableSize(stats.device_memory_usage)))
|
||||
util.humanReadableSize(scene_stats.device_memory_usage)))
|
||||
|
||||
|
||||
def _printFullJSONResult(ctx, results):
|
||||
|
@@ -288,8 +288,9 @@ class HistoryResultVisitor(ResultVisitor):
|
||||
continue
|
||||
scene_stats_history = stats_history[scene_name]
|
||||
data = []
|
||||
sorted_scene_stats_history = sorted(scene_stats_history,
|
||||
key=lambda k: k['timestamp'])
|
||||
sorted_scene_stats_history = sorted(
|
||||
scene_stats_history,
|
||||
key=lambda k: k['timestamp'])
|
||||
uniq_scene_stats_history = self.removeDuplicated(
|
||||
sorted_scene_stats_history)
|
||||
for scene_stats in uniq_scene_stats_history:
|
||||
@@ -313,6 +314,7 @@ class HistoryResultVisitor(ResultVisitor):
|
||||
with open(filename, "w") as f:
|
||||
f.write(code)
|
||||
|
||||
|
||||
def main():
|
||||
parser = configureArgumentParser()
|
||||
args = parser.parse_args()
|
||||
|
9
benchmark/third_party/cpu_cores/__init__.py
vendored
Normal file
9
benchmark/third_party/cpu_cores/__init__.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# This file is part of cpu_cores released under the MIT license.
|
||||
# See the LICENSE file for more information.
|
||||
|
||||
version_info = (0, 1, 3)
|
||||
__version__ = ".".join([str(x) for x in version_info])
|
||||
|
||||
from cpu_cores.common import CPUCoresCounter
|
||||
|
||||
__all__ = ['CPUCoresCounter']
|
43
benchmark/third_party/cpu_cores/common.py
vendored
Normal file
43
benchmark/third_party/cpu_cores/common.py
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# This file is part of cpu_cores released under the MIT license.
|
||||
# See the LICENSE file for more information.
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
class CPUCoresCounter(object):
|
||||
|
||||
platform = None
|
||||
_physical_cores_count = None
|
||||
_physical_processors_count = None
|
||||
|
||||
def _count(self, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
def factory(cls, force_platform=None):
|
||||
if force_platform is not None:
|
||||
cls.platform = force_platform
|
||||
else:
|
||||
cls.platform = sys.platform
|
||||
if cls.platform.startswith('darwin'):
|
||||
from cpu_cores.darwin import DarwinCPUCoresCounter
|
||||
return DarwinCPUCoresCounter()
|
||||
elif cls.platform.startswith('linux'):
|
||||
from cpu_cores.linux import LinuxCPUCoresCounter
|
||||
return LinuxCPUCoresCounter()
|
||||
else:
|
||||
raise NotImplementedError("unsupported platform type [%s]" %
|
||||
cls.platform)
|
||||
|
||||
def _check_counting_or_do_it(self):
|
||||
if self._physical_processors_count is None or \
|
||||
self._physical_cores_count is None:
|
||||
self._count()
|
||||
|
||||
def get_physical_cores_count(self):
|
||||
self._check_counting_or_do_it()
|
||||
return self._physical_cores_count
|
||||
|
||||
def get_physical_processors_count(self):
|
||||
self._check_counting_or_do_it()
|
||||
return self._physical_processors_count
|
35
benchmark/third_party/cpu_cores/darwin.py
vendored
Normal file
35
benchmark/third_party/cpu_cores/darwin.py
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# This file is part of cpu_cores released under the MIT license.
|
||||
# See the LICENSE file for more information.
|
||||
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
from cpu_cores.common import CPUCoresCounter
|
||||
|
||||
CPUINFO_COMMAND = "/usr/sbin/system_profiler" \
|
||||
" -detailLevel full SPHardwareDataType"
|
||||
|
||||
|
||||
class DarwinCPUCoresCounter(CPUCoresCounter):
|
||||
|
||||
def _count(self, command=None):
|
||||
if command is None:
|
||||
command = CPUINFO_COMMAND
|
||||
s = subprocess.Popen(shlex.split(command),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
if s:
|
||||
out, err = s.communicate()
|
||||
if len(err.strip()) > 0 or len(out.strip()) == 0:
|
||||
raise Exception('impossible to get the cpu cores count' +
|
||||
'(darwin) (error message = %s)' % err.strip())
|
||||
lines = out.split(b'\n')
|
||||
for line in lines:
|
||||
tmp = line.strip()
|
||||
if tmp.startswith(b'Total Number of Cores:'):
|
||||
self._physical_cores_count = int(tmp.split(b':')[1])
|
||||
if tmp.startswith(b'Number of Processors:'):
|
||||
self._physical_processors_count = int(tmp.split(b':')[1])
|
||||
if self._physical_processors_count is None or \
|
||||
self._physical_cores_count is None:
|
||||
raise Exception('impossible to get the cpu cores count (darwin)')
|
54
benchmark/third_party/cpu_cores/linux.py
vendored
Normal file
54
benchmark/third_party/cpu_cores/linux.py
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
# This file is part of cpu_cores released under the MIT license.
|
||||
# See the LICENSE file for more information.
|
||||
|
||||
from cpu_cores.common import CPUCoresCounter
|
||||
|
||||
CPUINFO_FILEPATH = "/proc/cpuinfo"
|
||||
|
||||
|
||||
def _core_hash(cpu_infos):
|
||||
if 'core id' not in cpu_infos and 'physical id' not in cpu_infos:
|
||||
return "%i" % cpu_infos['processor']
|
||||
if 'core id' in cpu_infos and 'physical id' not in cpu_infos:
|
||||
raise Exception("incorrect cpuinfo file :"
|
||||
" we have a core_id without physical_id")
|
||||
if 'core id' in cpu_infos:
|
||||
return "%i_%i" % (cpu_infos['physical id'], cpu_infos['core id'])
|
||||
else:
|
||||
return "%i" % cpu_infos['physical id']
|
||||
|
||||
|
||||
def _processor_hash(cpu_infos):
|
||||
if 'core id' not in cpu_infos and 'physical id' not in cpu_infos:
|
||||
return "%i" % cpu_infos['processor']
|
||||
if 'core id' in cpu_infos and 'physical id' not in cpu_infos:
|
||||
raise Exception("incorrect cpuinfo file :"
|
||||
" we have a core_id without physical_id")
|
||||
return "%i" % cpu_infos['physical id']
|
||||
|
||||
|
||||
class LinuxCPUCoresCounter(CPUCoresCounter):
|
||||
|
||||
def _count(self, cpuinfo_filepath=None):
|
||||
if cpuinfo_filepath is None:
|
||||
cpuinfo_filepath = CPUINFO_FILEPATH
|
||||
with open(cpuinfo_filepath, 'r') as f:
|
||||
# we read lines in reversed order to be sure to end with a
|
||||
# "processor:" line
|
||||
lines = reversed(f.readlines())
|
||||
cores = set()
|
||||
processors = set()
|
||||
cpu_infos = {}
|
||||
for line in lines:
|
||||
tmp = line.strip()
|
||||
for key in ('processor', 'physical id', 'core id'):
|
||||
if tmp.startswith(key):
|
||||
cpu_infos[key] = int(tmp.split(':')[1].strip())
|
||||
if key == 'processor':
|
||||
cores.add(_core_hash(cpu_infos))
|
||||
processors.add(_processor_hash(cpu_infos))
|
||||
cpu_infos = {}
|
||||
if len(cores) == 0 or len(processors) == 0:
|
||||
raise Exception("can't get the cpu cores count (linux)")
|
||||
self._physical_cores_count = len(cores)
|
||||
self._physical_processors_count = len(processors)
|
2
benchmark/third_party/dateutil/__init__.py
vendored
Normal file
2
benchmark/third_party/dateutil/__init__.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from ._version import VERSION as __version__
|
34
benchmark/third_party/dateutil/_common.py
vendored
Normal file
34
benchmark/third_party/dateutil/_common.py
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
"""
|
||||
Common code used in multiple modules.
|
||||
"""
|
||||
|
||||
|
||||
class weekday(object):
|
||||
__slots__ = ["weekday", "n"]
|
||||
|
||||
def __init__(self, weekday, n=None):
|
||||
self.weekday = weekday
|
||||
self.n = n
|
||||
|
||||
def __call__(self, n):
|
||||
if n == self.n:
|
||||
return self
|
||||
else:
|
||||
return self.__class__(self.weekday, n)
|
||||
|
||||
def __eq__(self, other):
|
||||
try:
|
||||
if self.weekday != other.weekday or self.n != other.n:
|
||||
return False
|
||||
except AttributeError:
|
||||
return False
|
||||
return True
|
||||
|
||||
__hash__ = None
|
||||
|
||||
def __repr__(self):
|
||||
s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday]
|
||||
if not self.n:
|
||||
return s
|
||||
else:
|
||||
return "%s(%+d)" % (s, self.n)
|
10
benchmark/third_party/dateutil/_version.py
vendored
Normal file
10
benchmark/third_party/dateutil/_version.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
Contains information about the dateutil version.
|
||||
"""
|
||||
|
||||
VERSION_MAJOR = 2
|
||||
VERSION_MINOR = 6
|
||||
VERSION_PATCH = 1
|
||||
|
||||
VERSION_TUPLE = (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)
|
||||
VERSION = '.'.join(map(str, VERSION_TUPLE))
|
89
benchmark/third_party/dateutil/easter.py
vendored
Normal file
89
benchmark/third_party/dateutil/easter.py
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This module offers a generic easter computing method for any given year, using
|
||||
Western, Orthodox or Julian algorithms.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"]
|
||||
|
||||
EASTER_JULIAN = 1
|
||||
EASTER_ORTHODOX = 2
|
||||
EASTER_WESTERN = 3
|
||||
|
||||
|
||||
def easter(year, method=EASTER_WESTERN):
|
||||
"""
|
||||
This method was ported from the work done by GM Arts,
|
||||
on top of the algorithm by Claus Tondering, which was
|
||||
based in part on the algorithm of Ouding (1940), as
|
||||
quoted in "Explanatory Supplement to the Astronomical
|
||||
Almanac", P. Kenneth Seidelmann, editor.
|
||||
|
||||
This algorithm implements three different easter
|
||||
calculation methods:
|
||||
|
||||
1 - Original calculation in Julian calendar, valid in
|
||||
dates after 326 AD
|
||||
2 - Original method, with date converted to Gregorian
|
||||
calendar, valid in years 1583 to 4099
|
||||
3 - Revised method, in Gregorian calendar, valid in
|
||||
years 1583 to 4099 as well
|
||||
|
||||
These methods are represented by the constants:
|
||||
|
||||
* ``EASTER_JULIAN = 1``
|
||||
* ``EASTER_ORTHODOX = 2``
|
||||
* ``EASTER_WESTERN = 3``
|
||||
|
||||
The default method is method 3.
|
||||
|
||||
More about the algorithm may be found at:
|
||||
|
||||
http://users.chariot.net.au/~gmarts/eastalg.htm
|
||||
|
||||
and
|
||||
|
||||
http://www.tondering.dk/claus/calendar.html
|
||||
|
||||
"""
|
||||
|
||||
if not (1 <= method <= 3):
|
||||
raise ValueError("invalid method")
|
||||
|
||||
# g - Golden year - 1
|
||||
# c - Century
|
||||
# h - (23 - Epact) mod 30
|
||||
# i - Number of days from March 21 to Paschal Full Moon
|
||||
# j - Weekday for PFM (0=Sunday, etc)
|
||||
# p - Number of days from March 21 to Sunday on or before PFM
|
||||
# (-6 to 28 methods 1 & 3, to 56 for method 2)
|
||||
# e - Extra days to add for method 2 (converting Julian
|
||||
# date to Gregorian date)
|
||||
|
||||
y = year
|
||||
g = y % 19
|
||||
e = 0
|
||||
if method < 3:
|
||||
# Old method
|
||||
i = (19*g + 15) % 30
|
||||
j = (y + y//4 + i) % 7
|
||||
if method == 2:
|
||||
# Extra dates to convert Julian to Gregorian date
|
||||
e = 10
|
||||
if y > 1600:
|
||||
e = e + y//100 - 16 - (y//100 - 16)//4
|
||||
else:
|
||||
# New method
|
||||
c = y//100
|
||||
h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30
|
||||
i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11))
|
||||
j = (y + y//4 + i + 2 - c + c//4) % 7
|
||||
|
||||
# p can be from -6 to 56 corresponding to dates 22 March to 23 May
|
||||
# (later dates apply to method 2, although 23 May never actually occurs)
|
||||
p = i - j + e
|
||||
d = 1 + (p + 27 + (p + 6)//40) % 31
|
||||
m = 3 + (p + 26)//30
|
||||
return datetime.date(int(y), int(m), int(d))
|
1374
benchmark/third_party/dateutil/parser.py
vendored
Normal file
1374
benchmark/third_party/dateutil/parser.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
549
benchmark/third_party/dateutil/relativedelta.py
vendored
Normal file
549
benchmark/third_party/dateutil/relativedelta.py
vendored
Normal file
@@ -0,0 +1,549 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
import calendar
|
||||
|
||||
import operator
|
||||
from math import copysign
|
||||
|
||||
from six import integer_types
|
||||
from warnings import warn
|
||||
|
||||
from ._common import weekday
|
||||
|
||||
MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7))
|
||||
|
||||
__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"]
|
||||
|
||||
|
||||
class relativedelta(object):
|
||||
"""
|
||||
The relativedelta type is based on the specification of the excellent
|
||||
work done by M.-A. Lemburg in his
|
||||
`mx.DateTime <http://www.egenix.com/files/python/mxDateTime.html>`_ extension.
|
||||
However, notice that this type does *NOT* implement the same algorithm as
|
||||
his work. Do *NOT* expect it to behave like mx.DateTime's counterpart.
|
||||
|
||||
There are two different ways to build a relativedelta instance. The
|
||||
first one is passing it two date/datetime classes::
|
||||
|
||||
relativedelta(datetime1, datetime2)
|
||||
|
||||
The second one is passing it any number of the following keyword arguments::
|
||||
|
||||
relativedelta(arg1=x,arg2=y,arg3=z...)
|
||||
|
||||
year, month, day, hour, minute, second, microsecond:
|
||||
Absolute information (argument is singular); adding or subtracting a
|
||||
relativedelta with absolute information does not perform an aritmetic
|
||||
operation, but rather REPLACES the corresponding value in the
|
||||
original datetime with the value(s) in relativedelta.
|
||||
|
||||
years, months, weeks, days, hours, minutes, seconds, microseconds:
|
||||
Relative information, may be negative (argument is plural); adding
|
||||
or subtracting a relativedelta with relative information performs
|
||||
the corresponding aritmetic operation on the original datetime value
|
||||
with the information in the relativedelta.
|
||||
|
||||
weekday:
|
||||
One of the weekday instances (MO, TU, etc). These instances may
|
||||
receive a parameter N, specifying the Nth weekday, which could
|
||||
be positive or negative (like MO(+1) or MO(-2). Not specifying
|
||||
it is the same as specifying +1. You can also use an integer,
|
||||
where 0=MO.
|
||||
|
||||
leapdays:
|
||||
Will add given days to the date found, if year is a leap
|
||||
year, and the date found is post 28 of february.
|
||||
|
||||
yearday, nlyearday:
|
||||
Set the yearday or the non-leap year day (jump leap days).
|
||||
These are converted to day/month/leapdays information.
|
||||
|
||||
Here is the behavior of operations with relativedelta:
|
||||
|
||||
1. Calculate the absolute year, using the 'year' argument, or the
|
||||
original datetime year, if the argument is not present.
|
||||
|
||||
2. Add the relative 'years' argument to the absolute year.
|
||||
|
||||
3. Do steps 1 and 2 for month/months.
|
||||
|
||||
4. Calculate the absolute day, using the 'day' argument, or the
|
||||
original datetime day, if the argument is not present. Then,
|
||||
subtract from the day until it fits in the year and month
|
||||
found after their operations.
|
||||
|
||||
5. Add the relative 'days' argument to the absolute day. Notice
|
||||
that the 'weeks' argument is multiplied by 7 and added to
|
||||
'days'.
|
||||
|
||||
6. Do steps 1 and 2 for hour/hours, minute/minutes, second/seconds,
|
||||
microsecond/microseconds.
|
||||
|
||||
7. If the 'weekday' argument is present, calculate the weekday,
|
||||
with the given (wday, nth) tuple. wday is the index of the
|
||||
weekday (0-6, 0=Mon), and nth is the number of weeks to add
|
||||
forward or backward, depending on its signal. Notice that if
|
||||
the calculated date is already Monday, for example, using
|
||||
(0, 1) or (0, -1) won't change the day.
|
||||
"""
|
||||
|
||||
def __init__(self, dt1=None, dt2=None,
|
||||
years=0, months=0, days=0, leapdays=0, weeks=0,
|
||||
hours=0, minutes=0, seconds=0, microseconds=0,
|
||||
year=None, month=None, day=None, weekday=None,
|
||||
yearday=None, nlyearday=None,
|
||||
hour=None, minute=None, second=None, microsecond=None):
|
||||
|
||||
# Check for non-integer values in integer-only quantities
|
||||
if any(x is not None and x != int(x) for x in (years, months)):
|
||||
raise ValueError("Non-integer years and months are "
|
||||
"ambiguous and not currently supported.")
|
||||
|
||||
if dt1 and dt2:
|
||||
# datetime is a subclass of date. So both must be date
|
||||
if not (isinstance(dt1, datetime.date) and
|
||||
isinstance(dt2, datetime.date)):
|
||||
raise TypeError("relativedelta only diffs datetime/date")
|
||||
|
||||
# We allow two dates, or two datetimes, so we coerce them to be
|
||||
# of the same type
|
||||
if (isinstance(dt1, datetime.datetime) !=
|
||||
isinstance(dt2, datetime.datetime)):
|
||||
if not isinstance(dt1, datetime.datetime):
|
||||
dt1 = datetime.datetime.fromordinal(dt1.toordinal())
|
||||
elif not isinstance(dt2, datetime.datetime):
|
||||
dt2 = datetime.datetime.fromordinal(dt2.toordinal())
|
||||
|
||||
self.years = 0
|
||||
self.months = 0
|
||||
self.days = 0
|
||||
self.leapdays = 0
|
||||
self.hours = 0
|
||||
self.minutes = 0
|
||||
self.seconds = 0
|
||||
self.microseconds = 0
|
||||
self.year = None
|
||||
self.month = None
|
||||
self.day = None
|
||||
self.weekday = None
|
||||
self.hour = None
|
||||
self.minute = None
|
||||
self.second = None
|
||||
self.microsecond = None
|
||||
self._has_time = 0
|
||||
|
||||
# Get year / month delta between the two
|
||||
months = (dt1.year - dt2.year) * 12 + (dt1.month - dt2.month)
|
||||
self._set_months(months)
|
||||
|
||||
# Remove the year/month delta so the timedelta is just well-defined
|
||||
# time units (seconds, days and microseconds)
|
||||
dtm = self.__radd__(dt2)
|
||||
|
||||
# If we've overshot our target, make an adjustment
|
||||
if dt1 < dt2:
|
||||
compare = operator.gt
|
||||
increment = 1
|
||||
else:
|
||||
compare = operator.lt
|
||||
increment = -1
|
||||
|
||||
while compare(dt1, dtm):
|
||||
months += increment
|
||||
self._set_months(months)
|
||||
dtm = self.__radd__(dt2)
|
||||
|
||||
# Get the timedelta between the "months-adjusted" date and dt1
|
||||
delta = dt1 - dtm
|
||||
self.seconds = delta.seconds + delta.days * 86400
|
||||
self.microseconds = delta.microseconds
|
||||
else:
|
||||
# Relative information
|
||||
self.years = years
|
||||
self.months = months
|
||||
self.days = days + weeks * 7
|
||||
self.leapdays = leapdays
|
||||
self.hours = hours
|
||||
self.minutes = minutes
|
||||
self.seconds = seconds
|
||||
self.microseconds = microseconds
|
||||
|
||||
# Absolute information
|
||||
self.year = year
|
||||
self.month = month
|
||||
self.day = day
|
||||
self.hour = hour
|
||||
self.minute = minute
|
||||
self.second = second
|
||||
self.microsecond = microsecond
|
||||
|
||||
if any(x is not None and int(x) != x
|
||||
for x in (year, month, day, hour,
|
||||
minute, second, microsecond)):
|
||||
# For now we'll deprecate floats - later it'll be an error.
|
||||
warn("Non-integer value passed as absolute information. " +
|
||||
"This is not a well-defined condition and will raise " +
|
||||
"errors in future versions.", DeprecationWarning)
|
||||
|
||||
if isinstance(weekday, integer_types):
|
||||
self.weekday = weekdays[weekday]
|
||||
else:
|
||||
self.weekday = weekday
|
||||
|
||||
yday = 0
|
||||
if nlyearday:
|
||||
yday = nlyearday
|
||||
elif yearday:
|
||||
yday = yearday
|
||||
if yearday > 59:
|
||||
self.leapdays = -1
|
||||
if yday:
|
||||
ydayidx = [31, 59, 90, 120, 151, 181, 212,
|
||||
243, 273, 304, 334, 366]
|
||||
for idx, ydays in enumerate(ydayidx):
|
||||
if yday <= ydays:
|
||||
self.month = idx+1
|
||||
if idx == 0:
|
||||
self.day = yday
|
||||
else:
|
||||
self.day = yday-ydayidx[idx-1]
|
||||
break
|
||||
else:
|
||||
raise ValueError("invalid year day (%d)" % yday)
|
||||
|
||||
self._fix()
|
||||
|
||||
def _fix(self):
|
||||
if abs(self.microseconds) > 999999:
|
||||
s = _sign(self.microseconds)
|
||||
div, mod = divmod(self.microseconds * s, 1000000)
|
||||
self.microseconds = mod * s
|
||||
self.seconds += div * s
|
||||
if abs(self.seconds) > 59:
|
||||
s = _sign(self.seconds)
|
||||
div, mod = divmod(self.seconds * s, 60)
|
||||
self.seconds = mod * s
|
||||
self.minutes += div * s
|
||||
if abs(self.minutes) > 59:
|
||||
s = _sign(self.minutes)
|
||||
div, mod = divmod(self.minutes * s, 60)
|
||||
self.minutes = mod * s
|
||||
self.hours += div * s
|
||||
if abs(self.hours) > 23:
|
||||
s = _sign(self.hours)
|
||||
div, mod = divmod(self.hours * s, 24)
|
||||
self.hours = mod * s
|
||||
self.days += div * s
|
||||
if abs(self.months) > 11:
|
||||
s = _sign(self.months)
|
||||
div, mod = divmod(self.months * s, 12)
|
||||
self.months = mod * s
|
||||
self.years += div * s
|
||||
if (self.hours or self.minutes or self.seconds or self.microseconds
|
||||
or self.hour is not None or self.minute is not None or
|
||||
self.second is not None or self.microsecond is not None):
|
||||
self._has_time = 1
|
||||
else:
|
||||
self._has_time = 0
|
||||
|
||||
@property
|
||||
def weeks(self):
|
||||
return self.days // 7
|
||||
|
||||
@weeks.setter
|
||||
def weeks(self, value):
|
||||
self.days = self.days - (self.weeks * 7) + value * 7
|
||||
|
||||
def _set_months(self, months):
|
||||
self.months = months
|
||||
if abs(self.months) > 11:
|
||||
s = _sign(self.months)
|
||||
div, mod = divmod(self.months * s, 12)
|
||||
self.months = mod * s
|
||||
self.years = div * s
|
||||
else:
|
||||
self.years = 0
|
||||
|
||||
def normalized(self):
|
||||
"""
|
||||
Return a version of this object represented entirely using integer
|
||||
values for the relative attributes.
|
||||
|
||||
>>> relativedelta(days=1.5, hours=2).normalized()
|
||||
relativedelta(days=1, hours=14)
|
||||
|
||||
:return:
|
||||
Returns a :class:`dateutil.relativedelta.relativedelta` object.
|
||||
"""
|
||||
# Cascade remainders down (rounding each to roughly nearest microsecond)
|
||||
days = int(self.days)
|
||||
|
||||
hours_f = round(self.hours + 24 * (self.days - days), 11)
|
||||
hours = int(hours_f)
|
||||
|
||||
minutes_f = round(self.minutes + 60 * (hours_f - hours), 10)
|
||||
minutes = int(minutes_f)
|
||||
|
||||
seconds_f = round(self.seconds + 60 * (minutes_f - minutes), 8)
|
||||
seconds = int(seconds_f)
|
||||
|
||||
microseconds = round(self.microseconds + 1e6 * (seconds_f - seconds))
|
||||
|
||||
# Constructor carries overflow back up with call to _fix()
|
||||
return self.__class__(years=self.years, months=self.months,
|
||||
days=days, hours=hours, minutes=minutes,
|
||||
seconds=seconds, microseconds=microseconds,
|
||||
leapdays=self.leapdays, year=self.year,
|
||||
month=self.month, day=self.day,
|
||||
weekday=self.weekday, hour=self.hour,
|
||||
minute=self.minute, second=self.second,
|
||||
microsecond=self.microsecond)
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, relativedelta):
|
||||
return self.__class__(years=other.years + self.years,
|
||||
months=other.months + self.months,
|
||||
days=other.days + self.days,
|
||||
hours=other.hours + self.hours,
|
||||
minutes=other.minutes + self.minutes,
|
||||
seconds=other.seconds + self.seconds,
|
||||
microseconds=(other.microseconds +
|
||||
self.microseconds),
|
||||
leapdays=other.leapdays or self.leapdays,
|
||||
year=(other.year if other.year is not None
|
||||
else self.year),
|
||||
month=(other.month if other.month is not None
|
||||
else self.month),
|
||||
day=(other.day if other.day is not None
|
||||
else self.day),
|
||||
weekday=(other.weekday if other.weekday is not None
|
||||
else self.weekday),
|
||||
hour=(other.hour if other.hour is not None
|
||||
else self.hour),
|
||||
minute=(other.minute if other.minute is not None
|
||||
else self.minute),
|
||||
second=(other.second if other.second is not None
|
||||
else self.second),
|
||||
microsecond=(other.microsecond if other.microsecond
|
||||
is not None else
|
||||
self.microsecond))
|
||||
if isinstance(other, datetime.timedelta):
|
||||
return self.__class__(years=self.years,
|
||||
months=self.months,
|
||||
days=self.days + other.days,
|
||||
hours=self.hours,
|
||||
minutes=self.minutes,
|
||||
seconds=self.seconds + other.seconds,
|
||||
microseconds=self.microseconds + other.microseconds,
|
||||
leapdays=self.leapdays,
|
||||
year=self.year,
|
||||
month=self.month,
|
||||
day=self.day,
|
||||
weekday=self.weekday,
|
||||
hour=self.hour,
|
||||
minute=self.minute,
|
||||
second=self.second,
|
||||
microsecond=self.microsecond)
|
||||
if not isinstance(other, datetime.date):
|
||||
return NotImplemented
|
||||
elif self._has_time and not isinstance(other, datetime.datetime):
|
||||
other = datetime.datetime.fromordinal(other.toordinal())
|
||||
year = (self.year or other.year)+self.years
|
||||
month = self.month or other.month
|
||||
if self.months:
|
||||
assert 1 <= abs(self.months) <= 12
|
||||
month += self.months
|
||||
if month > 12:
|
||||
year += 1
|
||||
month -= 12
|
||||
elif month < 1:
|
||||
year -= 1
|
||||
month += 12
|
||||
day = min(calendar.monthrange(year, month)[1],
|
||||
self.day or other.day)
|
||||
repl = {"year": year, "month": month, "day": day}
|
||||
for attr in ["hour", "minute", "second", "microsecond"]:
|
||||
value = getattr(self, attr)
|
||||
if value is not None:
|
||||
repl[attr] = value
|
||||
days = self.days
|
||||
if self.leapdays and month > 2 and calendar.isleap(year):
|
||||
days += self.leapdays
|
||||
ret = (other.replace(**repl)
|
||||
+ datetime.timedelta(days=days,
|
||||
hours=self.hours,
|
||||
minutes=self.minutes,
|
||||
seconds=self.seconds,
|
||||
microseconds=self.microseconds))
|
||||
if self.weekday:
|
||||
weekday, nth = self.weekday.weekday, self.weekday.n or 1
|
||||
jumpdays = (abs(nth) - 1) * 7
|
||||
if nth > 0:
|
||||
jumpdays += (7 - ret.weekday() + weekday) % 7
|
||||
else:
|
||||
jumpdays += (ret.weekday() - weekday) % 7
|
||||
jumpdays *= -1
|
||||
ret += datetime.timedelta(days=jumpdays)
|
||||
return ret
|
||||
|
||||
def __radd__(self, other):
|
||||
return self.__add__(other)
|
||||
|
||||
def __rsub__(self, other):
|
||||
return self.__neg__().__radd__(other)
|
||||
|
||||
def __sub__(self, other):
|
||||
if not isinstance(other, relativedelta):
|
||||
return NotImplemented # In case the other object defines __rsub__
|
||||
return self.__class__(years=self.years - other.years,
|
||||
months=self.months - other.months,
|
||||
days=self.days - other.days,
|
||||
hours=self.hours - other.hours,
|
||||
minutes=self.minutes - other.minutes,
|
||||
seconds=self.seconds - other.seconds,
|
||||
microseconds=self.microseconds - other.microseconds,
|
||||
leapdays=self.leapdays or other.leapdays,
|
||||
year=(self.year if self.year is not None
|
||||
else other.year),
|
||||
month=(self.month if self.month is not None else
|
||||
other.month),
|
||||
day=(self.day if self.day is not None else
|
||||
other.day),
|
||||
weekday=(self.weekday if self.weekday is not None else
|
||||
other.weekday),
|
||||
hour=(self.hour if self.hour is not None else
|
||||
other.hour),
|
||||
minute=(self.minute if self.minute is not None else
|
||||
other.minute),
|
||||
second=(self.second if self.second is not None else
|
||||
other.second),
|
||||
microsecond=(self.microsecond if self.microsecond
|
||||
is not None else
|
||||
other.microsecond))
|
||||
|
||||
def __neg__(self):
|
||||
return self.__class__(years=-self.years,
|
||||
months=-self.months,
|
||||
days=-self.days,
|
||||
hours=-self.hours,
|
||||
minutes=-self.minutes,
|
||||
seconds=-self.seconds,
|
||||
microseconds=-self.microseconds,
|
||||
leapdays=self.leapdays,
|
||||
year=self.year,
|
||||
month=self.month,
|
||||
day=self.day,
|
||||
weekday=self.weekday,
|
||||
hour=self.hour,
|
||||
minute=self.minute,
|
||||
second=self.second,
|
||||
microsecond=self.microsecond)
|
||||
|
||||
def __bool__(self):
|
||||
return not (not self.years and
|
||||
not self.months and
|
||||
not self.days and
|
||||
not self.hours and
|
||||
not self.minutes and
|
||||
not self.seconds and
|
||||
not self.microseconds and
|
||||
not self.leapdays and
|
||||
self.year is None and
|
||||
self.month is None and
|
||||
self.day is None and
|
||||
self.weekday is None and
|
||||
self.hour is None and
|
||||
self.minute is None and
|
||||
self.second is None and
|
||||
self.microsecond is None)
|
||||
# Compatibility with Python 2.x
|
||||
__nonzero__ = __bool__
|
||||
|
||||
def __mul__(self, other):
|
||||
try:
|
||||
f = float(other)
|
||||
except TypeError:
|
||||
return NotImplemented
|
||||
|
||||
return self.__class__(years=int(self.years * f),
|
||||
months=int(self.months * f),
|
||||
days=int(self.days * f),
|
||||
hours=int(self.hours * f),
|
||||
minutes=int(self.minutes * f),
|
||||
seconds=int(self.seconds * f),
|
||||
microseconds=int(self.microseconds * f),
|
||||
leapdays=self.leapdays,
|
||||
year=self.year,
|
||||
month=self.month,
|
||||
day=self.day,
|
||||
weekday=self.weekday,
|
||||
hour=self.hour,
|
||||
minute=self.minute,
|
||||
second=self.second,
|
||||
microsecond=self.microsecond)
|
||||
|
||||
__rmul__ = __mul__
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, relativedelta):
|
||||
return NotImplemented
|
||||
if self.weekday or other.weekday:
|
||||
if not self.weekday or not other.weekday:
|
||||
return False
|
||||
if self.weekday.weekday != other.weekday.weekday:
|
||||
return False
|
||||
n1, n2 = self.weekday.n, other.weekday.n
|
||||
if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)):
|
||||
return False
|
||||
return (self.years == other.years and
|
||||
self.months == other.months and
|
||||
self.days == other.days and
|
||||
self.hours == other.hours and
|
||||
self.minutes == other.minutes and
|
||||
self.seconds == other.seconds and
|
||||
self.microseconds == other.microseconds and
|
||||
self.leapdays == other.leapdays and
|
||||
self.year == other.year and
|
||||
self.month == other.month and
|
||||
self.day == other.day and
|
||||
self.hour == other.hour and
|
||||
self.minute == other.minute and
|
||||
self.second == other.second and
|
||||
self.microsecond == other.microsecond)
|
||||
|
||||
__hash__ = None
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __div__(self, other):
|
||||
try:
|
||||
reciprocal = 1 / float(other)
|
||||
except TypeError:
|
||||
return NotImplemented
|
||||
|
||||
return self.__mul__(reciprocal)
|
||||
|
||||
__truediv__ = __div__
|
||||
|
||||
def __repr__(self):
|
||||
l = []
|
||||
for attr in ["years", "months", "days", "leapdays",
|
||||
"hours", "minutes", "seconds", "microseconds"]:
|
||||
value = getattr(self, attr)
|
||||
if value:
|
||||
l.append("{attr}={value:+g}".format(attr=attr, value=value))
|
||||
for attr in ["year", "month", "day", "weekday",
|
||||
"hour", "minute", "second", "microsecond"]:
|
||||
value = getattr(self, attr)
|
||||
if value is not None:
|
||||
l.append("{attr}={value}".format(attr=attr, value=repr(value)))
|
||||
return "{classname}({attrs})".format(classname=self.__class__.__name__,
|
||||
attrs=", ".join(l))
|
||||
|
||||
|
||||
def _sign(x):
|
||||
return int(copysign(1, x))
|
||||
|
||||
# vim:ts=4:sw=4:et
|
1610
benchmark/third_party/dateutil/rrule.py
vendored
Normal file
1610
benchmark/third_party/dateutil/rrule.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
0
benchmark/third_party/dateutil/test/__init__.py
vendored
Normal file
0
benchmark/third_party/dateutil/test/__init__.py
vendored
Normal file
292
benchmark/third_party/dateutil/test/_common.py
vendored
Normal file
292
benchmark/third_party/dateutil/test/_common.py
vendored
Normal file
@@ -0,0 +1,292 @@
|
||||
from __future__ import unicode_literals
|
||||
try:
|
||||
import unittest2 as unittest
|
||||
except ImportError:
|
||||
import unittest
|
||||
|
||||
import os
|
||||
import datetime
|
||||
import time
|
||||
import subprocess
|
||||
import warnings
|
||||
import tempfile
|
||||
import pickle
|
||||
|
||||
|
||||
class WarningTestMixin(object):
|
||||
# Based on https://stackoverflow.com/a/12935176/467366
|
||||
class _AssertWarnsContext(warnings.catch_warnings):
|
||||
def __init__(self, expected_warnings, parent, **kwargs):
|
||||
super(WarningTestMixin._AssertWarnsContext, self).__init__(**kwargs)
|
||||
|
||||
self.parent = parent
|
||||
try:
|
||||
self.expected_warnings = list(expected_warnings)
|
||||
except TypeError:
|
||||
self.expected_warnings = [expected_warnings]
|
||||
|
||||
self._warning_log = []
|
||||
|
||||
def __enter__(self, *args, **kwargs):
|
||||
rv = super(WarningTestMixin._AssertWarnsContext, self).__enter__(*args, **kwargs)
|
||||
|
||||
if self._showwarning is not self._module.showwarning:
|
||||
super_showwarning = self._module.showwarning
|
||||
else:
|
||||
super_showwarning = None
|
||||
|
||||
def showwarning(*args, **kwargs):
|
||||
if super_showwarning is not None:
|
||||
super_showwarning(*args, **kwargs)
|
||||
|
||||
self._warning_log.append(warnings.WarningMessage(*args, **kwargs))
|
||||
|
||||
self._module.showwarning = showwarning
|
||||
return rv
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
super(WarningTestMixin._AssertWarnsContext, self).__exit__(self, *args, **kwargs)
|
||||
|
||||
self.parent.assertTrue(any(issubclass(item.category, warning)
|
||||
for warning in self.expected_warnings
|
||||
for item in self._warning_log))
|
||||
|
||||
def assertWarns(self, warning, callable=None, *args, **kwargs):
|
||||
warnings.simplefilter('always')
|
||||
context = self.__class__._AssertWarnsContext(warning, self)
|
||||
if callable is None:
|
||||
return context
|
||||
else:
|
||||
with context:
|
||||
callable(*args, **kwargs)
|
||||
|
||||
|
||||
class PicklableMixin(object):
|
||||
def _get_nobj_bytes(self, obj, dump_kwargs, load_kwargs):
|
||||
"""
|
||||
Pickle and unpickle an object using ``pickle.dumps`` / ``pickle.loads``
|
||||
"""
|
||||
pkl = pickle.dumps(obj, **dump_kwargs)
|
||||
return pickle.loads(pkl, **load_kwargs)
|
||||
|
||||
def _get_nobj_file(self, obj, dump_kwargs, load_kwargs):
|
||||
"""
|
||||
Pickle and unpickle an object using ``pickle.dump`` / ``pickle.load`` on
|
||||
a temporary file.
|
||||
"""
|
||||
with tempfile.TemporaryFile('w+b') as pkl:
|
||||
pickle.dump(obj, pkl, **dump_kwargs)
|
||||
pkl.seek(0) # Reset the file to the beginning to read it
|
||||
nobj = pickle.load(pkl, **load_kwargs)
|
||||
|
||||
return nobj
|
||||
|
||||
def assertPicklable(self, obj, asfile=False,
|
||||
dump_kwargs=None, load_kwargs=None):
|
||||
"""
|
||||
Assert that an object can be pickled and unpickled. This assertion
|
||||
assumes that the desired behavior is that the unpickled object compares
|
||||
equal to the original object, but is not the same object.
|
||||
"""
|
||||
get_nobj = self._get_nobj_file if asfile else self._get_nobj_bytes
|
||||
dump_kwargs = dump_kwargs or {}
|
||||
load_kwargs = load_kwargs or {}
|
||||
|
||||
nobj = get_nobj(obj, dump_kwargs, load_kwargs)
|
||||
self.assertIsNot(obj, nobj)
|
||||
self.assertEqual(obj, nobj)
|
||||
|
||||
|
||||
class TZContextBase(object):
|
||||
"""
|
||||
Base class for a context manager which allows changing of time zones.
|
||||
|
||||
Subclasses may define a guard variable to either block or or allow time
|
||||
zone changes by redefining ``_guard_var_name`` and ``_guard_allows_change``.
|
||||
The default is that the guard variable must be affirmatively set.
|
||||
|
||||
Subclasses must define ``get_current_tz`` and ``set_current_tz``.
|
||||
"""
|
||||
_guard_var_name = "DATEUTIL_MAY_CHANGE_TZ"
|
||||
_guard_allows_change = True
|
||||
|
||||
def __init__(self, tzval):
|
||||
self.tzval = tzval
|
||||
self._old_tz = None
|
||||
|
||||
@classmethod
|
||||
def tz_change_allowed(cls):
|
||||
"""
|
||||
Class method used to query whether or not this class allows time zone
|
||||
changes.
|
||||
"""
|
||||
guard = bool(os.environ.get(cls._guard_var_name, False))
|
||||
|
||||
# _guard_allows_change gives the "default" behavior - if True, the
|
||||
# guard is overcoming a block. If false, the guard is causing a block.
|
||||
# Whether tz_change is allowed is therefore the XNOR of the two.
|
||||
return guard == cls._guard_allows_change
|
||||
|
||||
@classmethod
|
||||
def tz_change_disallowed_message(cls):
|
||||
""" Generate instructions on how to allow tz changes """
|
||||
msg = ('Changing time zone not allowed. Set {envar} to {gval} '
|
||||
'if you would like to allow this behavior')
|
||||
|
||||
return msg.format(envar=cls._guard_var_name,
|
||||
gval=cls._guard_allows_change)
|
||||
|
||||
def __enter__(self):
|
||||
if not self.tz_change_allowed():
|
||||
raise ValueError(self.tz_change_disallowed_message())
|
||||
|
||||
self._old_tz = self.get_current_tz()
|
||||
self.set_current_tz(self.tzval)
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
if self._old_tz is not None:
|
||||
self.set_current_tz(self._old_tz)
|
||||
|
||||
self._old_tz = None
|
||||
|
||||
def get_current_tz(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def set_current_tz(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class TZEnvContext(TZContextBase):
|
||||
"""
|
||||
Context manager that temporarily sets the `TZ` variable (for use on
|
||||
*nix-like systems). Because the effect is local to the shell anyway, this
|
||||
will apply *unless* a guard is set.
|
||||
|
||||
If you do not want the TZ environment variable set, you may set the
|
||||
``DATEUTIL_MAY_NOT_CHANGE_TZ_VAR`` variable to a truthy value.
|
||||
"""
|
||||
_guard_var_name = "DATEUTIL_MAY_NOT_CHANGE_TZ_VAR"
|
||||
_guard_allows_change = False
|
||||
|
||||
def get_current_tz(self):
|
||||
return os.environ.get('TZ', UnsetTz)
|
||||
|
||||
def set_current_tz(self, tzval):
|
||||
if tzval is UnsetTz and 'TZ' in os.environ:
|
||||
del os.environ['TZ']
|
||||
else:
|
||||
os.environ['TZ'] = tzval
|
||||
|
||||
time.tzset()
|
||||
|
||||
|
||||
class TZWinContext(TZContextBase):
|
||||
"""
|
||||
Context manager for changing local time zone on Windows.
|
||||
|
||||
Because the effect of this is system-wide and global, it may have
|
||||
unintended side effect. Set the ``DATEUTIL_MAY_CHANGE_TZ`` environment
|
||||
variable to a truthy value before using this context manager.
|
||||
"""
|
||||
def get_current_tz(self):
|
||||
p = subprocess.Popen(['tzutil', '/g'], stdout=subprocess.PIPE)
|
||||
|
||||
ctzname, err = p.communicate()
|
||||
ctzname = ctzname.decode() # Popen returns
|
||||
|
||||
if p.returncode:
|
||||
raise OSError('Failed to get current time zone: ' + err)
|
||||
|
||||
return ctzname
|
||||
|
||||
def set_current_tz(self, tzname):
|
||||
p = subprocess.Popen('tzutil /s "' + tzname + '"')
|
||||
|
||||
out, err = p.communicate()
|
||||
|
||||
if p.returncode:
|
||||
raise OSError('Failed to set current time zone: ' +
|
||||
(err or 'Unknown error.'))
|
||||
|
||||
|
||||
###
|
||||
# Compatibility functions
|
||||
|
||||
def _total_seconds(td):
|
||||
# Python 2.6 doesn't have a total_seconds() method on timedelta objects
|
||||
return ((td.seconds + td.days * 86400) * 1000000 +
|
||||
td.microseconds) // 1000000
|
||||
|
||||
|
||||
total_seconds = getattr(datetime.timedelta, 'total_seconds', _total_seconds)
|
||||
|
||||
|
||||
###
|
||||
# Utility classes
|
||||
class NotAValueClass(object):
|
||||
"""
|
||||
A class analogous to NaN that has operations defined for any type.
|
||||
"""
|
||||
def _op(self, other):
|
||||
return self # Operation with NotAValue returns NotAValue
|
||||
|
||||
def _cmp(self, other):
|
||||
return False
|
||||
|
||||
__add__ = __radd__ = _op
|
||||
__sub__ = __rsub__ = _op
|
||||
__mul__ = __rmul__ = _op
|
||||
__div__ = __rdiv__ = _op
|
||||
__truediv__ = __rtruediv__ = _op
|
||||
__floordiv__ = __rfloordiv__ = _op
|
||||
|
||||
__lt__ = __rlt__ = _op
|
||||
__gt__ = __rgt__ = _op
|
||||
__eq__ = __req__ = _op
|
||||
__le__ = __rle__ = _op
|
||||
__ge__ = __rge__ = _op
|
||||
|
||||
|
||||
NotAValue = NotAValueClass()
|
||||
|
||||
|
||||
class ComparesEqualClass(object):
|
||||
"""
|
||||
A class that is always equal to whatever you compare it to.
|
||||
"""
|
||||
|
||||
def __eq__(self, other):
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
return False
|
||||
|
||||
def __le__(self, other):
|
||||
return True
|
||||
|
||||
def __ge__(self, other):
|
||||
return True
|
||||
|
||||
def __lt__(self, other):
|
||||
return False
|
||||
|
||||
def __gt__(self, other):
|
||||
return False
|
||||
|
||||
__req__ = __eq__
|
||||
__rne__ = __ne__
|
||||
__rle__ = __le__
|
||||
__rge__ = __ge__
|
||||
__rlt__ = __lt__
|
||||
__rgt__ = __gt__
|
||||
|
||||
|
||||
ComparesEqual = ComparesEqualClass()
|
||||
|
||||
|
||||
class UnsetTzClass(object):
|
||||
""" Sentinel class for unset time zone variable """
|
||||
pass
|
||||
|
||||
|
||||
UnsetTz = UnsetTzClass()
|
99
benchmark/third_party/dateutil/test/test_easter.py
vendored
Normal file
99
benchmark/third_party/dateutil/test/test_easter.py
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
from dateutil.easter import easter
|
||||
from dateutil.easter import EASTER_WESTERN, EASTER_ORTHODOX, EASTER_JULIAN
|
||||
|
||||
from datetime import date
|
||||
|
||||
try:
|
||||
import unittest2 as unittest
|
||||
except ImportError:
|
||||
import unittest
|
||||
|
||||
# List of easters between 1990 and 2050
|
||||
western_easter_dates = [
|
||||
date(1990, 4, 15), date(1991, 3, 31), date(1992, 4, 19), date(1993, 4, 11),
|
||||
date(1994, 4, 3), date(1995, 4, 16), date(1996, 4, 7), date(1997, 3, 30),
|
||||
date(1998, 4, 12), date(1999, 4, 4),
|
||||
|
||||
date(2000, 4, 23), date(2001, 4, 15), date(2002, 3, 31), date(2003, 4, 20),
|
||||
date(2004, 4, 11), date(2005, 3, 27), date(2006, 4, 16), date(2007, 4, 8),
|
||||
date(2008, 3, 23), date(2009, 4, 12),
|
||||
|
||||
date(2010, 4, 4), date(2011, 4, 24), date(2012, 4, 8), date(2013, 3, 31),
|
||||
date(2014, 4, 20), date(2015, 4, 5), date(2016, 3, 27), date(2017, 4, 16),
|
||||
date(2018, 4, 1), date(2019, 4, 21),
|
||||
|
||||
date(2020, 4, 12), date(2021, 4, 4), date(2022, 4, 17), date(2023, 4, 9),
|
||||
date(2024, 3, 31), date(2025, 4, 20), date(2026, 4, 5), date(2027, 3, 28),
|
||||
date(2028, 4, 16), date(2029, 4, 1),
|
||||
|
||||
date(2030, 4, 21), date(2031, 4, 13), date(2032, 3, 28), date(2033, 4, 17),
|
||||
date(2034, 4, 9), date(2035, 3, 25), date(2036, 4, 13), date(2037, 4, 5),
|
||||
date(2038, 4, 25), date(2039, 4, 10),
|
||||
|
||||
date(2040, 4, 1), date(2041, 4, 21), date(2042, 4, 6), date(2043, 3, 29),
|
||||
date(2044, 4, 17), date(2045, 4, 9), date(2046, 3, 25), date(2047, 4, 14),
|
||||
date(2048, 4, 5), date(2049, 4, 18), date(2050, 4, 10)
|
||||
]
|
||||
|
||||
orthodox_easter_dates = [
|
||||
date(1990, 4, 15), date(1991, 4, 7), date(1992, 4, 26), date(1993, 4, 18),
|
||||
date(1994, 5, 1), date(1995, 4, 23), date(1996, 4, 14), date(1997, 4, 27),
|
||||
date(1998, 4, 19), date(1999, 4, 11),
|
||||
|
||||
date(2000, 4, 30), date(2001, 4, 15), date(2002, 5, 5), date(2003, 4, 27),
|
||||
date(2004, 4, 11), date(2005, 5, 1), date(2006, 4, 23), date(2007, 4, 8),
|
||||
date(2008, 4, 27), date(2009, 4, 19),
|
||||
|
||||
date(2010, 4, 4), date(2011, 4, 24), date(2012, 4, 15), date(2013, 5, 5),
|
||||
date(2014, 4, 20), date(2015, 4, 12), date(2016, 5, 1), date(2017, 4, 16),
|
||||
date(2018, 4, 8), date(2019, 4, 28),
|
||||
|
||||
date(2020, 4, 19), date(2021, 5, 2), date(2022, 4, 24), date(2023, 4, 16),
|
||||
date(2024, 5, 5), date(2025, 4, 20), date(2026, 4, 12), date(2027, 5, 2),
|
||||
date(2028, 4, 16), date(2029, 4, 8),
|
||||
|
||||
date(2030, 4, 28), date(2031, 4, 13), date(2032, 5, 2), date(2033, 4, 24),
|
||||
date(2034, 4, 9), date(2035, 4, 29), date(2036, 4, 20), date(2037, 4, 5),
|
||||
date(2038, 4, 25), date(2039, 4, 17),
|
||||
|
||||
date(2040, 5, 6), date(2041, 4, 21), date(2042, 4, 13), date(2043, 5, 3),
|
||||
date(2044, 4, 24), date(2045, 4, 9), date(2046, 4, 29), date(2047, 4, 21),
|
||||
date(2048, 4, 5), date(2049, 4, 25), date(2050, 4, 17)
|
||||
]
|
||||
|
||||
# A random smattering of Julian dates.
|
||||
# Pulled values from http://www.kevinlaughery.com/east4099.html
|
||||
julian_easter_dates = [
|
||||
date( 326, 4, 3), date( 375, 4, 5), date( 492, 4, 5), date( 552, 3, 31),
|
||||
date( 562, 4, 9), date( 569, 4, 21), date( 597, 4, 14), date( 621, 4, 19),
|
||||
date( 636, 3, 31), date( 655, 3, 29), date( 700, 4, 11), date( 725, 4, 8),
|
||||
date( 750, 3, 29), date( 782, 4, 7), date( 835, 4, 18), date( 849, 4, 14),
|
||||
date( 867, 3, 30), date( 890, 4, 12), date( 922, 4, 21), date( 934, 4, 6),
|
||||
date(1049, 3, 26), date(1058, 4, 19), date(1113, 4, 6), date(1119, 3, 30),
|
||||
date(1242, 4, 20), date(1255, 3, 28), date(1257, 4, 8), date(1258, 3, 24),
|
||||
date(1261, 4, 24), date(1278, 4, 17), date(1333, 4, 4), date(1351, 4, 17),
|
||||
date(1371, 4, 6), date(1391, 3, 26), date(1402, 3, 26), date(1412, 4, 3),
|
||||
date(1439, 4, 5), date(1445, 3, 28), date(1531, 4, 9), date(1555, 4, 14)
|
||||
]
|
||||
|
||||
|
||||
class EasterTest(unittest.TestCase):
|
||||
def testEasterWestern(self):
|
||||
for easter_date in western_easter_dates:
|
||||
self.assertEqual(easter_date,
|
||||
easter(easter_date.year, EASTER_WESTERN))
|
||||
|
||||
def testEasterOrthodox(self):
|
||||
for easter_date in orthodox_easter_dates:
|
||||
self.assertEqual(easter_date,
|
||||
easter(easter_date.year, EASTER_ORTHODOX))
|
||||
|
||||
def testEasterJulian(self):
|
||||
for easter_date in julian_easter_dates:
|
||||
self.assertEqual(easter_date,
|
||||
easter(easter_date.year, EASTER_JULIAN))
|
||||
|
||||
def testEasterBadMethod(self):
|
||||
# Invalid methods raise ValueError
|
||||
with self.assertRaises(ValueError):
|
||||
easter(1975, 4)
|
166
benchmark/third_party/dateutil/test/test_imports.py
vendored
Normal file
166
benchmark/third_party/dateutil/test/test_imports.py
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
import sys
|
||||
|
||||
try:
|
||||
import unittest2 as unittest
|
||||
except ImportError:
|
||||
import unittest
|
||||
|
||||
class ImportVersionTest(unittest.TestCase):
|
||||
""" Test that dateutil.__version__ can be imported"""
|
||||
|
||||
def testImportVersionStr(self):
|
||||
from dateutil import __version__
|
||||
|
||||
def testImportRoot(self):
|
||||
import dateutil
|
||||
|
||||
self.assertTrue(hasattr(dateutil, '__version__'))
|
||||
|
||||
|
||||
class ImportEasterTest(unittest.TestCase):
|
||||
""" Test that dateutil.easter-related imports work properly """
|
||||
|
||||
def testEasterDirect(self):
|
||||
import dateutil.easter
|
||||
|
||||
def testEasterFrom(self):
|
||||
from dateutil import easter
|
||||
|
||||
def testEasterStar(self):
|
||||
from dateutil.easter import easter
|
||||
|
||||
|
||||
class ImportParserTest(unittest.TestCase):
|
||||
""" Test that dateutil.parser-related imports work properly """
|
||||
def testParserDirect(self):
|
||||
import dateutil.parser
|
||||
|
||||
def testParserFrom(self):
|
||||
from dateutil import parser
|
||||
|
||||
def testParserAll(self):
|
||||
# All interface
|
||||
from dateutil.parser import parse
|
||||
from dateutil.parser import parserinfo
|
||||
|
||||
# Other public classes
|
||||
from dateutil.parser import parser
|
||||
|
||||
for var in (parse, parserinfo, parser):
|
||||
self.assertIsNot(var, None)
|
||||
|
||||
|
||||
class ImportRelativeDeltaTest(unittest.TestCase):
|
||||
""" Test that dateutil.relativedelta-related imports work properly """
|
||||
def testRelativeDeltaDirect(self):
|
||||
import dateutil.relativedelta
|
||||
|
||||
def testRelativeDeltaFrom(self):
|
||||
from dateutil import relativedelta
|
||||
|
||||
def testRelativeDeltaAll(self):
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from dateutil.relativedelta import MO, TU, WE, TH, FR, SA, SU
|
||||
|
||||
for var in (relativedelta, MO, TU, WE, TH, FR, SA, SU):
|
||||
self.assertIsNot(var, None)
|
||||
|
||||
# In the public interface but not in all
|
||||
from dateutil.relativedelta import weekday
|
||||
self.assertIsNot(weekday, None)
|
||||
|
||||
|
||||
class ImportRRuleTest(unittest.TestCase):
|
||||
""" Test that dateutil.rrule related imports work properly """
|
||||
def testRRuleDirect(self):
|
||||
import dateutil.rrule
|
||||
|
||||
def testRRuleFrom(self):
|
||||
from dateutil import rrule
|
||||
|
||||
def testRRuleAll(self):
|
||||
from dateutil.rrule import rrule
|
||||
from dateutil.rrule import rruleset
|
||||
from dateutil.rrule import rrulestr
|
||||
from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY
|
||||
from dateutil.rrule import HOURLY, MINUTELY, SECONDLY
|
||||
from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU
|
||||
|
||||
rr_all = (rrule, rruleset, rrulestr,
|
||||
YEARLY, MONTHLY, WEEKLY, DAILY,
|
||||
HOURLY, MINUTELY, SECONDLY,
|
||||
MO, TU, WE, TH, FR, SA, SU)
|
||||
|
||||
for var in rr_all:
|
||||
self.assertIsNot(var, None)
|
||||
|
||||
# In the public interface but not in all
|
||||
from dateutil.rrule import weekday
|
||||
self.assertIsNot(weekday, None)
|
||||
|
||||
|
||||
class ImportTZTest(unittest.TestCase):
|
||||
""" Test that dateutil.tz related imports work properly """
|
||||
def testTzDirect(self):
|
||||
import dateutil.tz
|
||||
|
||||
def testTzFrom(self):
|
||||
from dateutil import tz
|
||||
|
||||
def testTzAll(self):
|
||||
from dateutil.tz import tzutc
|
||||
from dateutil.tz import tzoffset
|
||||
from dateutil.tz import tzlocal
|
||||
from dateutil.tz import tzfile
|
||||
from dateutil.tz import tzrange
|
||||
from dateutil.tz import tzstr
|
||||
from dateutil.tz import tzical
|
||||
from dateutil.tz import gettz
|
||||
from dateutil.tz import tzwin
|
||||
from dateutil.tz import tzwinlocal
|
||||
|
||||
tz_all = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange",
|
||||
"tzstr", "tzical", "gettz"]
|
||||
|
||||
tz_all += ["tzwin", "tzwinlocal"] if sys.platform.startswith("win") else []
|
||||
lvars = locals()
|
||||
|
||||
for var in tz_all:
|
||||
self.assertIsNot(lvars[var], None)
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith('win'), "Requires Windows")
|
||||
class ImportTZWinTest(unittest.TestCase):
|
||||
""" Test that dateutil.tzwin related imports work properly """
|
||||
def testTzwinDirect(self):
|
||||
import dateutil.tzwin
|
||||
|
||||
def testTzwinFrom(self):
|
||||
from dateutil import tzwin
|
||||
|
||||
def testTzwinStar(self):
|
||||
from dateutil.tzwin import tzwin
|
||||
from dateutil.tzwin import tzwinlocal
|
||||
|
||||
tzwin_all = [tzwin, tzwinlocal]
|
||||
|
||||
for var in tzwin_all:
|
||||
self.assertIsNot(var, None)
|
||||
|
||||
|
||||
class ImportZoneInfoTest(unittest.TestCase):
|
||||
def testZoneinfoDirect(self):
|
||||
import dateutil.zoneinfo
|
||||
|
||||
def testZoneinfoFrom(self):
|
||||
from dateutil import zoneinfo
|
||||
|
||||
def testZoneinfoStar(self):
|
||||
from dateutil.zoneinfo import gettz
|
||||
from dateutil.zoneinfo import gettz_db_metadata
|
||||
from dateutil.zoneinfo import rebuild
|
||||
|
||||
zi_all = (gettz, gettz_db_metadata, rebuild)
|
||||
|
||||
for var in zi_all:
|
||||
self.assertIsNot(var, None)
|
897
benchmark/third_party/dateutil/test/test_parser.py
vendored
Normal file
897
benchmark/third_party/dateutil/test/test_parser.py
vendored
Normal file
@@ -0,0 +1,897 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from ._common import unittest
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from dateutil.tz import tzoffset
|
||||
from dateutil.parser import parse, parserinfo
|
||||
|
||||
from six import assertRaisesRegex, PY3
|
||||
from six.moves import StringIO
|
||||
|
||||
|
||||
class ParserTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.tzinfos = {"BRST": -10800}
|
||||
self.brsttz = tzoffset("BRST", -10800)
|
||||
self.default = datetime(2003, 9, 25)
|
||||
|
||||
# Parser should be able to handle bytestring and unicode
|
||||
self.uni_str = '2014-05-01 08:00:00'
|
||||
self.str_str = self.uni_str.encode()
|
||||
|
||||
def testEmptyString(self):
|
||||
with self.assertRaises(ValueError):
|
||||
parse('')
|
||||
|
||||
def testNone(self):
|
||||
with self.assertRaises(TypeError):
|
||||
parse(None)
|
||||
|
||||
def testInvalidType(self):
|
||||
with self.assertRaises(TypeError):
|
||||
parse(13)
|
||||
|
||||
def testDuckTyping(self):
|
||||
# We want to support arbitrary classes that implement the stream
|
||||
# interface.
|
||||
|
||||
class StringPassThrough(object):
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
def read(self, *args, **kwargs):
|
||||
return self.stream.read(*args, **kwargs)
|
||||
|
||||
dstr = StringPassThrough(StringIO('2014 January 19'))
|
||||
|
||||
self.assertEqual(parse(dstr), datetime(2014, 1, 19))
|
||||
|
||||
def testParseStream(self):
|
||||
dstr = StringIO('2014 January 19')
|
||||
|
||||
self.assertEqual(parse(dstr), datetime(2014, 1, 19))
|
||||
|
||||
def testParseStr(self):
|
||||
self.assertEqual(parse(self.str_str),
|
||||
parse(self.uni_str))
|
||||
|
||||
def testParserParseStr(self):
|
||||
from dateutil.parser import parser
|
||||
|
||||
self.assertEqual(parser().parse(self.str_str),
|
||||
parser().parse(self.uni_str))
|
||||
|
||||
def testParseUnicodeWords(self):
|
||||
|
||||
class rus_parserinfo(parserinfo):
|
||||
MONTHS = [("янв", "Январь"),
|
||||
("фев", "Февраль"),
|
||||
("мар", "Март"),
|
||||
("апр", "Апрель"),
|
||||
("май", "Май"),
|
||||
("июн", "Июнь"),
|
||||
("июл", "Июль"),
|
||||
("авг", "Август"),
|
||||
("сен", "Сентябрь"),
|
||||
("окт", "Октябрь"),
|
||||
("ноя", "Ноябрь"),
|
||||
("дек", "Декабрь")]
|
||||
|
||||
self.assertEqual(parse('10 Сентябрь 2015 10:20',
|
||||
parserinfo=rus_parserinfo()),
|
||||
datetime(2015, 9, 10, 10, 20))
|
||||
|
||||
def testParseWithNulls(self):
|
||||
# This relies on the from __future__ import unicode_literals, because
|
||||
# explicitly specifying a unicode literal is a syntax error in Py 3.2
|
||||
# May want to switch to u'...' if we ever drop Python 3.2 support.
|
||||
pstring = '\x00\x00August 29, 1924'
|
||||
|
||||
self.assertEqual(parse(pstring),
|
||||
datetime(1924, 8, 29))
|
||||
|
||||
def testDateCommandFormat(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
|
||||
tzinfos=self.tzinfos),
|
||||
datetime(2003, 9, 25, 10, 36, 28,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testDateCommandFormatUnicode(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
|
||||
tzinfos=self.tzinfos),
|
||||
datetime(2003, 9, 25, 10, 36, 28,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testDateCommandFormatReversed(self):
|
||||
self.assertEqual(parse("2003 10:36:28 BRST 25 Sep Thu",
|
||||
tzinfos=self.tzinfos),
|
||||
datetime(2003, 9, 25, 10, 36, 28,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testDateCommandFormatWithLong(self):
|
||||
if not PY3:
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
|
||||
tzinfos={"BRST": long(-10800)}),
|
||||
datetime(2003, 9, 25, 10, 36, 28,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testDateCommandFormatIgnoreTz(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
|
||||
ignoretz=True),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip1(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28 2003"),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip2(self):
|
||||
self.assertEqual(parse("Thu Sep 25 10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip3(self):
|
||||
self.assertEqual(parse("Thu Sep 10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip4(self):
|
||||
self.assertEqual(parse("Thu 10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip5(self):
|
||||
self.assertEqual(parse("Sep 10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip6(self):
|
||||
self.assertEqual(parse("10:36:28", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testDateCommandFormatStrip7(self):
|
||||
self.assertEqual(parse("10:36", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36))
|
||||
|
||||
def testDateCommandFormatStrip8(self):
|
||||
self.assertEqual(parse("Thu Sep 25 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateCommandFormatStrip9(self):
|
||||
self.assertEqual(parse("Sep 25 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateCommandFormatStrip10(self):
|
||||
self.assertEqual(parse("Sep 2003", default=self.default),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateCommandFormatStrip11(self):
|
||||
self.assertEqual(parse("Sep", default=self.default),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateCommandFormatStrip12(self):
|
||||
self.assertEqual(parse("2003", default=self.default),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateRCommandFormat(self):
|
||||
self.assertEqual(parse("Thu, 25 Sep 2003 10:49:41 -0300"),
|
||||
datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOFormat(self):
|
||||
self.assertEqual(parse("2003-09-25T10:49:41.5-03:00"),
|
||||
datetime(2003, 9, 25, 10, 49, 41, 500000,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOFormatStrip1(self):
|
||||
self.assertEqual(parse("2003-09-25T10:49:41-03:00"),
|
||||
datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOFormatStrip2(self):
|
||||
self.assertEqual(parse("2003-09-25T10:49:41"),
|
||||
datetime(2003, 9, 25, 10, 49, 41))
|
||||
|
||||
def testISOFormatStrip3(self):
|
||||
self.assertEqual(parse("2003-09-25T10:49"),
|
||||
datetime(2003, 9, 25, 10, 49))
|
||||
|
||||
def testISOFormatStrip4(self):
|
||||
self.assertEqual(parse("2003-09-25T10"),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testISOFormatStrip5(self):
|
||||
self.assertEqual(parse("2003-09-25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testISOStrippedFormat(self):
|
||||
self.assertEqual(parse("20030925T104941.5-0300"),
|
||||
datetime(2003, 9, 25, 10, 49, 41, 500000,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOStrippedFormatStrip1(self):
|
||||
self.assertEqual(parse("20030925T104941-0300"),
|
||||
datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testISOStrippedFormatStrip2(self):
|
||||
self.assertEqual(parse("20030925T104941"),
|
||||
datetime(2003, 9, 25, 10, 49, 41))
|
||||
|
||||
def testISOStrippedFormatStrip3(self):
|
||||
self.assertEqual(parse("20030925T1049"),
|
||||
datetime(2003, 9, 25, 10, 49, 0))
|
||||
|
||||
def testISOStrippedFormatStrip4(self):
|
||||
self.assertEqual(parse("20030925T10"),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testISOStrippedFormatStrip5(self):
|
||||
self.assertEqual(parse("20030925"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testPythonLoggerFormat(self):
|
||||
self.assertEqual(parse("2003-09-25 10:49:41,502"),
|
||||
datetime(2003, 9, 25, 10, 49, 41, 502000))
|
||||
|
||||
def testNoSeparator1(self):
|
||||
self.assertEqual(parse("199709020908"),
|
||||
datetime(1997, 9, 2, 9, 8))
|
||||
|
||||
def testNoSeparator2(self):
|
||||
self.assertEqual(parse("19970902090807"),
|
||||
datetime(1997, 9, 2, 9, 8, 7))
|
||||
|
||||
def testDateWithDash1(self):
|
||||
self.assertEqual(parse("2003-09-25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash2(self):
|
||||
self.assertEqual(parse("2003-Sep-25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash3(self):
|
||||
self.assertEqual(parse("25-Sep-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash4(self):
|
||||
self.assertEqual(parse("25-Sep-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash5(self):
|
||||
self.assertEqual(parse("Sep-25-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash6(self):
|
||||
self.assertEqual(parse("09-25-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash7(self):
|
||||
self.assertEqual(parse("25-09-2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDash8(self):
|
||||
self.assertEqual(parse("10-09-2003", dayfirst=True),
|
||||
datetime(2003, 9, 10))
|
||||
|
||||
def testDateWithDash9(self):
|
||||
self.assertEqual(parse("10-09-2003"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithDash10(self):
|
||||
self.assertEqual(parse("10-09-03"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithDash11(self):
|
||||
self.assertEqual(parse("10-09-03", yearfirst=True),
|
||||
datetime(2010, 9, 3))
|
||||
|
||||
def testDateWithDot1(self):
|
||||
self.assertEqual(parse("2003.09.25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot2(self):
|
||||
self.assertEqual(parse("2003.Sep.25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot3(self):
|
||||
self.assertEqual(parse("25.Sep.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot4(self):
|
||||
self.assertEqual(parse("25.Sep.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot5(self):
|
||||
self.assertEqual(parse("Sep.25.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot6(self):
|
||||
self.assertEqual(parse("09.25.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot7(self):
|
||||
self.assertEqual(parse("25.09.2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithDot8(self):
|
||||
self.assertEqual(parse("10.09.2003", dayfirst=True),
|
||||
datetime(2003, 9, 10))
|
||||
|
||||
def testDateWithDot9(self):
|
||||
self.assertEqual(parse("10.09.2003"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithDot10(self):
|
||||
self.assertEqual(parse("10.09.03"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithDot11(self):
|
||||
self.assertEqual(parse("10.09.03", yearfirst=True),
|
||||
datetime(2010, 9, 3))
|
||||
|
||||
def testDateWithSlash1(self):
|
||||
self.assertEqual(parse("2003/09/25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash2(self):
|
||||
self.assertEqual(parse("2003/Sep/25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash3(self):
|
||||
self.assertEqual(parse("25/Sep/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash4(self):
|
||||
self.assertEqual(parse("25/Sep/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash5(self):
|
||||
self.assertEqual(parse("Sep/25/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash6(self):
|
||||
self.assertEqual(parse("09/25/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash7(self):
|
||||
self.assertEqual(parse("25/09/2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSlash8(self):
|
||||
self.assertEqual(parse("10/09/2003", dayfirst=True),
|
||||
datetime(2003, 9, 10))
|
||||
|
||||
def testDateWithSlash9(self):
|
||||
self.assertEqual(parse("10/09/2003"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithSlash10(self):
|
||||
self.assertEqual(parse("10/09/03"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithSlash11(self):
|
||||
self.assertEqual(parse("10/09/03", yearfirst=True),
|
||||
datetime(2010, 9, 3))
|
||||
|
||||
def testDateWithSpace1(self):
|
||||
self.assertEqual(parse("2003 09 25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace2(self):
|
||||
self.assertEqual(parse("2003 Sep 25"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace3(self):
|
||||
self.assertEqual(parse("25 Sep 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace4(self):
|
||||
self.assertEqual(parse("25 Sep 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace5(self):
|
||||
self.assertEqual(parse("Sep 25 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace6(self):
|
||||
self.assertEqual(parse("09 25 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace7(self):
|
||||
self.assertEqual(parse("25 09 2003"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testDateWithSpace8(self):
|
||||
self.assertEqual(parse("10 09 2003", dayfirst=True),
|
||||
datetime(2003, 9, 10))
|
||||
|
||||
def testDateWithSpace9(self):
|
||||
self.assertEqual(parse("10 09 2003"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithSpace10(self):
|
||||
self.assertEqual(parse("10 09 03"),
|
||||
datetime(2003, 10, 9))
|
||||
|
||||
def testDateWithSpace11(self):
|
||||
self.assertEqual(parse("10 09 03", yearfirst=True),
|
||||
datetime(2010, 9, 3))
|
||||
|
||||
def testDateWithSpace12(self):
|
||||
self.assertEqual(parse("25 09 03"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testStrangelyOrderedDate1(self):
|
||||
self.assertEqual(parse("03 25 Sep"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testStrangelyOrderedDate2(self):
|
||||
self.assertEqual(parse("2003 25 Sep"),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testStrangelyOrderedDate3(self):
|
||||
self.assertEqual(parse("25 03 Sep"),
|
||||
datetime(2025, 9, 3))
|
||||
|
||||
def testHourWithLetters(self):
|
||||
self.assertEqual(parse("10h36m28.5s", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28, 500000))
|
||||
|
||||
def testHourWithLettersStrip1(self):
|
||||
self.assertEqual(parse("10h36m28s", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 28))
|
||||
|
||||
def testHourWithLettersStrip2(self):
|
||||
self.assertEqual(parse("10h36m", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36))
|
||||
|
||||
def testHourWithLettersStrip3(self):
|
||||
self.assertEqual(parse("10h", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourWithLettersStrip4(self):
|
||||
self.assertEqual(parse("10 h 36", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36))
|
||||
|
||||
def testHourWithLetterStrip5(self):
|
||||
self.assertEqual(parse("10 h 36.5", default=self.default),
|
||||
datetime(2003, 9, 25, 10, 36, 30))
|
||||
|
||||
def testMinuteWithLettersSpaces1(self):
|
||||
self.assertEqual(parse("36 m 5", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 36, 5))
|
||||
|
||||
def testMinuteWithLettersSpaces2(self):
|
||||
self.assertEqual(parse("36 m 5 s", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 36, 5))
|
||||
|
||||
def testMinuteWithLettersSpaces3(self):
|
||||
self.assertEqual(parse("36 m 05", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 36, 5))
|
||||
|
||||
def testMinuteWithLettersSpaces4(self):
|
||||
self.assertEqual(parse("36 m 05 s", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 36, 5))
|
||||
|
||||
def testAMPMNoHour(self):
|
||||
with self.assertRaises(ValueError):
|
||||
parse("AM")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
parse("Jan 20, 2015 PM")
|
||||
|
||||
def testHourAmPm1(self):
|
||||
self.assertEqual(parse("10h am", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm2(self):
|
||||
self.assertEqual(parse("10h pm", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm3(self):
|
||||
self.assertEqual(parse("10am", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm4(self):
|
||||
self.assertEqual(parse("10pm", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm5(self):
|
||||
self.assertEqual(parse("10:00 am", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm6(self):
|
||||
self.assertEqual(parse("10:00 pm", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm7(self):
|
||||
self.assertEqual(parse("10:00am", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm8(self):
|
||||
self.assertEqual(parse("10:00pm", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm9(self):
|
||||
self.assertEqual(parse("10:00a.m", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm10(self):
|
||||
self.assertEqual(parse("10:00p.m", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testHourAmPm11(self):
|
||||
self.assertEqual(parse("10:00a.m.", default=self.default),
|
||||
datetime(2003, 9, 25, 10))
|
||||
|
||||
def testHourAmPm12(self):
|
||||
self.assertEqual(parse("10:00p.m.", default=self.default),
|
||||
datetime(2003, 9, 25, 22))
|
||||
|
||||
def testAMPMRange(self):
|
||||
with self.assertRaises(ValueError):
|
||||
parse("13:44 AM")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
parse("January 25, 1921 23:13 PM")
|
||||
|
||||
def testPertain(self):
|
||||
self.assertEqual(parse("Sep 03", default=self.default),
|
||||
datetime(2003, 9, 3))
|
||||
self.assertEqual(parse("Sep of 03", default=self.default),
|
||||
datetime(2003, 9, 25))
|
||||
|
||||
def testWeekdayAlone(self):
|
||||
self.assertEqual(parse("Wed", default=self.default),
|
||||
datetime(2003, 10, 1))
|
||||
|
||||
def testLongWeekday(self):
|
||||
self.assertEqual(parse("Wednesday", default=self.default),
|
||||
datetime(2003, 10, 1))
|
||||
|
||||
def testLongMonth(self):
|
||||
self.assertEqual(parse("October", default=self.default),
|
||||
datetime(2003, 10, 25))
|
||||
|
||||
def testZeroYear(self):
|
||||
self.assertEqual(parse("31-Dec-00", default=self.default),
|
||||
datetime(2000, 12, 31))
|
||||
|
||||
def testFuzzy(self):
|
||||
s = "Today is 25 of September of 2003, exactly " \
|
||||
"at 10:49:41 with timezone -03:00."
|
||||
self.assertEqual(parse(s, fuzzy=True),
|
||||
datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz))
|
||||
|
||||
def testFuzzyWithTokens(self):
|
||||
s1 = "Today is 25 of September of 2003, exactly " \
|
||||
"at 10:49:41 with timezone -03:00."
|
||||
self.assertEqual(parse(s1, fuzzy_with_tokens=True),
|
||||
(datetime(2003, 9, 25, 10, 49, 41,
|
||||
tzinfo=self.brsttz),
|
||||
('Today is ', 'of ', ', exactly at ',
|
||||
' with timezone ', '.')))
|
||||
|
||||
s2 = "http://biz.yahoo.com/ipo/p/600221.html"
|
||||
self.assertEqual(parse(s2, fuzzy_with_tokens=True),
|
||||
(datetime(2060, 2, 21, 0, 0, 0),
|
||||
('http://biz.yahoo.com/ipo/p/', '.html')))
|
||||
|
||||
def testFuzzyAMPMProblem(self):
|
||||
# Sometimes fuzzy parsing results in AM/PM flag being set without
|
||||
# hours - if it's fuzzy it should ignore that.
|
||||
s1 = "I have a meeting on March 1, 1974."
|
||||
s2 = "On June 8th, 2020, I am going to be the first man on Mars"
|
||||
|
||||
# Also don't want any erroneous AM or PMs changing the parsed time
|
||||
s3 = "Meet me at the AM/PM on Sunset at 3:00 AM on December 3rd, 2003"
|
||||
s4 = "Meet me at 3:00AM on December 3rd, 2003 at the AM/PM on Sunset"
|
||||
|
||||
self.assertEqual(parse(s1, fuzzy=True), datetime(1974, 3, 1))
|
||||
self.assertEqual(parse(s2, fuzzy=True), datetime(2020, 6, 8))
|
||||
self.assertEqual(parse(s3, fuzzy=True), datetime(2003, 12, 3, 3))
|
||||
self.assertEqual(parse(s4, fuzzy=True), datetime(2003, 12, 3, 3))
|
||||
|
||||
def testFuzzyIgnoreAMPM(self):
|
||||
s1 = "Jan 29, 1945 14:45 AM I going to see you there?"
|
||||
|
||||
self.assertEqual(parse(s1, fuzzy=True), datetime(1945, 1, 29, 14, 45))
|
||||
|
||||
def testExtraSpace(self):
|
||||
self.assertEqual(parse(" July 4 , 1976 12:01:02 am "),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat1(self):
|
||||
self.assertEqual(parse("Wed, July 10, '96"),
|
||||
datetime(1996, 7, 10, 0, 0))
|
||||
|
||||
def testRandomFormat2(self):
|
||||
self.assertEqual(parse("1996.07.10 AD at 15:08:56 PDT",
|
||||
ignoretz=True),
|
||||
datetime(1996, 7, 10, 15, 8, 56))
|
||||
|
||||
def testRandomFormat3(self):
|
||||
self.assertEqual(parse("1996.July.10 AD 12:08 PM"),
|
||||
datetime(1996, 7, 10, 12, 8))
|
||||
|
||||
def testRandomFormat4(self):
|
||||
self.assertEqual(parse("Tuesday, April 12, 1952 AD 3:30:42pm PST",
|
||||
ignoretz=True),
|
||||
datetime(1952, 4, 12, 15, 30, 42))
|
||||
|
||||
def testRandomFormat5(self):
|
||||
self.assertEqual(parse("November 5, 1994, 8:15:30 am EST",
|
||||
ignoretz=True),
|
||||
datetime(1994, 11, 5, 8, 15, 30))
|
||||
|
||||
def testRandomFormat6(self):
|
||||
self.assertEqual(parse("1994-11-05T08:15:30-05:00",
|
||||
ignoretz=True),
|
||||
datetime(1994, 11, 5, 8, 15, 30))
|
||||
|
||||
def testRandomFormat7(self):
|
||||
self.assertEqual(parse("1994-11-05T08:15:30Z",
|
||||
ignoretz=True),
|
||||
datetime(1994, 11, 5, 8, 15, 30))
|
||||
|
||||
def testRandomFormat8(self):
|
||||
self.assertEqual(parse("July 4, 1976"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat9(self):
|
||||
self.assertEqual(parse("7 4 1976"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat10(self):
|
||||
self.assertEqual(parse("4 jul 1976"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat11(self):
|
||||
self.assertEqual(parse("7-4-76"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat12(self):
|
||||
self.assertEqual(parse("19760704"), datetime(1976, 7, 4))
|
||||
|
||||
def testRandomFormat13(self):
|
||||
self.assertEqual(parse("0:01:02", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 1, 2))
|
||||
|
||||
def testRandomFormat14(self):
|
||||
self.assertEqual(parse("12h 01m02s am", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 1, 2))
|
||||
|
||||
def testRandomFormat15(self):
|
||||
self.assertEqual(parse("0:01:02 on July 4, 1976"),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat16(self):
|
||||
self.assertEqual(parse("0:01:02 on July 4, 1976"),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat17(self):
|
||||
self.assertEqual(parse("1976-07-04T00:01:02Z", ignoretz=True),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat18(self):
|
||||
self.assertEqual(parse("July 4, 1976 12:01:02 am"),
|
||||
datetime(1976, 7, 4, 0, 1, 2))
|
||||
|
||||
def testRandomFormat19(self):
|
||||
self.assertEqual(parse("Mon Jan 2 04:24:27 1995"),
|
||||
datetime(1995, 1, 2, 4, 24, 27))
|
||||
|
||||
def testRandomFormat20(self):
|
||||
self.assertEqual(parse("Tue Apr 4 00:22:12 PDT 1995", ignoretz=True),
|
||||
datetime(1995, 4, 4, 0, 22, 12))
|
||||
|
||||
def testRandomFormat21(self):
|
||||
self.assertEqual(parse("04.04.95 00:22"),
|
||||
datetime(1995, 4, 4, 0, 22))
|
||||
|
||||
def testRandomFormat22(self):
|
||||
self.assertEqual(parse("Jan 1 1999 11:23:34.578"),
|
||||
datetime(1999, 1, 1, 11, 23, 34, 578000))
|
||||
|
||||
def testRandomFormat23(self):
|
||||
self.assertEqual(parse("950404 122212"),
|
||||
datetime(1995, 4, 4, 12, 22, 12))
|
||||
|
||||
def testRandomFormat24(self):
|
||||
self.assertEqual(parse("0:00 PM, PST", default=self.default,
|
||||
ignoretz=True),
|
||||
datetime(2003, 9, 25, 12, 0))
|
||||
|
||||
def testRandomFormat25(self):
|
||||
self.assertEqual(parse("12:08 PM", default=self.default),
|
||||
datetime(2003, 9, 25, 12, 8))
|
||||
|
||||
def testRandomFormat26(self):
|
||||
self.assertEqual(parse("5:50 A.M. on June 13, 1990"),
|
||||
datetime(1990, 6, 13, 5, 50))
|
||||
|
||||
def testRandomFormat27(self):
|
||||
self.assertEqual(parse("3rd of May 2001"), datetime(2001, 5, 3))
|
||||
|
||||
def testRandomFormat28(self):
|
||||
self.assertEqual(parse("5th of March 2001"), datetime(2001, 3, 5))
|
||||
|
||||
def testRandomFormat29(self):
|
||||
self.assertEqual(parse("1st of May 2003"), datetime(2003, 5, 1))
|
||||
|
||||
def testRandomFormat30(self):
|
||||
self.assertEqual(parse("01h02m03", default=self.default),
|
||||
datetime(2003, 9, 25, 1, 2, 3))
|
||||
|
||||
def testRandomFormat31(self):
|
||||
self.assertEqual(parse("01h02", default=self.default),
|
||||
datetime(2003, 9, 25, 1, 2))
|
||||
|
||||
def testRandomFormat32(self):
|
||||
self.assertEqual(parse("01h02s", default=self.default),
|
||||
datetime(2003, 9, 25, 1, 0, 2))
|
||||
|
||||
def testRandomFormat33(self):
|
||||
self.assertEqual(parse("01m02", default=self.default),
|
||||
datetime(2003, 9, 25, 0, 1, 2))
|
||||
|
||||
def testRandomFormat34(self):
|
||||
self.assertEqual(parse("01m02h", default=self.default),
|
||||
datetime(2003, 9, 25, 2, 1))
|
||||
|
||||
def testRandomFormat35(self):
|
||||
self.assertEqual(parse("2004 10 Apr 11h30m", default=self.default),
|
||||
datetime(2004, 4, 10, 11, 30))
|
||||
|
||||
def test_99_ad(self):
|
||||
self.assertEqual(parse('0099-01-01T00:00:00'),
|
||||
datetime(99, 1, 1, 0, 0))
|
||||
|
||||
def test_31_ad(self):
|
||||
self.assertEqual(parse('0031-01-01T00:00:00'),
|
||||
datetime(31, 1, 1, 0, 0))
|
||||
|
||||
def testInvalidDay(self):
|
||||
with self.assertRaises(ValueError):
|
||||
parse("Feb 30, 2007")
|
||||
|
||||
def testUnspecifiedDayFallback(self):
|
||||
# Test that for an unspecified day, the fallback behavior is correct.
|
||||
self.assertEqual(parse("April 2009", default=datetime(2010, 1, 31)),
|
||||
datetime(2009, 4, 30))
|
||||
|
||||
def testUnspecifiedDayFallbackFebNoLeapYear(self):
|
||||
self.assertEqual(parse("Feb 2007", default=datetime(2010, 1, 31)),
|
||||
datetime(2007, 2, 28))
|
||||
|
||||
def testUnspecifiedDayFallbackFebLeapYear(self):
|
||||
self.assertEqual(parse("Feb 2008", default=datetime(2010, 1, 31)),
|
||||
datetime(2008, 2, 29))
|
||||
|
||||
def testErrorType01(self):
|
||||
self.assertRaises(ValueError,
|
||||
parse, 'shouldfail')
|
||||
|
||||
def testCorrectErrorOnFuzzyWithTokens(self):
|
||||
assertRaisesRegex(self, ValueError, 'Unknown string format',
|
||||
parse, '04/04/32/423', fuzzy_with_tokens=True)
|
||||
assertRaisesRegex(self, ValueError, 'Unknown string format',
|
||||
parse, '04/04/04 +32423', fuzzy_with_tokens=True)
|
||||
assertRaisesRegex(self, ValueError, 'Unknown string format',
|
||||
parse, '04/04/0d4', fuzzy_with_tokens=True)
|
||||
|
||||
def testIncreasingCTime(self):
|
||||
# This test will check 200 different years, every month, every day,
|
||||
# every hour, every minute, every second, and every weekday, using
|
||||
# a delta of more or less 1 year, 1 month, 1 day, 1 minute and
|
||||
# 1 second.
|
||||
delta = timedelta(days=365+31+1, seconds=1+60+60*60)
|
||||
dt = datetime(1900, 1, 1, 0, 0, 0, 0)
|
||||
for i in range(200):
|
||||
self.assertEqual(parse(dt.ctime()), dt)
|
||||
dt += delta
|
||||
|
||||
def testIncreasingISOFormat(self):
|
||||
delta = timedelta(days=365+31+1, seconds=1+60+60*60)
|
||||
dt = datetime(1900, 1, 1, 0, 0, 0, 0)
|
||||
for i in range(200):
|
||||
self.assertEqual(parse(dt.isoformat()), dt)
|
||||
dt += delta
|
||||
|
||||
def testMicrosecondsPrecisionError(self):
|
||||
# Skip found out that sad precision problem. :-(
|
||||
dt1 = parse("00:11:25.01")
|
||||
dt2 = parse("00:12:10.01")
|
||||
self.assertEqual(dt1.microsecond, 10000)
|
||||
self.assertEqual(dt2.microsecond, 10000)
|
||||
|
||||
def testMicrosecondPrecisionErrorReturns(self):
|
||||
# One more precision issue, discovered by Eric Brown. This should
|
||||
# be the last one, as we're no longer using floating points.
|
||||
for ms in [100001, 100000, 99999, 99998,
|
||||
10001, 10000, 9999, 9998,
|
||||
1001, 1000, 999, 998,
|
||||
101, 100, 99, 98]:
|
||||
dt = datetime(2008, 2, 27, 21, 26, 1, ms)
|
||||
self.assertEqual(parse(dt.isoformat()), dt)
|
||||
|
||||
def testHighPrecisionSeconds(self):
|
||||
self.assertEqual(parse("20080227T21:26:01.123456789"),
|
||||
datetime(2008, 2, 27, 21, 26, 1, 123456))
|
||||
|
||||
def testCustomParserInfo(self):
|
||||
# Custom parser info wasn't working, as Michael Elsdörfer discovered.
|
||||
from dateutil.parser import parserinfo, parser
|
||||
|
||||
class myparserinfo(parserinfo):
|
||||
MONTHS = parserinfo.MONTHS[:]
|
||||
MONTHS[0] = ("Foo", "Foo")
|
||||
myparser = parser(myparserinfo())
|
||||
dt = myparser.parse("01/Foo/2007")
|
||||
self.assertEqual(dt, datetime(2007, 1, 1))
|
||||
|
||||
def testCustomParserShortDaynames(self):
|
||||
# Horacio Hoyos discovered that day names shorter than 3 characters,
|
||||
# for example two letter German day name abbreviations, don't work:
|
||||
# https://github.com/dateutil/dateutil/issues/343
|
||||
from dateutil.parser import parserinfo, parser
|
||||
|
||||
class GermanParserInfo(parserinfo):
|
||||
WEEKDAYS = [("Mo", "Montag"),
|
||||
("Di", "Dienstag"),
|
||||
("Mi", "Mittwoch"),
|
||||
("Do", "Donnerstag"),
|
||||
("Fr", "Freitag"),
|
||||
("Sa", "Samstag"),
|
||||
("So", "Sonntag")]
|
||||
|
||||
myparser = parser(GermanParserInfo())
|
||||
dt = myparser.parse("Sa 21. Jan 2017")
|
||||
self.assertEqual(dt, datetime(2017, 1, 21))
|
||||
|
||||
def testNoYearFirstNoDayFirst(self):
|
||||
dtstr = '090107'
|
||||
|
||||
# Should be MMDDYY
|
||||
self.assertEqual(parse(dtstr),
|
||||
datetime(2007, 9, 1))
|
||||
|
||||
self.assertEqual(parse(dtstr, yearfirst=False, dayfirst=False),
|
||||
datetime(2007, 9, 1))
|
||||
|
||||
def testYearFirst(self):
|
||||
dtstr = '090107'
|
||||
|
||||
# Should be MMDDYY
|
||||
self.assertEqual(parse(dtstr, yearfirst=True),
|
||||
datetime(2009, 1, 7))
|
||||
|
||||
self.assertEqual(parse(dtstr, yearfirst=True, dayfirst=False),
|
||||
datetime(2009, 1, 7))
|
||||
|
||||
def testDayFirst(self):
|
||||
dtstr = '090107'
|
||||
|
||||
# Should be DDMMYY
|
||||
self.assertEqual(parse(dtstr, dayfirst=True),
|
||||
datetime(2007, 1, 9))
|
||||
|
||||
self.assertEqual(parse(dtstr, yearfirst=False, dayfirst=True),
|
||||
datetime(2007, 1, 9))
|
||||
|
||||
def testDayFirstYearFirst(self):
|
||||
dtstr = '090107'
|
||||
# Should be YYDDMM
|
||||
self.assertEqual(parse(dtstr, yearfirst=True, dayfirst=True),
|
||||
datetime(2009, 7, 1))
|
||||
|
||||
def testUnambiguousYearFirst(self):
|
||||
dtstr = '2015 09 25'
|
||||
self.assertEqual(parse(dtstr, yearfirst=True),
|
||||
datetime(2015, 9, 25))
|
||||
|
||||
def testUnambiguousDayFirst(self):
|
||||
dtstr = '2015 09 25'
|
||||
self.assertEqual(parse(dtstr, dayfirst=True),
|
||||
datetime(2015, 9, 25))
|
||||
|
||||
def testUnambiguousDayFirstYearFirst(self):
|
||||
dtstr = '2015 09 25'
|
||||
self.assertEqual(parse(dtstr, dayfirst=True, yearfirst=True),
|
||||
datetime(2015, 9, 25))
|
577
benchmark/third_party/dateutil/test/test_relativedelta.py
vendored
Normal file
577
benchmark/third_party/dateutil/test/test_relativedelta.py
vendored
Normal file
@@ -0,0 +1,577 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from ._common import unittest, WarningTestMixin, NotAValue
|
||||
|
||||
import calendar
|
||||
from datetime import datetime, date, timedelta
|
||||
|
||||
from dateutil.relativedelta import relativedelta, MO, TU, WE, FR, SU
|
||||
|
||||
|
||||
class RelativeDeltaTest(WarningTestMixin, unittest.TestCase):
|
||||
now = datetime(2003, 9, 17, 20, 54, 47, 282310)
|
||||
today = date(2003, 9, 17)
|
||||
|
||||
def testInheritance(self):
|
||||
# Ensure that relativedelta is inheritance-friendly.
|
||||
class rdChildClass(relativedelta):
|
||||
pass
|
||||
|
||||
ccRD = rdChildClass(years=1, months=1, days=1, leapdays=1, weeks=1,
|
||||
hours=1, minutes=1, seconds=1, microseconds=1)
|
||||
|
||||
rd = relativedelta(years=1, months=1, days=1, leapdays=1, weeks=1,
|
||||
hours=1, minutes=1, seconds=1, microseconds=1)
|
||||
|
||||
self.assertEqual(type(ccRD + rd), type(ccRD),
|
||||
msg='Addition does not inherit type.')
|
||||
|
||||
self.assertEqual(type(ccRD - rd), type(ccRD),
|
||||
msg='Subtraction does not inherit type.')
|
||||
|
||||
self.assertEqual(type(-ccRD), type(ccRD),
|
||||
msg='Negation does not inherit type.')
|
||||
|
||||
self.assertEqual(type(ccRD * 5.0), type(ccRD),
|
||||
msg='Multiplication does not inherit type.')
|
||||
|
||||
self.assertEqual(type(ccRD / 5.0), type(ccRD),
|
||||
msg='Division does not inherit type.')
|
||||
|
||||
def testMonthEndMonthBeginning(self):
|
||||
self.assertEqual(relativedelta(datetime(2003, 1, 31, 23, 59, 59),
|
||||
datetime(2003, 3, 1, 0, 0, 0)),
|
||||
relativedelta(months=-1, seconds=-1))
|
||||
|
||||
self.assertEqual(relativedelta(datetime(2003, 3, 1, 0, 0, 0),
|
||||
datetime(2003, 1, 31, 23, 59, 59)),
|
||||
relativedelta(months=1, seconds=1))
|
||||
|
||||
def testMonthEndMonthBeginningLeapYear(self):
|
||||
self.assertEqual(relativedelta(datetime(2012, 1, 31, 23, 59, 59),
|
||||
datetime(2012, 3, 1, 0, 0, 0)),
|
||||
relativedelta(months=-1, seconds=-1))
|
||||
|
||||
self.assertEqual(relativedelta(datetime(2003, 3, 1, 0, 0, 0),
|
||||
datetime(2003, 1, 31, 23, 59, 59)),
|
||||
relativedelta(months=1, seconds=1))
|
||||
|
||||
def testNextMonth(self):
|
||||
self.assertEqual(self.now+relativedelta(months=+1),
|
||||
datetime(2003, 10, 17, 20, 54, 47, 282310))
|
||||
|
||||
def testNextMonthPlusOneWeek(self):
|
||||
self.assertEqual(self.now+relativedelta(months=+1, weeks=+1),
|
||||
datetime(2003, 10, 24, 20, 54, 47, 282310))
|
||||
|
||||
def testNextMonthPlusOneWeek10am(self):
|
||||
self.assertEqual(self.today +
|
||||
relativedelta(months=+1, weeks=+1, hour=10),
|
||||
datetime(2003, 10, 24, 10, 0))
|
||||
|
||||
def testNextMonthPlusOneWeek10amDiff(self):
|
||||
self.assertEqual(relativedelta(datetime(2003, 10, 24, 10, 0),
|
||||
self.today),
|
||||
relativedelta(months=+1, days=+7, hours=+10))
|
||||
|
||||
def testOneMonthBeforeOneYear(self):
|
||||
self.assertEqual(self.now+relativedelta(years=+1, months=-1),
|
||||
datetime(2004, 8, 17, 20, 54, 47, 282310))
|
||||
|
||||
def testMonthsOfDiffNumOfDays(self):
|
||||
self.assertEqual(date(2003, 1, 27)+relativedelta(months=+1),
|
||||
date(2003, 2, 27))
|
||||
self.assertEqual(date(2003, 1, 31)+relativedelta(months=+1),
|
||||
date(2003, 2, 28))
|
||||
self.assertEqual(date(2003, 1, 31)+relativedelta(months=+2),
|
||||
date(2003, 3, 31))
|
||||
|
||||
def testMonthsOfDiffNumOfDaysWithYears(self):
|
||||
self.assertEqual(date(2000, 2, 28)+relativedelta(years=+1),
|
||||
date(2001, 2, 28))
|
||||
self.assertEqual(date(2000, 2, 29)+relativedelta(years=+1),
|
||||
date(2001, 2, 28))
|
||||
|
||||
self.assertEqual(date(1999, 2, 28)+relativedelta(years=+1),
|
||||
date(2000, 2, 28))
|
||||
self.assertEqual(date(1999, 3, 1)+relativedelta(years=+1),
|
||||
date(2000, 3, 1))
|
||||
self.assertEqual(date(1999, 3, 1)+relativedelta(years=+1),
|
||||
date(2000, 3, 1))
|
||||
|
||||
self.assertEqual(date(2001, 2, 28)+relativedelta(years=-1),
|
||||
date(2000, 2, 28))
|
||||
self.assertEqual(date(2001, 3, 1)+relativedelta(years=-1),
|
||||
date(2000, 3, 1))
|
||||
|
||||
def testNextFriday(self):
|
||||
self.assertEqual(self.today+relativedelta(weekday=FR),
|
||||
date(2003, 9, 19))
|
||||
|
||||
def testNextFridayInt(self):
|
||||
self.assertEqual(self.today+relativedelta(weekday=calendar.FRIDAY),
|
||||
date(2003, 9, 19))
|
||||
|
||||
def testLastFridayInThisMonth(self):
|
||||
self.assertEqual(self.today+relativedelta(day=31, weekday=FR(-1)),
|
||||
date(2003, 9, 26))
|
||||
|
||||
def testNextWednesdayIsToday(self):
|
||||
self.assertEqual(self.today+relativedelta(weekday=WE),
|
||||
date(2003, 9, 17))
|
||||
|
||||
def testNextWenesdayNotToday(self):
|
||||
self.assertEqual(self.today+relativedelta(days=+1, weekday=WE),
|
||||
date(2003, 9, 24))
|
||||
|
||||
def test15thISOYearWeek(self):
|
||||
self.assertEqual(date(2003, 1, 1) +
|
||||
relativedelta(day=4, weeks=+14, weekday=MO(-1)),
|
||||
date(2003, 4, 7))
|
||||
|
||||
def testMillenniumAge(self):
|
||||
self.assertEqual(relativedelta(self.now, date(2001, 1, 1)),
|
||||
relativedelta(years=+2, months=+8, days=+16,
|
||||
hours=+20, minutes=+54, seconds=+47,
|
||||
microseconds=+282310))
|
||||
|
||||
def testJohnAge(self):
|
||||
self.assertEqual(relativedelta(self.now,
|
||||
datetime(1978, 4, 5, 12, 0)),
|
||||
relativedelta(years=+25, months=+5, days=+12,
|
||||
hours=+8, minutes=+54, seconds=+47,
|
||||
microseconds=+282310))
|
||||
|
||||
def testJohnAgeWithDate(self):
|
||||
self.assertEqual(relativedelta(self.today,
|
||||
datetime(1978, 4, 5, 12, 0)),
|
||||
relativedelta(years=+25, months=+5, days=+11,
|
||||
hours=+12))
|
||||
|
||||
def testYearDay(self):
|
||||
self.assertEqual(date(2003, 1, 1)+relativedelta(yearday=260),
|
||||
date(2003, 9, 17))
|
||||
self.assertEqual(date(2002, 1, 1)+relativedelta(yearday=260),
|
||||
date(2002, 9, 17))
|
||||
self.assertEqual(date(2000, 1, 1)+relativedelta(yearday=260),
|
||||
date(2000, 9, 16))
|
||||
self.assertEqual(self.today+relativedelta(yearday=261),
|
||||
date(2003, 9, 18))
|
||||
|
||||
def testYearDayBug(self):
|
||||
# Tests a problem reported by Adam Ryan.
|
||||
self.assertEqual(date(2010, 1, 1)+relativedelta(yearday=15),
|
||||
date(2010, 1, 15))
|
||||
|
||||
def testNonLeapYearDay(self):
|
||||
self.assertEqual(date(2003, 1, 1)+relativedelta(nlyearday=260),
|
||||
date(2003, 9, 17))
|
||||
self.assertEqual(date(2002, 1, 1)+relativedelta(nlyearday=260),
|
||||
date(2002, 9, 17))
|
||||
self.assertEqual(date(2000, 1, 1)+relativedelta(nlyearday=260),
|
||||
date(2000, 9, 17))
|
||||
self.assertEqual(self.today+relativedelta(yearday=261),
|
||||
date(2003, 9, 18))
|
||||
|
||||
def testAddition(self):
|
||||
self.assertEqual(relativedelta(days=10) +
|
||||
relativedelta(years=1, months=2, days=3, hours=4,
|
||||
minutes=5, microseconds=6),
|
||||
relativedelta(years=1, months=2, days=13, hours=4,
|
||||
minutes=5, microseconds=6))
|
||||
|
||||
def testAbsoluteAddition(self):
|
||||
self.assertEqual(relativedelta() + relativedelta(day=0, hour=0),
|
||||
relativedelta(day=0, hour=0))
|
||||
self.assertEqual(relativedelta(day=0, hour=0) + relativedelta(),
|
||||
relativedelta(day=0, hour=0))
|
||||
|
||||
def testAdditionToDatetime(self):
|
||||
self.assertEqual(datetime(2000, 1, 1) + relativedelta(days=1),
|
||||
datetime(2000, 1, 2))
|
||||
|
||||
def testRightAdditionToDatetime(self):
|
||||
self.assertEqual(relativedelta(days=1) + datetime(2000, 1, 1),
|
||||
datetime(2000, 1, 2))
|
||||
|
||||
def testAdditionInvalidType(self):
|
||||
with self.assertRaises(TypeError):
|
||||
relativedelta(days=3) + 9
|
||||
|
||||
def testAdditionUnsupportedType(self):
|
||||
# For unsupported types that define their own comparators, etc.
|
||||
self.assertIs(relativedelta(days=1) + NotAValue, NotAValue)
|
||||
|
||||
def testSubtraction(self):
|
||||
self.assertEqual(relativedelta(days=10) -
|
||||
relativedelta(years=1, months=2, days=3, hours=4,
|
||||
minutes=5, microseconds=6),
|
||||
relativedelta(years=-1, months=-2, days=7, hours=-4,
|
||||
minutes=-5, microseconds=-6))
|
||||
|
||||
def testRightSubtractionFromDatetime(self):
|
||||
self.assertEqual(datetime(2000, 1, 2) - relativedelta(days=1),
|
||||
datetime(2000, 1, 1))
|
||||
|
||||
def testSubractionWithDatetime(self):
|
||||
self.assertRaises(TypeError, lambda x, y: x - y,
|
||||
(relativedelta(days=1), datetime(2000, 1, 1)))
|
||||
|
||||
def testSubtractionInvalidType(self):
|
||||
with self.assertRaises(TypeError):
|
||||
relativedelta(hours=12) - 14
|
||||
|
||||
def testSubtractionUnsupportedType(self):
|
||||
self.assertIs(relativedelta(days=1) + NotAValue, NotAValue)
|
||||
|
||||
def testMultiplication(self):
|
||||
self.assertEqual(datetime(2000, 1, 1) + relativedelta(days=1) * 28,
|
||||
datetime(2000, 1, 29))
|
||||
self.assertEqual(datetime(2000, 1, 1) + 28 * relativedelta(days=1),
|
||||
datetime(2000, 1, 29))
|
||||
|
||||
def testMultiplicationUnsupportedType(self):
|
||||
self.assertIs(relativedelta(days=1) * NotAValue, NotAValue)
|
||||
|
||||
def testDivision(self):
|
||||
self.assertEqual(datetime(2000, 1, 1) + relativedelta(days=28) / 28,
|
||||
datetime(2000, 1, 2))
|
||||
|
||||
def testDivisionUnsupportedType(self):
|
||||
self.assertIs(relativedelta(days=1) / NotAValue, NotAValue)
|
||||
|
||||
def testBoolean(self):
|
||||
self.assertFalse(relativedelta(days=0))
|
||||
self.assertTrue(relativedelta(days=1))
|
||||
|
||||
def testComparison(self):
|
||||
d1 = relativedelta(years=1, months=1, days=1, leapdays=0, hours=1,
|
||||
minutes=1, seconds=1, microseconds=1)
|
||||
d2 = relativedelta(years=1, months=1, days=1, leapdays=0, hours=1,
|
||||
minutes=1, seconds=1, microseconds=1)
|
||||
d3 = relativedelta(years=1, months=1, days=1, leapdays=0, hours=1,
|
||||
minutes=1, seconds=1, microseconds=2)
|
||||
|
||||
self.assertEqual(d1, d2)
|
||||
self.assertNotEqual(d1, d3)
|
||||
|
||||
def testInequalityTypeMismatch(self):
|
||||
# Different type
|
||||
self.assertFalse(relativedelta(year=1) == 19)
|
||||
|
||||
def testInequalityUnsupportedType(self):
|
||||
self.assertIs(relativedelta(hours=3) == NotAValue, NotAValue)
|
||||
|
||||
def testInequalityWeekdays(self):
|
||||
# Different weekdays
|
||||
no_wday = relativedelta(year=1997, month=4)
|
||||
wday_mo_1 = relativedelta(year=1997, month=4, weekday=MO(+1))
|
||||
wday_mo_2 = relativedelta(year=1997, month=4, weekday=MO(+2))
|
||||
wday_tu = relativedelta(year=1997, month=4, weekday=TU)
|
||||
|
||||
self.assertTrue(wday_mo_1 == wday_mo_1)
|
||||
|
||||
self.assertFalse(no_wday == wday_mo_1)
|
||||
self.assertFalse(wday_mo_1 == no_wday)
|
||||
|
||||
self.assertFalse(wday_mo_1 == wday_mo_2)
|
||||
self.assertFalse(wday_mo_2 == wday_mo_1)
|
||||
|
||||
self.assertFalse(wday_mo_1 == wday_tu)
|
||||
self.assertFalse(wday_tu == wday_mo_1)
|
||||
|
||||
def testMonthOverflow(self):
|
||||
self.assertEqual(relativedelta(months=273),
|
||||
relativedelta(years=22, months=9))
|
||||
|
||||
def testWeeks(self):
|
||||
# Test that the weeks property is working properly.
|
||||
rd = relativedelta(years=4, months=2, weeks=8, days=6)
|
||||
self.assertEqual((rd.weeks, rd.days), (8, 8 * 7 + 6))
|
||||
|
||||
rd.weeks = 3
|
||||
self.assertEqual((rd.weeks, rd.days), (3, 3 * 7 + 6))
|
||||
|
||||
def testRelativeDeltaRepr(self):
|
||||
self.assertEqual(repr(relativedelta(years=1, months=-1, days=15)),
|
||||
'relativedelta(years=+1, months=-1, days=+15)')
|
||||
|
||||
self.assertEqual(repr(relativedelta(months=14, seconds=-25)),
|
||||
'relativedelta(years=+1, months=+2, seconds=-25)')
|
||||
|
||||
self.assertEqual(repr(relativedelta(month=3, hour=3, weekday=SU(3))),
|
||||
'relativedelta(month=3, weekday=SU(+3), hour=3)')
|
||||
|
||||
def testRelativeDeltaFractionalYear(self):
|
||||
with self.assertRaises(ValueError):
|
||||
relativedelta(years=1.5)
|
||||
|
||||
def testRelativeDeltaFractionalMonth(self):
|
||||
with self.assertRaises(ValueError):
|
||||
relativedelta(months=1.5)
|
||||
|
||||
def testRelativeDeltaFractionalAbsolutes(self):
|
||||
# Fractional absolute values will soon be unsupported,
|
||||
# check for the deprecation warning.
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(year=2.86)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(month=1.29)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(day=0.44)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(hour=23.98)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(minute=45.21)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(second=13.2)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
relativedelta(microsecond=157221.93)
|
||||
|
||||
def testRelativeDeltaFractionalRepr(self):
|
||||
rd = relativedelta(years=3, months=-2, days=1.25)
|
||||
|
||||
self.assertEqual(repr(rd),
|
||||
'relativedelta(years=+3, months=-2, days=+1.25)')
|
||||
|
||||
rd = relativedelta(hours=0.5, seconds=9.22)
|
||||
self.assertEqual(repr(rd),
|
||||
'relativedelta(hours=+0.5, seconds=+9.22)')
|
||||
|
||||
def testRelativeDeltaFractionalWeeks(self):
|
||||
# Equivalent to days=8, hours=18
|
||||
rd = relativedelta(weeks=1.25)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd,
|
||||
datetime(2009, 9, 11, 18))
|
||||
|
||||
def testRelativeDeltaFractionalDays(self):
|
||||
rd1 = relativedelta(days=1.48)
|
||||
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd1,
|
||||
datetime(2009, 9, 4, 11, 31, 12))
|
||||
|
||||
rd2 = relativedelta(days=1.5)
|
||||
self.assertEqual(d1 + rd2,
|
||||
datetime(2009, 9, 4, 12, 0, 0))
|
||||
|
||||
def testRelativeDeltaFractionalHours(self):
|
||||
rd = relativedelta(days=1, hours=12.5)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd,
|
||||
datetime(2009, 9, 4, 12, 30, 0))
|
||||
|
||||
def testRelativeDeltaFractionalMinutes(self):
|
||||
rd = relativedelta(hours=1, minutes=30.5)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd,
|
||||
datetime(2009, 9, 3, 1, 30, 30))
|
||||
|
||||
def testRelativeDeltaFractionalSeconds(self):
|
||||
rd = relativedelta(hours=5, minutes=30, seconds=30.5)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd,
|
||||
datetime(2009, 9, 3, 5, 30, 30, 500000))
|
||||
|
||||
def testRelativeDeltaFractionalPositiveOverflow(self):
|
||||
# Equivalent to (days=1, hours=14)
|
||||
rd1 = relativedelta(days=1.5, hours=2)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd1,
|
||||
datetime(2009, 9, 4, 14, 0, 0))
|
||||
|
||||
# Equivalent to (days=1, hours=14, minutes=45)
|
||||
rd2 = relativedelta(days=1.5, hours=2.5, minutes=15)
|
||||
d1 = datetime(2009, 9, 3, 0, 0)
|
||||
self.assertEqual(d1 + rd2,
|
||||
datetime(2009, 9, 4, 14, 45))
|
||||
|
||||
# Carry back up - equivalent to (days=2, hours=2, minutes=0, seconds=1)
|
||||
rd3 = relativedelta(days=1.5, hours=13, minutes=59.5, seconds=31)
|
||||
self.assertEqual(d1 + rd3,
|
||||
datetime(2009, 9, 5, 2, 0, 1))
|
||||
|
||||
def testRelativeDeltaFractionalNegativeDays(self):
|
||||
# Equivalent to (days=-1, hours=-1)
|
||||
rd1 = relativedelta(days=-1.5, hours=11)
|
||||
d1 = datetime(2009, 9, 3, 12, 0)
|
||||
self.assertEqual(d1 + rd1,
|
||||
datetime(2009, 9, 2, 11, 0, 0))
|
||||
|
||||
# Equivalent to (days=-1, hours=-9)
|
||||
rd2 = relativedelta(days=-1.25, hours=-3)
|
||||
self.assertEqual(d1 + rd2,
|
||||
datetime(2009, 9, 2, 3))
|
||||
|
||||
def testRelativeDeltaNormalizeFractionalDays(self):
|
||||
# Equivalent to (days=2, hours=18)
|
||||
rd1 = relativedelta(days=2.75)
|
||||
|
||||
self.assertEqual(rd1.normalized(), relativedelta(days=2, hours=18))
|
||||
|
||||
# Equvalent to (days=1, hours=11, minutes=31, seconds=12)
|
||||
rd2 = relativedelta(days=1.48)
|
||||
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(days=1, hours=11, minutes=31, seconds=12))
|
||||
|
||||
def testRelativeDeltaNormalizeFractionalDays2(self):
|
||||
# Equivalent to (hours=1, minutes=30)
|
||||
rd1 = relativedelta(hours=1.5)
|
||||
|
||||
self.assertEqual(rd1.normalized(), relativedelta(hours=1, minutes=30))
|
||||
|
||||
# Equivalent to (hours=3, minutes=17, seconds=5, microseconds=100)
|
||||
rd2 = relativedelta(hours=3.28472225)
|
||||
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(hours=3, minutes=17, seconds=5, microseconds=100))
|
||||
|
||||
def testRelativeDeltaNormalizeFractionalMinutes(self):
|
||||
# Equivalent to (minutes=15, seconds=36)
|
||||
rd1 = relativedelta(minutes=15.6)
|
||||
|
||||
self.assertEqual(rd1.normalized(),
|
||||
relativedelta(minutes=15, seconds=36))
|
||||
|
||||
# Equivalent to (minutes=25, seconds=20, microseconds=25000)
|
||||
rd2 = relativedelta(minutes=25.33375)
|
||||
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(minutes=25, seconds=20, microseconds=25000))
|
||||
|
||||
def testRelativeDeltaNormalizeFractionalSeconds(self):
|
||||
# Equivalent to (seconds=45, microseconds=25000)
|
||||
rd1 = relativedelta(seconds=45.025)
|
||||
self.assertEqual(rd1.normalized(),
|
||||
relativedelta(seconds=45, microseconds=25000))
|
||||
|
||||
def testRelativeDeltaFractionalPositiveOverflow2(self):
|
||||
# Equivalent to (days=1, hours=14)
|
||||
rd1 = relativedelta(days=1.5, hours=2)
|
||||
self.assertEqual(rd1.normalized(),
|
||||
relativedelta(days=1, hours=14))
|
||||
|
||||
# Equivalent to (days=1, hours=14, minutes=45)
|
||||
rd2 = relativedelta(days=1.5, hours=2.5, minutes=15)
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(days=1, hours=14, minutes=45))
|
||||
|
||||
# Carry back up - equivalent to:
|
||||
# (days=2, hours=2, minutes=0, seconds=2, microseconds=3)
|
||||
rd3 = relativedelta(days=1.5, hours=13, minutes=59.50045,
|
||||
seconds=31.473, microseconds=500003)
|
||||
self.assertEqual(rd3.normalized(),
|
||||
relativedelta(days=2, hours=2, minutes=0,
|
||||
seconds=2, microseconds=3))
|
||||
|
||||
def testRelativeDeltaFractionalNegativeOverflow(self):
|
||||
# Equivalent to (days=-1)
|
||||
rd1 = relativedelta(days=-0.5, hours=-12)
|
||||
self.assertEqual(rd1.normalized(),
|
||||
relativedelta(days=-1))
|
||||
|
||||
# Equivalent to (days=-1)
|
||||
rd2 = relativedelta(days=-1.5, hours=12)
|
||||
self.assertEqual(rd2.normalized(),
|
||||
relativedelta(days=-1))
|
||||
|
||||
# Equivalent to (days=-1, hours=-14, minutes=-45)
|
||||
rd3 = relativedelta(days=-1.5, hours=-2.5, minutes=-15)
|
||||
self.assertEqual(rd3.normalized(),
|
||||
relativedelta(days=-1, hours=-14, minutes=-45))
|
||||
|
||||
# Equivalent to (days=-1, hours=-14, minutes=+15)
|
||||
rd4 = relativedelta(days=-1.5, hours=-2.5, minutes=45)
|
||||
self.assertEqual(rd4.normalized(),
|
||||
relativedelta(days=-1, hours=-14, minutes=+15))
|
||||
|
||||
# Carry back up - equivalent to:
|
||||
# (days=-2, hours=-2, minutes=0, seconds=-2, microseconds=-3)
|
||||
rd3 = relativedelta(days=-1.5, hours=-13, minutes=-59.50045,
|
||||
seconds=-31.473, microseconds=-500003)
|
||||
self.assertEqual(rd3.normalized(),
|
||||
relativedelta(days=-2, hours=-2, minutes=0,
|
||||
seconds=-2, microseconds=-3))
|
||||
|
||||
def testInvalidYearDay(self):
|
||||
with self.assertRaises(ValueError):
|
||||
relativedelta(yearday=367)
|
||||
|
||||
def testAddTimedeltaToUnpopulatedRelativedelta(self):
|
||||
td = timedelta(
|
||||
days=1,
|
||||
seconds=1,
|
||||
microseconds=1,
|
||||
milliseconds=1,
|
||||
minutes=1,
|
||||
hours=1,
|
||||
weeks=1
|
||||
)
|
||||
|
||||
expected = relativedelta(
|
||||
weeks=1,
|
||||
days=1,
|
||||
hours=1,
|
||||
minutes=1,
|
||||
seconds=1,
|
||||
microseconds=1001
|
||||
)
|
||||
|
||||
self.assertEqual(expected, relativedelta() + td)
|
||||
|
||||
def testAddTimedeltaToPopulatedRelativeDelta(self):
|
||||
td = timedelta(
|
||||
days=1,
|
||||
seconds=1,
|
||||
microseconds=1,
|
||||
milliseconds=1,
|
||||
minutes=1,
|
||||
hours=1,
|
||||
weeks=1
|
||||
)
|
||||
|
||||
rd = relativedelta(
|
||||
year=1,
|
||||
month=1,
|
||||
day=1,
|
||||
hour=1,
|
||||
minute=1,
|
||||
second=1,
|
||||
microsecond=1,
|
||||
years=1,
|
||||
months=1,
|
||||
days=1,
|
||||
weeks=1,
|
||||
hours=1,
|
||||
minutes=1,
|
||||
seconds=1,
|
||||
microseconds=1
|
||||
)
|
||||
|
||||
expected = relativedelta(
|
||||
year=1,
|
||||
month=1,
|
||||
day=1,
|
||||
hour=1,
|
||||
minute=1,
|
||||
second=1,
|
||||
microsecond=1,
|
||||
years=1,
|
||||
months=1,
|
||||
weeks=2,
|
||||
days=2,
|
||||
hours=2,
|
||||
minutes=2,
|
||||
seconds=2,
|
||||
microseconds=1002,
|
||||
)
|
||||
|
||||
self.assertEqual(expected, rd + td)
|
4704
benchmark/third_party/dateutil/test/test_rrule.py
vendored
Normal file
4704
benchmark/third_party/dateutil/test/test_rrule.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2161
benchmark/third_party/dateutil/test/test_tz.py
vendored
Normal file
2161
benchmark/third_party/dateutil/test/test_tz.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
benchmark/third_party/dateutil/tz/__init__.py
vendored
Normal file
5
benchmark/third_party/dateutil/tz/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
from .tz import *
|
||||
|
||||
__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange",
|
||||
"tzstr", "tzical", "tzwin", "tzwinlocal", "gettz",
|
||||
"enfold", "datetime_ambiguous", "datetime_exists"]
|
394
benchmark/third_party/dateutil/tz/_common.py
vendored
Normal file
394
benchmark/third_party/dateutil/tz/_common.py
vendored
Normal file
@@ -0,0 +1,394 @@
|
||||
from six import PY3
|
||||
|
||||
from functools import wraps
|
||||
|
||||
from datetime import datetime, timedelta, tzinfo
|
||||
|
||||
|
||||
ZERO = timedelta(0)
|
||||
|
||||
__all__ = ['tzname_in_python2', 'enfold']
|
||||
|
||||
|
||||
def tzname_in_python2(namefunc):
|
||||
"""Change unicode output into bytestrings in Python 2
|
||||
|
||||
tzname() API changed in Python 3. It used to return bytes, but was changed
|
||||
to unicode strings
|
||||
"""
|
||||
def adjust_encoding(*args, **kwargs):
|
||||
name = namefunc(*args, **kwargs)
|
||||
if name is not None and not PY3:
|
||||
name = name.encode()
|
||||
|
||||
return name
|
||||
|
||||
return adjust_encoding
|
||||
|
||||
|
||||
# The following is adapted from Alexander Belopolsky's tz library
|
||||
# https://github.com/abalkin/tz
|
||||
if hasattr(datetime, 'fold'):
|
||||
# This is the pre-python 3.6 fold situation
|
||||
def enfold(dt, fold=1):
|
||||
"""
|
||||
Provides a unified interface for assigning the ``fold`` attribute to
|
||||
datetimes both before and after the implementation of PEP-495.
|
||||
|
||||
:param fold:
|
||||
The value for the ``fold`` attribute in the returned datetime. This
|
||||
should be either 0 or 1.
|
||||
|
||||
:return:
|
||||
Returns an object for which ``getattr(dt, 'fold', 0)`` returns
|
||||
``fold`` for all versions of Python. In versions prior to
|
||||
Python 3.6, this is a ``_DatetimeWithFold`` object, which is a
|
||||
subclass of :py:class:`datetime.datetime` with the ``fold``
|
||||
attribute added, if ``fold`` is 1.
|
||||
|
||||
.. versionadded:: 2.6.0
|
||||
"""
|
||||
return dt.replace(fold=fold)
|
||||
|
||||
else:
|
||||
class _DatetimeWithFold(datetime):
|
||||
"""
|
||||
This is a class designed to provide a PEP 495-compliant interface for
|
||||
Python versions before 3.6. It is used only for dates in a fold, so
|
||||
the ``fold`` attribute is fixed at ``1``.
|
||||
|
||||
.. versionadded:: 2.6.0
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def fold(self):
|
||||
return 1
|
||||
|
||||
def enfold(dt, fold=1):
|
||||
"""
|
||||
Provides a unified interface for assigning the ``fold`` attribute to
|
||||
datetimes both before and after the implementation of PEP-495.
|
||||
|
||||
:param fold:
|
||||
The value for the ``fold`` attribute in the returned datetime. This
|
||||
should be either 0 or 1.
|
||||
|
||||
:return:
|
||||
Returns an object for which ``getattr(dt, 'fold', 0)`` returns
|
||||
``fold`` for all versions of Python. In versions prior to
|
||||
Python 3.6, this is a ``_DatetimeWithFold`` object, which is a
|
||||
subclass of :py:class:`datetime.datetime` with the ``fold``
|
||||
attribute added, if ``fold`` is 1.
|
||||
|
||||
.. versionadded:: 2.6.0
|
||||
"""
|
||||
if getattr(dt, 'fold', 0) == fold:
|
||||
return dt
|
||||
|
||||
args = dt.timetuple()[:6]
|
||||
args += (dt.microsecond, dt.tzinfo)
|
||||
|
||||
if fold:
|
||||
return _DatetimeWithFold(*args)
|
||||
else:
|
||||
return datetime(*args)
|
||||
|
||||
|
||||
def _validate_fromutc_inputs(f):
|
||||
"""
|
||||
The CPython version of ``fromutc`` checks that the input is a ``datetime``
|
||||
object and that ``self`` is attached as its ``tzinfo``.
|
||||
"""
|
||||
@wraps(f)
|
||||
def fromutc(self, dt):
|
||||
if not isinstance(dt, datetime):
|
||||
raise TypeError("fromutc() requires a datetime argument")
|
||||
if dt.tzinfo is not self:
|
||||
raise ValueError("dt.tzinfo is not self")
|
||||
|
||||
return f(self, dt)
|
||||
|
||||
return fromutc
|
||||
|
||||
|
||||
class _tzinfo(tzinfo):
|
||||
"""
|
||||
Base class for all ``dateutil`` ``tzinfo`` objects.
|
||||
"""
|
||||
|
||||
def is_ambiguous(self, dt):
|
||||
"""
|
||||
Whether or not the "wall time" of a given datetime is ambiguous in this
|
||||
zone.
|
||||
|
||||
:param dt:
|
||||
A :py:class:`datetime.datetime`, naive or time zone aware.
|
||||
|
||||
|
||||
:return:
|
||||
Returns ``True`` if ambiguous, ``False`` otherwise.
|
||||
|
||||
.. versionadded:: 2.6.0
|
||||
"""
|
||||
|
||||
dt = dt.replace(tzinfo=self)
|
||||
|
||||
wall_0 = enfold(dt, fold=0)
|
||||
wall_1 = enfold(dt, fold=1)
|
||||
|
||||
same_offset = wall_0.utcoffset() == wall_1.utcoffset()
|
||||
same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None)
|
||||
|
||||
return same_dt and not same_offset
|
||||
|
||||
def _fold_status(self, dt_utc, dt_wall):
|
||||
"""
|
||||
Determine the fold status of a "wall" datetime, given a representation
|
||||
of the same datetime as a (naive) UTC datetime. This is calculated based
|
||||
on the assumption that ``dt.utcoffset() - dt.dst()`` is constant for all
|
||||
datetimes, and that this offset is the actual number of hours separating
|
||||
``dt_utc`` and ``dt_wall``.
|
||||
|
||||
:param dt_utc:
|
||||
Representation of the datetime as UTC
|
||||
|
||||
:param dt_wall:
|
||||
Representation of the datetime as "wall time". This parameter must
|
||||
either have a `fold` attribute or have a fold-naive
|
||||
:class:`datetime.tzinfo` attached, otherwise the calculation may
|
||||
fail.
|
||||
"""
|
||||
if self.is_ambiguous(dt_wall):
|
||||
delta_wall = dt_wall - dt_utc
|
||||
_fold = int(delta_wall == (dt_utc.utcoffset() - dt_utc.dst()))
|
||||
else:
|
||||
_fold = 0
|
||||
|
||||
return _fold
|
||||
|
||||
def _fold(self, dt):
|
||||
return getattr(dt, 'fold', 0)
|
||||
|
||||
def _fromutc(self, dt):
|
||||
"""
|
||||
Given a timezone-aware datetime in a given timezone, calculates a
|
||||
timezone-aware datetime in a new timezone.
|
||||
|
||||
Since this is the one time that we *know* we have an unambiguous
|
||||
datetime object, we take this opportunity to determine whether the
|
||||
datetime is ambiguous and in a "fold" state (e.g. if it's the first
|
||||
occurence, chronologically, of the ambiguous datetime).
|
||||
|
||||
:param dt:
|
||||
A timezone-aware :class:`datetime.datetime` object.
|
||||
"""
|
||||
|
||||
# Re-implement the algorithm from Python's datetime.py
|
||||
dtoff = dt.utcoffset()
|
||||
if dtoff is None:
|
||||
raise ValueError("fromutc() requires a non-None utcoffset() "
|
||||
"result")
|
||||
|
||||
# The original datetime.py code assumes that `dst()` defaults to
|
||||
# zero during ambiguous times. PEP 495 inverts this presumption, so
|
||||
# for pre-PEP 495 versions of python, we need to tweak the algorithm.
|
||||
dtdst = dt.dst()
|
||||
if dtdst is None:
|
||||
raise ValueError("fromutc() requires a non-None dst() result")
|
||||
delta = dtoff - dtdst
|
||||
|
||||
dt += delta
|
||||
# Set fold=1 so we can default to being in the fold for
|
||||
# ambiguous dates.
|
||||
dtdst = enfold(dt, fold=1).dst()
|
||||
if dtdst is None:
|
||||
raise ValueError("fromutc(): dt.dst gave inconsistent "
|
||||
"results; cannot convert")
|
||||
return dt + dtdst
|
||||
|
||||
@_validate_fromutc_inputs
|
||||
def fromutc(self, dt):
|
||||
"""
|
||||
Given a timezone-aware datetime in a given timezone, calculates a
|
||||
timezone-aware datetime in a new timezone.
|
||||
|
||||
Since this is the one time that we *know* we have an unambiguous
|
||||
datetime object, we take this opportunity to determine whether the
|
||||
datetime is ambiguous and in a "fold" state (e.g. if it's the first
|
||||
occurance, chronologically, of the ambiguous datetime).
|
||||
|
||||
:param dt:
|
||||
A timezone-aware :class:`datetime.datetime` object.
|
||||
"""
|
||||
dt_wall = self._fromutc(dt)
|
||||
|
||||
# Calculate the fold status given the two datetimes.
|
||||
_fold = self._fold_status(dt, dt_wall)
|
||||
|
||||
# Set the default fold value for ambiguous dates
|
||||
return enfold(dt_wall, fold=_fold)
|
||||
|
||||
|
||||
class tzrangebase(_tzinfo):
|
||||
"""
|
||||
This is an abstract base class for time zones represented by an annual
|
||||
transition into and out of DST. Child classes should implement the following
|
||||
methods:
|
||||
|
||||
* ``__init__(self, *args, **kwargs)``
|
||||
* ``transitions(self, year)`` - this is expected to return a tuple of
|
||||
datetimes representing the DST on and off transitions in standard
|
||||
time.
|
||||
|
||||
A fully initialized ``tzrangebase`` subclass should also provide the
|
||||
following attributes:
|
||||
* ``hasdst``: Boolean whether or not the zone uses DST.
|
||||
* ``_dst_offset`` / ``_std_offset``: :class:`datetime.timedelta` objects
|
||||
representing the respective UTC offsets.
|
||||
* ``_dst_abbr`` / ``_std_abbr``: Strings representing the timezone short
|
||||
abbreviations in DST and STD, respectively.
|
||||
* ``_hasdst``: Whether or not the zone has DST.
|
||||
|
||||
.. versionadded:: 2.6.0
|
||||
"""
|
||||
def __init__(self):
|
||||
raise NotImplementedError('tzrangebase is an abstract base class')
|
||||
|
||||
def utcoffset(self, dt):
|
||||
isdst = self._isdst(dt)
|
||||
|
||||
if isdst is None:
|
||||
return None
|
||||
elif isdst:
|
||||
return self._dst_offset
|
||||
else:
|
||||
return self._std_offset
|
||||
|
||||
def dst(self, dt):
|
||||
isdst = self._isdst(dt)
|
||||
|
||||
if isdst is None:
|
||||
return None
|
||||
elif isdst:
|
||||
return self._dst_base_offset
|
||||
else:
|
||||
return ZERO
|
||||
|
||||
@tzname_in_python2
|
||||
def tzname(self, dt):
|
||||
if self._isdst(dt):
|
||||
return self._dst_abbr
|
||||
else:
|
||||
return self._std_abbr
|
||||
|
||||
def fromutc(self, dt):
|
||||
""" Given a datetime in UTC, return local time """
|
||||
if not isinstance(dt, datetime):
|
||||
raise TypeError("fromutc() requires a datetime argument")
|
||||
|
||||
if dt.tzinfo is not self:
|
||||
raise ValueError("dt.tzinfo is not self")
|
||||
|
||||
# Get transitions - if there are none, fixed offset
|
||||
transitions = self.transitions(dt.year)
|
||||
if transitions is None:
|
||||
return dt + self.utcoffset(dt)
|
||||
|
||||
# Get the transition times in UTC
|
||||
dston, dstoff = transitions
|
||||
|
||||
dston -= self._std_offset
|
||||
dstoff -= self._std_offset
|
||||
|
||||
utc_transitions = (dston, dstoff)
|
||||
dt_utc = dt.replace(tzinfo=None)
|
||||
|
||||
isdst = self._naive_isdst(dt_utc, utc_transitions)
|
||||
|
||||
if isdst:
|
||||
dt_wall = dt + self._dst_offset
|
||||
else:
|
||||
dt_wall = dt + self._std_offset
|
||||
|
||||
_fold = int(not isdst and self.is_ambiguous(dt_wall))
|
||||
|
||||
return enfold(dt_wall, fold=_fold)
|
||||
|
||||
def is_ambiguous(self, dt):
|
||||
"""
|
||||
Whether or not the "wall time" of a given datetime is ambiguous in this
|
||||
zone.
|
||||
|
||||
:param dt:
|
||||
A :py:class:`datetime.datetime`, naive or time zone aware.
|
||||
|
||||
|
||||
:return:
|
||||
Returns ``True`` if ambiguous, ``False`` otherwise.
|
||||
|
||||
.. versionadded:: 2.6.0
|
||||
"""
|
||||
if not self.hasdst:
|
||||
return False
|
||||
|
||||
start, end = self.transitions(dt.year)
|
||||
|
||||
dt = dt.replace(tzinfo=None)
|
||||
return (end <= dt < end + self._dst_base_offset)
|
||||
|
||||
def _isdst(self, dt):
|
||||
if not self.hasdst:
|
||||
return False
|
||||
elif dt is None:
|
||||
return None
|
||||
|
||||
transitions = self.transitions(dt.year)
|
||||
|
||||
if transitions is None:
|
||||
return False
|
||||
|
||||
dt = dt.replace(tzinfo=None)
|
||||
|
||||
isdst = self._naive_isdst(dt, transitions)
|
||||
|
||||
# Handle ambiguous dates
|
||||
if not isdst and self.is_ambiguous(dt):
|
||||
return not self._fold(dt)
|
||||
else:
|
||||
return isdst
|
||||
|
||||
def _naive_isdst(self, dt, transitions):
|
||||
dston, dstoff = transitions
|
||||
|
||||
dt = dt.replace(tzinfo=None)
|
||||
|
||||
if dston < dstoff:
|
||||
isdst = dston <= dt < dstoff
|
||||
else:
|
||||
isdst = not dstoff <= dt < dston
|
||||
|
||||
return isdst
|
||||
|
||||
@property
|
||||
def _dst_base_offset(self):
|
||||
return self._dst_offset - self._std_offset
|
||||
|
||||
__hash__ = None
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(...)" % self.__class__.__name__
|
||||
|
||||
__reduce__ = object.__reduce__
|
||||
|
||||
|
||||
def _total_seconds(td):
|
||||
# Python 2.6 doesn't have a total_seconds() method on timedelta objects
|
||||
return ((td.seconds + td.days * 86400) * 1000000 +
|
||||
td.microseconds) // 1000000
|
||||
|
||||
|
||||
_total_seconds = getattr(timedelta, 'total_seconds', _total_seconds)
|
1511
benchmark/third_party/dateutil/tz/tz.py
vendored
Normal file
1511
benchmark/third_party/dateutil/tz/tz.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
332
benchmark/third_party/dateutil/tz/win.py
vendored
Normal file
332
benchmark/third_party/dateutil/tz/win.py
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
# This code was originally contributed by Jeffrey Harris.
|
||||
import datetime
|
||||
import struct
|
||||
|
||||
from six.moves import winreg
|
||||
from six import text_type
|
||||
|
||||
try:
|
||||
import ctypes
|
||||
from ctypes import wintypes
|
||||
except ValueError:
|
||||
# ValueError is raised on non-Windows systems for some horrible reason.
|
||||
raise ImportError("Running tzwin on non-Windows system")
|
||||
|
||||
from ._common import tzrangebase
|
||||
|
||||
__all__ = ["tzwin", "tzwinlocal", "tzres"]
|
||||
|
||||
ONEWEEK = datetime.timedelta(7)
|
||||
|
||||
TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
|
||||
TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones"
|
||||
TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
|
||||
|
||||
|
||||
def _settzkeyname():
|
||||
handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
|
||||
try:
|
||||
winreg.OpenKey(handle, TZKEYNAMENT).Close()
|
||||
TZKEYNAME = TZKEYNAMENT
|
||||
except WindowsError:
|
||||
TZKEYNAME = TZKEYNAME9X
|
||||
handle.Close()
|
||||
return TZKEYNAME
|
||||
|
||||
|
||||
TZKEYNAME = _settzkeyname()
|
||||
|
||||
|
||||
class tzres(object):
|
||||
"""
|
||||
Class for accessing `tzres.dll`, which contains timezone name related
|
||||
resources.
|
||||
|
||||
.. versionadded:: 2.5.0
|
||||
"""
|
||||
p_wchar = ctypes.POINTER(wintypes.WCHAR) # Pointer to a wide char
|
||||
|
||||
def __init__(self, tzres_loc='tzres.dll'):
|
||||
# Load the user32 DLL so we can load strings from tzres
|
||||
user32 = ctypes.WinDLL('user32')
|
||||
|
||||
# Specify the LoadStringW function
|
||||
user32.LoadStringW.argtypes = (wintypes.HINSTANCE,
|
||||
wintypes.UINT,
|
||||
wintypes.LPWSTR,
|
||||
ctypes.c_int)
|
||||
|
||||
self.LoadStringW = user32.LoadStringW
|
||||
self._tzres = ctypes.WinDLL(tzres_loc)
|
||||
self.tzres_loc = tzres_loc
|
||||
|
||||
def load_name(self, offset):
|
||||
"""
|
||||
Load a timezone name from a DLL offset (integer).
|
||||
|
||||
>>> from dateutil.tzwin import tzres
|
||||
>>> tzr = tzres()
|
||||
>>> print(tzr.load_name(112))
|
||||
'Eastern Standard Time'
|
||||
|
||||
:param offset:
|
||||
A positive integer value referring to a string from the tzres dll.
|
||||
|
||||
..note:
|
||||
Offsets found in the registry are generally of the form
|
||||
`@tzres.dll,-114`. The offset in this case if 114, not -114.
|
||||
|
||||
"""
|
||||
resource = self.p_wchar()
|
||||
lpBuffer = ctypes.cast(ctypes.byref(resource), wintypes.LPWSTR)
|
||||
nchar = self.LoadStringW(self._tzres._handle, offset, lpBuffer, 0)
|
||||
return resource[:nchar]
|
||||
|
||||
def name_from_string(self, tzname_str):
|
||||
"""
|
||||
Parse strings as returned from the Windows registry into the time zone
|
||||
name as defined in the registry.
|
||||
|
||||
>>> from dateutil.tzwin import tzres
|
||||
>>> tzr = tzres()
|
||||
>>> print(tzr.name_from_string('@tzres.dll,-251'))
|
||||
'Dateline Daylight Time'
|
||||
>>> print(tzr.name_from_string('Eastern Standard Time'))
|
||||
'Eastern Standard Time'
|
||||
|
||||
:param tzname_str:
|
||||
A timezone name string as returned from a Windows registry key.
|
||||
|
||||
:return:
|
||||
Returns the localized timezone string from tzres.dll if the string
|
||||
is of the form `@tzres.dll,-offset`, else returns the input string.
|
||||
"""
|
||||
if not tzname_str.startswith('@'):
|
||||
return tzname_str
|
||||
|
||||
name_splt = tzname_str.split(',-')
|
||||
try:
|
||||
offset = int(name_splt[1])
|
||||
except:
|
||||
raise ValueError("Malformed timezone string.")
|
||||
|
||||
return self.load_name(offset)
|
||||
|
||||
|
||||
class tzwinbase(tzrangebase):
|
||||
"""tzinfo class based on win32's timezones available in the registry."""
|
||||
def __init__(self):
|
||||
raise NotImplementedError('tzwinbase is an abstract base class')
|
||||
|
||||
def __eq__(self, other):
|
||||
# Compare on all relevant dimensions, including name.
|
||||
if not isinstance(other, tzwinbase):
|
||||
return NotImplemented
|
||||
|
||||
return (self._std_offset == other._std_offset and
|
||||
self._dst_offset == other._dst_offset and
|
||||
self._stddayofweek == other._stddayofweek and
|
||||
self._dstdayofweek == other._dstdayofweek and
|
||||
self._stdweeknumber == other._stdweeknumber and
|
||||
self._dstweeknumber == other._dstweeknumber and
|
||||
self._stdhour == other._stdhour and
|
||||
self._dsthour == other._dsthour and
|
||||
self._stdminute == other._stdminute and
|
||||
self._dstminute == other._dstminute and
|
||||
self._std_abbr == other._std_abbr and
|
||||
self._dst_abbr == other._dst_abbr)
|
||||
|
||||
@staticmethod
|
||||
def list():
|
||||
"""Return a list of all time zones known to the system."""
|
||||
with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle:
|
||||
with winreg.OpenKey(handle, TZKEYNAME) as tzkey:
|
||||
result = [winreg.EnumKey(tzkey, i)
|
||||
for i in range(winreg.QueryInfoKey(tzkey)[0])]
|
||||
return result
|
||||
|
||||
def display(self):
|
||||
return self._display
|
||||
|
||||
def transitions(self, year):
|
||||
"""
|
||||
For a given year, get the DST on and off transition times, expressed
|
||||
always on the standard time side. For zones with no transitions, this
|
||||
function returns ``None``.
|
||||
|
||||
:param year:
|
||||
The year whose transitions you would like to query.
|
||||
|
||||
:return:
|
||||
Returns a :class:`tuple` of :class:`datetime.datetime` objects,
|
||||
``(dston, dstoff)`` for zones with an annual DST transition, or
|
||||
``None`` for fixed offset zones.
|
||||
"""
|
||||
|
||||
if not self.hasdst:
|
||||
return None
|
||||
|
||||
dston = picknthweekday(year, self._dstmonth, self._dstdayofweek,
|
||||
self._dsthour, self._dstminute,
|
||||
self._dstweeknumber)
|
||||
|
||||
dstoff = picknthweekday(year, self._stdmonth, self._stddayofweek,
|
||||
self._stdhour, self._stdminute,
|
||||
self._stdweeknumber)
|
||||
|
||||
# Ambiguous dates default to the STD side
|
||||
dstoff -= self._dst_base_offset
|
||||
|
||||
return dston, dstoff
|
||||
|
||||
def _get_hasdst(self):
|
||||
return self._dstmonth != 0
|
||||
|
||||
@property
|
||||
def _dst_base_offset(self):
|
||||
return self._dst_base_offset_
|
||||
|
||||
|
||||
class tzwin(tzwinbase):
|
||||
|
||||
def __init__(self, name):
|
||||
self._name = name
|
||||
|
||||
# multiple contexts only possible in 2.7 and 3.1, we still support 2.6
|
||||
with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle:
|
||||
tzkeyname = text_type("{kn}\\{name}").format(kn=TZKEYNAME, name=name)
|
||||
with winreg.OpenKey(handle, tzkeyname) as tzkey:
|
||||
keydict = valuestodict(tzkey)
|
||||
|
||||
self._std_abbr = keydict["Std"]
|
||||
self._dst_abbr = keydict["Dlt"]
|
||||
|
||||
self._display = keydict["Display"]
|
||||
|
||||
# See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm
|
||||
tup = struct.unpack("=3l16h", keydict["TZI"])
|
||||
stdoffset = -tup[0]-tup[1] # Bias + StandardBias * -1
|
||||
dstoffset = stdoffset-tup[2] # + DaylightBias * -1
|
||||
self._std_offset = datetime.timedelta(minutes=stdoffset)
|
||||
self._dst_offset = datetime.timedelta(minutes=dstoffset)
|
||||
|
||||
# for the meaning see the win32 TIME_ZONE_INFORMATION structure docs
|
||||
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
|
||||
(self._stdmonth,
|
||||
self._stddayofweek, # Sunday = 0
|
||||
self._stdweeknumber, # Last = 5
|
||||
self._stdhour,
|
||||
self._stdminute) = tup[4:9]
|
||||
|
||||
(self._dstmonth,
|
||||
self._dstdayofweek, # Sunday = 0
|
||||
self._dstweeknumber, # Last = 5
|
||||
self._dsthour,
|
||||
self._dstminute) = tup[12:17]
|
||||
|
||||
self._dst_base_offset_ = self._dst_offset - self._std_offset
|
||||
self.hasdst = self._get_hasdst()
|
||||
|
||||
def __repr__(self):
|
||||
return "tzwin(%s)" % repr(self._name)
|
||||
|
||||
def __reduce__(self):
|
||||
return (self.__class__, (self._name,))
|
||||
|
||||
|
||||
class tzwinlocal(tzwinbase):
|
||||
def __init__(self):
|
||||
with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle:
|
||||
with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey:
|
||||
keydict = valuestodict(tzlocalkey)
|
||||
|
||||
self._std_abbr = keydict["StandardName"]
|
||||
self._dst_abbr = keydict["DaylightName"]
|
||||
|
||||
try:
|
||||
tzkeyname = text_type('{kn}\\{sn}').format(kn=TZKEYNAME,
|
||||
sn=self._std_abbr)
|
||||
with winreg.OpenKey(handle, tzkeyname) as tzkey:
|
||||
_keydict = valuestodict(tzkey)
|
||||
self._display = _keydict["Display"]
|
||||
except OSError:
|
||||
self._display = None
|
||||
|
||||
stdoffset = -keydict["Bias"]-keydict["StandardBias"]
|
||||
dstoffset = stdoffset-keydict["DaylightBias"]
|
||||
|
||||
self._std_offset = datetime.timedelta(minutes=stdoffset)
|
||||
self._dst_offset = datetime.timedelta(minutes=dstoffset)
|
||||
|
||||
# For reasons unclear, in this particular key, the day of week has been
|
||||
# moved to the END of the SYSTEMTIME structure.
|
||||
tup = struct.unpack("=8h", keydict["StandardStart"])
|
||||
|
||||
(self._stdmonth,
|
||||
self._stdweeknumber, # Last = 5
|
||||
self._stdhour,
|
||||
self._stdminute) = tup[1:5]
|
||||
|
||||
self._stddayofweek = tup[7]
|
||||
|
||||
tup = struct.unpack("=8h", keydict["DaylightStart"])
|
||||
|
||||
(self._dstmonth,
|
||||
self._dstweeknumber, # Last = 5
|
||||
self._dsthour,
|
||||
self._dstminute) = tup[1:5]
|
||||
|
||||
self._dstdayofweek = tup[7]
|
||||
|
||||
self._dst_base_offset_ = self._dst_offset - self._std_offset
|
||||
self.hasdst = self._get_hasdst()
|
||||
|
||||
def __repr__(self):
|
||||
return "tzwinlocal()"
|
||||
|
||||
def __str__(self):
|
||||
# str will return the standard name, not the daylight name.
|
||||
return "tzwinlocal(%s)" % repr(self._std_abbr)
|
||||
|
||||
def __reduce__(self):
|
||||
return (self.__class__, ())
|
||||
|
||||
|
||||
def picknthweekday(year, month, dayofweek, hour, minute, whichweek):
|
||||
""" dayofweek == 0 means Sunday, whichweek 5 means last instance """
|
||||
first = datetime.datetime(year, month, 1, hour, minute)
|
||||
|
||||
# This will work if dayofweek is ISO weekday (1-7) or Microsoft-style (0-6),
|
||||
# Because 7 % 7 = 0
|
||||
weekdayone = first.replace(day=((dayofweek - first.isoweekday()) % 7) + 1)
|
||||
wd = weekdayone + ((whichweek - 1) * ONEWEEK)
|
||||
if (wd.month != month):
|
||||
wd -= ONEWEEK
|
||||
|
||||
return wd
|
||||
|
||||
|
||||
def valuestodict(key):
|
||||
"""Convert a registry key's values to a dictionary."""
|
||||
dout = {}
|
||||
size = winreg.QueryInfoKey(key)[1]
|
||||
tz_res = None
|
||||
|
||||
for i in range(size):
|
||||
key_name, value, dtype = winreg.EnumValue(key, i)
|
||||
if dtype == winreg.REG_DWORD or dtype == winreg.REG_DWORD_LITTLE_ENDIAN:
|
||||
# If it's a DWORD (32-bit integer), it's stored as unsigned - convert
|
||||
# that to a proper signed integer
|
||||
if value & (1 << 31):
|
||||
value = value - (1 << 32)
|
||||
elif dtype == winreg.REG_SZ:
|
||||
# If it's a reference to the tzres DLL, load the actual string
|
||||
if value.startswith('@tzres'):
|
||||
tz_res = tz_res or tzres()
|
||||
value = tz_res.name_from_string(value)
|
||||
|
||||
value = value.rstrip('\x00') # Remove trailing nulls
|
||||
|
||||
dout[key_name] = value
|
||||
|
||||
return dout
|
2
benchmark/third_party/dateutil/tzwin.py
vendored
Normal file
2
benchmark/third_party/dateutil/tzwin.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# tzwin has moved to dateutil.tz.win
|
||||
from .tz.win import *
|
183
benchmark/third_party/dateutil/zoneinfo/__init__.py
vendored
Normal file
183
benchmark/third_party/dateutil/zoneinfo/__init__.py
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import warnings
|
||||
import json
|
||||
|
||||
from tarfile import TarFile
|
||||
from pkgutil import get_data
|
||||
from io import BytesIO
|
||||
from contextlib import closing
|
||||
|
||||
from dateutil.tz import tzfile
|
||||
|
||||
__all__ = ["get_zonefile_instance", "gettz", "gettz_db_metadata", "rebuild"]
|
||||
|
||||
ZONEFILENAME = "dateutil-zoneinfo.tar.gz"
|
||||
METADATA_FN = 'METADATA'
|
||||
|
||||
# python2.6 compatability. Note that TarFile.__exit__ != TarFile.close, but
|
||||
# it's close enough for python2.6
|
||||
tar_open = TarFile.open
|
||||
if not hasattr(TarFile, '__exit__'):
|
||||
def tar_open(*args, **kwargs):
|
||||
return closing(TarFile.open(*args, **kwargs))
|
||||
|
||||
|
||||
class tzfile(tzfile):
|
||||
def __reduce__(self):
|
||||
return (gettz, (self._filename,))
|
||||
|
||||
|
||||
def getzoneinfofile_stream():
|
||||
try:
|
||||
return BytesIO(get_data(__name__, ZONEFILENAME))
|
||||
except IOError as e: # TODO switch to FileNotFoundError?
|
||||
warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror))
|
||||
return None
|
||||
|
||||
|
||||
class ZoneInfoFile(object):
|
||||
def __init__(self, zonefile_stream=None):
|
||||
if zonefile_stream is not None:
|
||||
with tar_open(fileobj=zonefile_stream, mode='r') as tf:
|
||||
# dict comprehension does not work on python2.6
|
||||
# TODO: get back to the nicer syntax when we ditch python2.6
|
||||
# self.zones = {zf.name: tzfile(tf.extractfile(zf),
|
||||
# filename = zf.name)
|
||||
# for zf in tf.getmembers() if zf.isfile()}
|
||||
self.zones = dict((zf.name, tzfile(tf.extractfile(zf),
|
||||
filename=zf.name))
|
||||
for zf in tf.getmembers()
|
||||
if zf.isfile() and zf.name != METADATA_FN)
|
||||
# deal with links: They'll point to their parent object. Less
|
||||
# waste of memory
|
||||
# links = {zl.name: self.zones[zl.linkname]
|
||||
# for zl in tf.getmembers() if zl.islnk() or zl.issym()}
|
||||
links = dict((zl.name, self.zones[zl.linkname])
|
||||
for zl in tf.getmembers() if
|
||||
zl.islnk() or zl.issym())
|
||||
self.zones.update(links)
|
||||
try:
|
||||
metadata_json = tf.extractfile(tf.getmember(METADATA_FN))
|
||||
metadata_str = metadata_json.read().decode('UTF-8')
|
||||
self.metadata = json.loads(metadata_str)
|
||||
except KeyError:
|
||||
# no metadata in tar file
|
||||
self.metadata = None
|
||||
else:
|
||||
self.zones = dict()
|
||||
self.metadata = None
|
||||
|
||||
def get(self, name, default=None):
|
||||
"""
|
||||
Wrapper for :func:`ZoneInfoFile.zones.get`. This is a convenience method
|
||||
for retrieving zones from the zone dictionary.
|
||||
|
||||
:param name:
|
||||
The name of the zone to retrieve. (Generally IANA zone names)
|
||||
|
||||
:param default:
|
||||
The value to return in the event of a missing key.
|
||||
|
||||
.. versionadded:: 2.6.0
|
||||
|
||||
"""
|
||||
return self.zones.get(name, default)
|
||||
|
||||
|
||||
# The current API has gettz as a module function, although in fact it taps into
|
||||
# a stateful class. So as a workaround for now, without changing the API, we
|
||||
# will create a new "global" class instance the first time a user requests a
|
||||
# timezone. Ugly, but adheres to the api.
|
||||
#
|
||||
# TODO: Remove after deprecation period.
|
||||
_CLASS_ZONE_INSTANCE = list()
|
||||
|
||||
|
||||
def get_zonefile_instance(new_instance=False):
|
||||
"""
|
||||
This is a convenience function which provides a :class:`ZoneInfoFile`
|
||||
instance using the data provided by the ``dateutil`` package. By default, it
|
||||
caches a single instance of the ZoneInfoFile object and returns that.
|
||||
|
||||
:param new_instance:
|
||||
If ``True``, a new instance of :class:`ZoneInfoFile` is instantiated and
|
||||
used as the cached instance for the next call. Otherwise, new instances
|
||||
are created only as necessary.
|
||||
|
||||
:return:
|
||||
Returns a :class:`ZoneInfoFile` object.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
"""
|
||||
if new_instance:
|
||||
zif = None
|
||||
else:
|
||||
zif = getattr(get_zonefile_instance, '_cached_instance', None)
|
||||
|
||||
if zif is None:
|
||||
zif = ZoneInfoFile(getzoneinfofile_stream())
|
||||
|
||||
get_zonefile_instance._cached_instance = zif
|
||||
|
||||
return zif
|
||||
|
||||
|
||||
def gettz(name):
|
||||
"""
|
||||
This retrieves a time zone from the local zoneinfo tarball that is packaged
|
||||
with dateutil.
|
||||
|
||||
:param name:
|
||||
An IANA-style time zone name, as found in the zoneinfo file.
|
||||
|
||||
:return:
|
||||
Returns a :class:`dateutil.tz.tzfile` time zone object.
|
||||
|
||||
.. warning::
|
||||
It is generally inadvisable to use this function, and it is only
|
||||
provided for API compatibility with earlier versions. This is *not*
|
||||
equivalent to ``dateutil.tz.gettz()``, which selects an appropriate
|
||||
time zone based on the inputs, favoring system zoneinfo. This is ONLY
|
||||
for accessing the dateutil-specific zoneinfo (which may be out of
|
||||
date compared to the system zoneinfo).
|
||||
|
||||
.. deprecated:: 2.6
|
||||
If you need to use a specific zoneinfofile over the system zoneinfo,
|
||||
instantiate a :class:`dateutil.zoneinfo.ZoneInfoFile` object and call
|
||||
:func:`dateutil.zoneinfo.ZoneInfoFile.get(name)` instead.
|
||||
|
||||
Use :func:`get_zonefile_instance` to retrieve an instance of the
|
||||
dateutil-provided zoneinfo.
|
||||
"""
|
||||
warnings.warn("zoneinfo.gettz() will be removed in future versions, "
|
||||
"to use the dateutil-provided zoneinfo files, instantiate a "
|
||||
"ZoneInfoFile object and use ZoneInfoFile.zones.get() "
|
||||
"instead. See the documentation for details.",
|
||||
DeprecationWarning)
|
||||
|
||||
if len(_CLASS_ZONE_INSTANCE) == 0:
|
||||
_CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream()))
|
||||
return _CLASS_ZONE_INSTANCE[0].zones.get(name)
|
||||
|
||||
|
||||
def gettz_db_metadata():
|
||||
""" Get the zonefile metadata
|
||||
|
||||
See `zonefile_metadata`_
|
||||
|
||||
:returns:
|
||||
A dictionary with the database metadata
|
||||
|
||||
.. deprecated:: 2.6
|
||||
See deprecation warning in :func:`zoneinfo.gettz`. To get metadata,
|
||||
query the attribute ``zoneinfo.ZoneInfoFile.metadata``.
|
||||
"""
|
||||
warnings.warn("zoneinfo.gettz_db_metadata() will be removed in future "
|
||||
"versions, to use the dateutil-provided zoneinfo files, "
|
||||
"ZoneInfoFile object and query the 'metadata' attribute "
|
||||
"instead. See the documentation for details.",
|
||||
DeprecationWarning)
|
||||
|
||||
if len(_CLASS_ZONE_INSTANCE) == 0:
|
||||
_CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream()))
|
||||
return _CLASS_ZONE_INSTANCE[0].metadata
|
BIN
benchmark/third_party/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz
vendored
Normal file
BIN
benchmark/third_party/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz
vendored
Normal file
Binary file not shown.
52
benchmark/third_party/dateutil/zoneinfo/rebuild.py
vendored
Normal file
52
benchmark/third_party/dateutil/zoneinfo/rebuild.py
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import shutil
|
||||
import json
|
||||
from subprocess import check_call
|
||||
|
||||
from dateutil.zoneinfo import tar_open, METADATA_FN, ZONEFILENAME
|
||||
|
||||
|
||||
def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None):
|
||||
"""Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar*
|
||||
|
||||
filename is the timezone tarball from ftp.iana.org/tz.
|
||||
|
||||
"""
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
zonedir = os.path.join(tmpdir, "zoneinfo")
|
||||
moduledir = os.path.dirname(__file__)
|
||||
try:
|
||||
with tar_open(filename) as tf:
|
||||
for name in zonegroups:
|
||||
tf.extract(name, tmpdir)
|
||||
filepaths = [os.path.join(tmpdir, n) for n in zonegroups]
|
||||
try:
|
||||
check_call(["zic", "-d", zonedir] + filepaths)
|
||||
except OSError as e:
|
||||
_print_on_nosuchfile(e)
|
||||
raise
|
||||
# write metadata file
|
||||
with open(os.path.join(zonedir, METADATA_FN), 'w') as f:
|
||||
json.dump(metadata, f, indent=4, sort_keys=True)
|
||||
target = os.path.join(moduledir, ZONEFILENAME)
|
||||
with tar_open(target, "w:%s" % format) as tf:
|
||||
for entry in os.listdir(zonedir):
|
||||
entrypath = os.path.join(zonedir, entry)
|
||||
tf.add(entrypath, entry)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
|
||||
def _print_on_nosuchfile(e):
|
||||
"""Print helpful troubleshooting message
|
||||
|
||||
e is an exception raised by subprocess.check_call()
|
||||
|
||||
"""
|
||||
if e.errno == 2:
|
||||
logging.error(
|
||||
"Could not find zic. Perhaps you need to install "
|
||||
"libc-bin or some other package that provides it, "
|
||||
"or it's not in your PATH?")
|
Reference in New Issue
Block a user