🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

python-dateutil

Package Overview
Dependencies
Maintainers
4
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

python-dateutil - pypi Package Compare versions

Comparing version
2.5.0
to
2.5.1
dateutil/test/__init__.py
+102
from __future__ import unicode_literals
try:
import unittest2 as unittest
except ImportError:
import unittest
import os
import subprocess
import warnings
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 TZWinContext(object):
""" Context manager for changing local time zone on Windows """
@classmethod
def tz_change_allowed(cls):
# Allowing dateutil to change the local TZ is set as a local environment
# flag.
return bool(os.environ.get('DATEUTIL_MAY_CHANGE_TZ', False))
def __init__(self, tzname):
self.tzname = tzname
self._old_tz = None
def __enter__(self):
if not self.tz_change_allowed():
raise ValueError('Environment variable DATEUTIL_MAY_CHANGE_TZ ' +
'must be true.')
self._old_tz = self.get_current_tz()
self.set_current_tz(self.tzname)
def __exit__(self, type, value, traceback):
if self._old_tz is not None:
self.set_current_tz(self._old_tz)
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.'))
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)
import sys
try:
import unittest2 as unittest
except ImportError:
import unittest
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):
tzwin_all = ["tzwin", "tzwinlocal"]
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)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from ._common import unittest
from datetime import datetime, timedelta, date
from dateutil.tz import tzoffset
from dateutil.parser import *
from six import assertRaisesRegex, PY3
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
base_str = '2014-05-01 08:00:00'
try:
# Python 2.x
self.uni_str = unicode(base_str)
self.str_str = str(base_str)
except NameError:
self.uni_str = str(base_str)
self.str_str = bytes(base_str.encode())
def testEmptyString(self):
with self.assertRaises(ValueError):
parse('')
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 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):
s = "Today is 25 of September of 2003, exactly " \
"at 10:49:41 with timezone -03:00."
self.assertEqual(parse(s, fuzzy_with_tokens=True),
(datetime(2003, 9, 25, 10, 49, 41,
tzinfo=self.brsttz),
('Today is ', 'of ', ', exactly at ',
' with timezone ', '.')))
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 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))
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from ._common import unittest, WarningTestMixin
import calendar
from datetime import datetime, date
from dateutil.relativedelta import *
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 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 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 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 testDivision(self):
self.assertEqual(datetime(2000, 1, 1) + relativedelta(days=28) / 28,
datetime(2000, 1, 2))
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 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 testRelativeDeltaNormalizeFractionalDays(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 testRelativeDeltaFractionalPositiveOverflow(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)

Sorry, the diff of this file is too big to display

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from ._common import unittest, TZWinContext
from datetime import datetime, timedelta
from datetime import time as dt_time
from six import BytesIO, StringIO
import os
import subprocess
import sys
import time as _time
import base64
IS_WIN = sys.platform.startswith('win')
# dateutil imports
from dateutil.relativedelta import relativedelta
from dateutil.parser import parse
from dateutil import tz as tz
from dateutil import zoneinfo
try:
from dateutil import tzwin
except ImportError as e:
if IS_WIN:
raise e
else:
pass
MISSING_TARBALL = ("This test fails if you don't have the dateutil "
"timezone file installed. Please read the README")
TZFILE_EST5EDT = b"""
VFppZgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAADrAAAABAAAABCeph5wn7rrYKCGAHCh
ms1gomXicKOD6eCkaq5wpTWnYKZTyvCnFYlgqDOs8Kj+peCqE47wqt6H4KvzcPCsvmngrdNS8K6e
S+CvszTwsH4t4LGcUXCyZ0pgs3wzcLRHLGC1XBVwticOYLc793C4BvBguRvZcLnm0mC7BPXwu8a0
YLzk1/C9r9DgvsS58L+PsuDApJvwwW+U4MKEffDDT3bgxGRf8MUvWODGTXxwxw864MgtXnDI+Fdg
yg1AcMrYOWDLiPBw0iP0cNJg++DTdeTw1EDd4NVVxvDWIL/g1zWo8NgAoeDZFYrw2eCD4Nr+p3Db
wGXg3N6JcN2pgmDevmtw34lkYOCeTXDhaUZg4n4vcONJKGDkXhFw5Vcu4OZHLfDnNxDg6CcP8OkW
8uDqBvHw6vbU4Ovm0/Ds1rbg7ca18O6/02Dvr9Jw8J+1YPGPtHDyf5dg82+WcPRfeWD1T3hw9j9b
YPcvWnD4KHfg+Q88cPoIWeD6+Fjw++g74PzYOvD9yB3g/rgc8P+n/+AAl/7wAYfh4AJ34PADcP5g
BGD9cAVQ4GAGQN9wBzDCYAeNGXAJEKRgCa2U8ArwhmAL4IVwDNmi4A3AZ3AOuYTgD6mD8BCZZuAR
iWXwEnlI4BNpR/AUWSrgFUkp8BY5DOAXKQvwGCIpYBkI7fAaAgtgGvIKcBvh7WAc0exwHcHPYB6x
znAfobFgIHYA8CGBk2AiVeLwI2qv4CQ1xPAlSpHgJhWm8Ccqc+An/sNwKQpV4CnepXAq6jfgK76H
cCzTVGAtnmlwLrM2YC9+S3AwkxhgMWdn8DJy+mAzR0nwNFLcYDUnK/A2Mr5gNwcN8Dgb2uA45u/w
Ofu84DrG0fA7257gPK/ucD27gOA+j9BwP5ti4EBvsnBBhH9gQk+UcENkYWBEL3ZwRURDYEYPWHBH
JCVgR/h08EkEB2BJ2FbwSuPpYEu4OPBMzQXgTZga8E6s5+BPd/zwUIzJ4FFhGXBSbKvgU0D7cFRM
jeBVIN1wVixv4FcAv3BYFYxgWOChcFn1bmBawINwW9VQYFypn/BdtTJgXomB8F+VFGBgaWPwYX4w
4GJJRfBjXhLgZCkn8GU99OBmEkRwZx3W4GfyJnBo/bjgadIIcGrdmuBrsepwbMa3YG2RzHBupplg
b3GucHCGe2BxWsrwcmZdYHM6rPB0Rj9gdRqO8HYvW+B2+nDweA894HjaUvB57x/gero08HvPAeB8
o1Fwfa7j4H6DM3B/jsXgAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
AAEAAQABAgMBAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
AAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEA
AQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
AAEAAQABAAEAAQABAAEAAQABAAEAAf//x8ABAP//ubAABP//x8ABCP//x8ABDEVEVABFU1QARVdU
AEVQVAAAAAABAAAAAQ==
"""
EUROPE_HELSINKI = b"""
VFppZgAAAAAAAAAAAAAAAAAAAAAAAAAFAAAABQAAAAAAAAB1AAAABQAAAA2kc28Yy85RYMy/hdAV
I+uQFhPckBcDzZAX876QGOOvkBnToJAaw5GQG7y9EBysrhAdnJ8QHoyQEB98gRAgbHIQIVxjECJM
VBAjPEUQJCw2ECUcJxAmDBgQJwVDkCf1NJAo5SWQKdUWkCrFB5ArtPiQLKTpkC2U2pAuhMuQL3S8
kDBkrZAxXdkQMnK0EDM9uxA0UpYQNR2dEDYyeBA2/X8QOBuUkDjdYRA5+3aQOr1DEDvbWJA8pl+Q
Pbs6kD6GQZA/mxyQQGYjkEGEORBCRgWQQ2QbEEQl55BFQ/0QRgXJkEcj3xBH7uYQSQPBEEnOyBBK
46MQS66qEEzMv5BNjowQTqyhkE9ubhBQjIOQUVeKkFJsZZBTN2yQVExHkFUXTpBWLCmQVvcwkFgV
RhBY1xKQWfUoEFq29JBb1QoQXKAREF207BBef/MQX5TOEGBf1RBhfeqQYj+3EGNdzJBkH5kQZT2u
kGYItZBnHZCQZ+iXkGj9cpBpyHmQat1UkGuoW5BsxnEQbYg9kG6mUxBvaB+QcIY1EHFRPBByZhcQ
czEeEHRF+RB1EQAQdi8VkHbw4hB4DveQeNDEEHnu2ZB6sKYQe867kHyZwpB9rp2QfnmkkH+Of5AC
AQIDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQD
BAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAME
AwQAABdoAAAAACowAQQAABwgAAkAACowAQQAABwgAAlITVQARUVTVABFRVQAAAAAAQEAAAABAQ==
"""
NEW_YORK = b"""
VFppZgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAABcAAADrAAAABAAAABCeph5wn7rrYKCGAHCh
ms1gomXicKOD6eCkaq5wpTWnYKZTyvCnFYlgqDOs8Kj+peCqE47wqt6H4KvzcPCsvmngrdNS8K6e
S+CvszTwsH4t4LGcUXCyZ0pgs3wzcLRHLGC1XBVwticOYLc793C4BvBguRvZcLnm0mC7BPXwu8a0
YLzk1/C9r9DgvsS58L+PsuDApJvwwW+U4MKEffDDT3bgxGRf8MUvWODGTXxwxw864MgtXnDI+Fdg
yg1AcMrYOWDLiPBw0iP0cNJg++DTdeTw1EDd4NVVxvDWIL/g1zWo8NgAoeDZFYrw2eCD4Nr+p3Db
wGXg3N6JcN2pgmDevmtw34lkYOCeTXDhaUZg4n4vcONJKGDkXhFw5Vcu4OZHLfDnNxDg6CcP8OkW
8uDqBvHw6vbU4Ovm0/Ds1rbg7ca18O6/02Dvr9Jw8J+1YPGPtHDyf5dg82+WcPRfeWD1T3hw9j9b
YPcvWnD4KHfg+Q88cPoIWeD6+Fjw++g74PzYOvD9yB3g/rgc8P+n/+AAl/7wAYfh4AJ34PADcP5g
BGD9cAVQ4GEGQN9yBzDCYgeNGXMJEKRjCa2U9ArwhmQL4IV1DNmi5Q3AZ3YOuYTmD6mD9xCZZucR
iWX4EnlI6BNpR/kUWSrpFUkp+RY5DOoXKQv6GCIpaxkI7fsaAgtsGvIKfBvh7Wwc0ex8HcHPbR6x
zn0fobFtIHYA/SGBk20iVeL+I2qv7iQ1xP4lSpHuJhWm/ycqc+8n/sOAKQpV8CnepYAq6jfxK76H
gSzTVHItnmmCLrM2cy9+S4MwkxhzMWdoBDJy+nQzR0oENFLcdTUnLAU2Mr51NwcOBjgb2vY45vAG
Ofu89jrG0gY72572PK/uhj27gPY+j9CGP5ti9kBvsoZBhH92Qk+UhkNkYXZEL3aHRURDd0XzqQdH
LV/3R9OLB0kNQfdJs20HSu0j90uciYdM1kB3TXxrh062IndPXE2HUJYEd1E8L4dSdeZ3UxwRh1RV
yHdU+/OHVjWqd1blEAdYHsb3WMTyB1n+qPdapNQHW96K91yEtgddvmz3XmSYB1+eTvdgTbSHYYdr
d2ItlodjZ013ZA14h2VHL3dl7VqHZycRd2fNPIdpBvN3aa0eh2rm1XdrljsHbM/x9212HQdur9P3
b1X/B3CPtfdxNeEHcm+X93MVwwd0T3n3dP7fh3Y4lnd23sGHeBh4d3i+o4d5+Fp3ep6Fh3vYPHd8
fmeHfbged35eSYd/mAB3AAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
AAEAAQABAgMBAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
AAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEA
AQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
AAEAAQABAAEAAQABAAEAAQABAAEAAf//x8ABAP//ubAABP//x8ABCP//x8ABDEVEVABFU1QARVdU
AEVQVAAEslgAAAAAAQWk7AEAAAACB4YfggAAAAMJZ1MDAAAABAtIhoQAAAAFDSsLhQAAAAYPDD8G
AAAABxDtcocAAAAIEs6mCAAAAAkVn8qJAAAACheA/goAAAALGWIxiwAAAAwdJeoMAAAADSHa5Q0A
AAAOJZ6djgAAAA8nf9EPAAAAECpQ9ZAAAAARLDIpEQAAABIuE1ySAAAAEzDnJBMAAAAUM7hIlAAA
ABU2jBAVAAAAFkO3G5YAAAAXAAAAAQAAAAE=
"""
TZICAL_EST5EDT = """
BEGIN:VTIMEZONE
TZID:US-Eastern
LAST-MODIFIED:19870101T000000Z
TZURL:http://zones.stds_r_us.net/tz/US-Eastern
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
END:DAYLIGHT
END:VTIMEZONE
"""
class TZTest(unittest.TestCase):
def testStrStart1(self):
self.assertEqual(datetime(2003, 4, 6, 1, 59,
tzinfo=tz.tzstr("EST5EDT")).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00,
tzinfo=tz.tzstr("EST5EDT")).tzname(), "EDT")
def testStrEnd1(self):
self.assertEqual(datetime(2003, 10, 26, 0, 59,
tzinfo=tz.tzstr("EST5EDT")).tzname(), "EDT")
self.assertEqual(datetime(2003, 10, 26, 1, 00,
tzinfo=tz.tzstr("EST5EDT")).tzname(), "EST")
def testStrStart2(self):
s = "EST5EDT,4,0,6,7200,10,0,26,7200,3600"
self.assertEqual(datetime(2003, 4, 6, 1, 59,
tzinfo=tz.tzstr(s)).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
def testStrEnd2(self):
s = "EST5EDT,4,0,6,7200,10,0,26,7200,3600"
self.assertEqual(datetime(2003, 10, 26, 0, 59,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
self.assertEqual(datetime(2003, 10, 26, 1, 00,
tzinfo=tz.tzstr(s)).tzname(), "EST")
def testStrStart3(self):
s = "EST5EDT,4,1,0,7200,10,-1,0,7200,3600"
self.assertEqual(datetime(2003, 4, 6, 1, 59,
tzinfo=tz.tzstr(s)).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
def testStrEnd3(self):
s = "EST5EDT,4,1,0,7200,10,-1,0,7200,3600"
self.assertEqual(datetime(2003, 10, 26, 0, 59,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
self.assertEqual(datetime(2003, 10, 26, 1, 00,
tzinfo=tz.tzstr(s)).tzname(), "EST")
def testStrStart4(self):
s = "EST5EDT4,M4.1.0/02:00:00,M10-5-0/02:00"
self.assertEqual(datetime(2003, 4, 6, 1, 59,
tzinfo=tz.tzstr(s)).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
def testStrEnd4(self):
s = "EST5EDT4,M4.1.0/02:00:00,M10-5-0/02:00"
self.assertEqual(datetime(2003, 10, 26, 0, 59,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
self.assertEqual(datetime(2003, 10, 26, 1, 00,
tzinfo=tz.tzstr(s)).tzname(), "EST")
def testStrStart5(self):
s = "EST5EDT4,95/02:00:00,298/02:00"
self.assertEqual(datetime(2003, 4, 6, 1, 59,
tzinfo=tz.tzstr(s)).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
def testStrEnd5(self):
s = "EST5EDT4,95/02:00:00,298/02"
self.assertEqual(datetime(2003, 10, 26, 0, 59,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
self.assertEqual(datetime(2003, 10, 26, 1, 00,
tzinfo=tz.tzstr(s)).tzname(), "EST")
def testStrStart6(self):
s = "EST5EDT4,J96/02:00:00,J299/02:00"
self.assertEqual(datetime(2003, 4, 6, 1, 59,
tzinfo=tz.tzstr(s)).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
def testStrEnd6(self):
s = "EST5EDT4,J96/02:00:00,J299/02"
self.assertEqual(datetime(2003, 10, 26, 0, 59,
tzinfo=tz.tzstr(s)).tzname(), "EDT")
self.assertEqual(datetime(2003, 10, 26, 1, 00,
tzinfo=tz.tzstr(s)).tzname(), "EST")
def testStrStr(self):
# Test that tz.tzstr() won't throw an error if given a str instead
# of a unicode literal.
self.assertEqual(datetime(2003, 4, 6, 1, 59,
tzinfo=tz.tzstr(str("EST5EDT"))).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00,
tzinfo=tz.tzstr(str("EST5EDT"))).tzname(), "EDT")
def testStrCmp1(self):
self.assertEqual(tz.tzstr("EST5EDT"),
tz.tzstr("EST5EDT4,M4.1.0/02:00:00,M10-5-0/02:00"))
def testStrCmp2(self):
self.assertEqual(tz.tzstr("EST5EDT"),
tz.tzstr("EST5EDT,4,1,0,7200,10,-1,0,7200,3600"))
def testRangeCmp1(self):
from dateutil.relativedelta import SU
self.assertEqual(tz.tzstr("EST5EDT"),
tz.tzrange("EST", -18000, "EDT", -14400,
relativedelta(hours=+2,
month=4, day=1,
weekday=SU(+1)),
relativedelta(hours=+1,
month=10, day=31,
weekday=SU(-1))))
def testRangeCmp2(self):
self.assertEqual(tz.tzstr("EST5EDT"),
tz.tzrange("EST", -18000, "EDT"))
def testFileStart1(self):
tzc = tz.tzfile(BytesIO(base64.b64decode(TZFILE_EST5EDT)))
self.assertEqual(datetime(2003, 4, 6, 1, 59, tzinfo=tzc).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00, tzinfo=tzc).tzname(), "EDT")
def testFileEnd1(self):
tzc = tz.tzfile(BytesIO(base64.b64decode(TZFILE_EST5EDT)))
self.assertEqual(datetime(2003, 10, 26, 0, 59, tzinfo=tzc).tzname(),
"EDT")
self.assertEqual(datetime(2003, 10, 26, 1, 00, tzinfo=tzc).tzname(),
"EST")
def testZoneInfoFileStart1(self):
tz = zoneinfo.gettz("EST5EDT")
self.assertEqual(datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname(), "EST",
MISSING_TARBALL)
self.assertEqual(datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname(), "EDT")
def testZoneInfoFileEnd1(self):
tzc = zoneinfo.gettz("EST5EDT")
self.assertEqual(datetime(2003, 10, 26, 0, 59, tzinfo=tzc).tzname(),
"EDT", MISSING_TARBALL)
self.assertEqual(datetime(2003, 10, 26, 1, 00, tzinfo=tzc).tzname(),
"EST")
def testZoneInfoOffsetSignal(self):
utc = zoneinfo.gettz("UTC")
nyc = zoneinfo.gettz("America/New_York")
self.assertNotEqual(utc, None, MISSING_TARBALL)
self.assertNotEqual(nyc, None)
t0 = datetime(2007, 11, 4, 0, 30, tzinfo=nyc)
t1 = t0.astimezone(utc)
t2 = t1.astimezone(nyc)
self.assertEqual(t0, t2)
self.assertEqual(nyc.dst(t0), timedelta(hours=1))
def testTzNameNone(self):
gmt5 = tz.tzoffset(None, -18000) # -5:00
self.assertIs(datetime(2003, 10, 26, 0, 0, tzinfo=gmt5).tzname(),
None)
def testICalStart1(self):
tzc = tz.tzical(StringIO(TZICAL_EST5EDT)).get()
self.assertEqual(datetime(2003, 4, 6, 1, 59, tzinfo=tzc).tzname(), "EST")
self.assertEqual(datetime(2003, 4, 6, 2, 00, tzinfo=tzc).tzname(), "EDT")
def testICalEnd1(self):
tzc = tz.tzical(StringIO(TZICAL_EST5EDT)).get()
self.assertEqual(datetime(2003, 10, 26, 0, 59, tzinfo=tzc).tzname(), "EDT")
self.assertEqual(datetime(2003, 10, 26, 1, 00, tzinfo=tzc).tzname(), "EST")
def testRoundNonFullMinutes(self):
# This timezone has an offset of 5992 seconds in 1900-01-01.
tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI)))
self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
"1900-01-01 00:00:00+01:40")
def testLeapCountDecodesProperly(self):
# This timezone has leapcnt, and failed to decode until
# Eugene Oden notified about the issue.
# As leap information is currently unused (and unstored) by tzfile() we
# can only indirectly test this: Take advantage of tzfile() not closing
# the input file if handed in as an opened file and assert that the
# full file content has been read by tzfile(). Note: For this test to
# work NEW_YORK must be in TZif version 1 format i.e. no more data
# after TZif v1 header + data has been read
fileobj = BytesIO(base64.b64decode(NEW_YORK))
tzc = tz.tzfile(fileobj)
# we expect no remaining file content now, i.e. zero-length; if there's
# still data we haven't read the file format correctly
remaining_tzfile_content = fileobj.read()
self.assertEqual(len(remaining_tzfile_content), 0)
def testIsStd(self):
# NEW_YORK tzfile contains this isstd information:
isstd_expected = (0, 0, 0, 1)
tzc = tz.tzfile(BytesIO(base64.b64decode(NEW_YORK)))
# gather the actual information as parsed by the tzfile class
isstd = []
for ttinfo in tzc._ttinfo_list:
# ttinfo objects contain boolean values
isstd.append(int(ttinfo.isstd))
# ttinfo list may contain more entries than isstd file content
isstd = tuple(isstd[:len(isstd_expected)])
self.assertEqual(
isstd_expected, isstd,
"isstd UTC/local indicators parsed: %s != tzfile contents: %s"
% (isstd, isstd_expected))
def testGettz(self):
# bug 892569
str(tz.gettz('UTC'))
def testGetTzEquality(self):
self.assertEqual(tz.gettz('UTC'), tz.gettz('UTC'))
def testBrokenIsDstHandling(self):
# tzrange._isdst() was using a date() rather than a datetime().
# Issue reported by Lennart Regebro.
dt = datetime(2007, 8, 6, 4, 10, tzinfo=tz.tzutc())
self.assertEqual(dt.astimezone(tz=tz.gettz("GMT+2")),
datetime(2007, 8, 6, 6, 10, tzinfo=tz.tzstr("GMT+2")))
def testGMTHasNoDaylight(self):
# tz.tzstr("GMT+2") improperly considered daylight saving time.
# Issue reported by Lennart Regebro.
dt = datetime(2007, 8, 6, 4, 10)
self.assertEqual(tz.gettz("GMT+2").dst(dt), timedelta(0))
def testGMTOffset(self):
# GMT and UTC offsets have inverted signal when compared to the
# usual TZ variable handling.
dt = datetime(2007, 8, 6, 4, 10, tzinfo=tz.tzutc())
self.assertEqual(dt.astimezone(tz=tz.tzstr("GMT+2")),
datetime(2007, 8, 6, 6, 10, tzinfo=tz.tzstr("GMT+2")))
self.assertEqual(dt.astimezone(tz=tz.gettz("UTC-2")),
datetime(2007, 8, 6, 2, 10, tzinfo=tz.tzstr("UTC-2")))
def testTimeOnlyUTC(self):
# https://github.com/dateutil/dateutil/issues/132
# tzutc doesn't care
tz_utc = tz.tzutc()
self.assertEqual(dt_time(13, 20, tzinfo=tz_utc).utcoffset(),
timedelta(0))
def testTimeOnlyOffset(self):
# tzoffset doesn't care
tz_offset = tz.tzoffset('+3', 3600)
self.assertEqual(dt_time(13, 20, tzinfo=tz_offset).utcoffset(),
timedelta(seconds=3600))
def testTimeOnlyLocal(self):
# tzlocal returns None
tz_local = tz.tzlocal()
self.assertIs(dt_time(13, 20, tzinfo=tz_local).utcoffset(), None)
def testTimeOnlyRange(self):
# tzrange returns None
tz_range = tz.tzrange('dflt')
self.assertIs(dt_time(13, 20, tzinfo=tz_range).utcoffset(), None)
def testTimeOnlyGettz(self):
# gettz returns None
tz_get = tz.gettz('Europe/Minsk')
self.assertIs(dt_time(13, 20, tzinfo=tz_get).utcoffset(), None)
@unittest.skipIf(IS_WIN, "requires Unix")
def testTZSetDoesntCorrupt(self):
# if we start in non-UTC then tzset UTC make sure parse doesn't get
# confused
os.environ['TZ'] = 'UTC'
_time.tzset()
# this should parse to UTC timezone not the original timezone
dt = parse('2014-07-20T12:34:56+00:00')
self.assertEqual(str(dt), '2014-07-20 12:34:56+00:00')
@unittest.skipUnless(IS_WIN, "Requires Windows")
class TzWinTest(unittest.TestCase):
def testTzResLoadName(self):
# This may not work right on non-US locales.
tzr = tzwin.tzres()
self.assertEqual(tzr.load_name(112), "Eastern Standard Time")
def testTzResNameFromString(self):
tzr = tzwin.tzres()
self.assertEqual(tzr.name_from_string('@tzres.dll,-221'),
'Alaskan Daylight Time')
self.assertEqual(tzr.name_from_string('Samoa Daylight Time'),
'Samoa Daylight Time')
with self.assertRaises(ValueError):
tzr.name_from_string('@tzres.dll,100')
def testIsdstZoneWithNoDaylightSaving(self):
tz = tzwin.tzwin("UTC")
dt = parse("2013-03-06 19:08:15")
self.assertFalse(tz._isdst(dt))
def testOffset(self):
tz = tzwin.tzwin("Cape Verde Standard Time")
self.assertEqual(tz.utcoffset(datetime(1995, 5, 21, 12, 9, 13)),
timedelta(-1, 82800))
def testLocal(self):
# Not sure how to pin a local time zone, so for now we're just going
# to run this and make sure it doesn't raise an error
# See Github Issue #135: https://github.com/dateutil/dateutil/issues/135
datetime.now(tzwin.tzwinlocal())
datetime(2014, 3, 11, tzinfo=tzwin.tzwinlocal()).utcoffset()
def testTzwinName(self):
# https://github.com/dateutil/dateutil/issues/143
tw = tz.tzwin('Eastern Standard Time')
# Cover the transitions for at least two years.
ESTs = 'Eastern Standard Time'
EDTs = 'Eastern Daylight Time'
transition_dates = [(datetime(2015, 3, 8, 0, 59), ESTs),
(datetime(2015, 3, 8, 2, 1), EDTs),
(datetime(2015, 11, 1, 1, 59), EDTs),
(datetime(2015, 11, 1, 3, 1), ESTs),
(datetime(2016, 3, 13, 0, 59), ESTs),
(datetime(2016, 3, 13, 2, 1), EDTs),
(datetime(2016, 11, 6, 1, 59), EDTs),
(datetime(2016, 11, 6, 3, 1), ESTs)]
for t_date, expected in transition_dates:
self.assertEqual(t_date.replace(tzinfo=tw).tzname(), expected)
def testTzwinRepr(self):
tw = tz.tzwin('Yakutsk Standard Time')
self.assertEqual(repr(tw), 'tzwin(' +
repr('Yakutsk Standard Time') + ')')
def testTzWinEquality(self):
# https://github.com/dateutil/dateutil/issues/151
tzwin_names = ('Eastern Standard Time',
'West Pacific Standard Time',
'Yakutsk Standard Time',
'Iran Standard Time',
'UTC')
for tzwin_name in tzwin_names:
# Get two different instances to compare
tw1 = tz.tzwin(tzwin_name)
tw2 = tz.tzwin(tzwin_name)
self.assertEqual(tw1, tw2)
def testTzWinInequality(self):
# https://github.com/dateutil/dateutil/issues/151
# Note these last two currently differ only in their name.
tzwin_names = (('Eastern Standard Time', 'Yakutsk Standard Time'),
('Greenwich Standard Time', 'GMT Standard Time'),
('GMT Standard Time', 'UTC'),
('E. South America Standard Time',
'Argentina Standard Time'))
for tzwn1, tzwn2 in tzwin_names:
# Get two different instances to compare
tw1 = tz.tzwin(tzwn1)
tw2 = tz.tzwin(tzwn2)
self.assertNotEqual(tw1, tw2)
def testTzwinTimeOnlyDST(self):
# For zones with DST, .dst() should return None
tw_est = tz.tzwin('Eastern Standard Time')
self.assertIs(dt_time(14, 10, tzinfo=tw_est).dst(), None)
# This zone has no DST, so .dst() can return 0
tw_sast = tz.tzwin('South Africa Standard Time')
self.assertEqual(dt_time(14, 10, tzinfo=tw_sast).dst(),
timedelta(0))
def testTzwinTimeOnlyUTCOffset(self):
# For zones with DST, .utcoffset() should return None
tw_est = tz.tzwin('Eastern Standard Time')
self.assertIs(dt_time(14, 10, tzinfo=tw_est).utcoffset(), None)
# This zone has no DST, so .utcoffset() returns standard offset
tw_sast = tz.tzwin('South Africa Standard Time')
self.assertEqual(dt_time(14, 10, tzinfo=tw_sast).utcoffset(),
timedelta(hours=2))
def testTzwinLocalTimeOnlyTZName(self):
# For zones with DST, the name defaults to standard time
tw_est = tz.tzwin('Eastern Standard Time')
self.assertEqual(dt_time(14, 10, tzinfo=tw_est).tzname(),
'Eastern Standard Time')
# For zones with no DST, this should work normally.
tw_sast = tz.tzwin('South Africa Standard Time')
self.assertEqual(dt_time(14, 10, tzinfo=tw_sast),
'South Africa Standard Time')
@unittest.skipUnless(TZWinContext.tz_change_allowed(),
'Skipping unless tz changes are allowed.')
def testTzwinLocalName(self):
# https://github.com/dateutil/dateutil/issues/143
ESTs = 'Eastern Standard Time'
EDTs = 'Eastern Daylight Time'
transition_dates = [(datetime(2015, 3, 8, 0, 59), ESTs),
(datetime(2015, 3, 8, 2, 1), EDTs),
(datetime(2015, 11, 1, 1, 59), EDTs),
(datetime(2015, 11, 1, 3, 1), ESTs),
(datetime(2016, 3, 13, 0, 59), ESTs),
(datetime(2016, 3, 13, 2, 1), EDTs),
(datetime(2016, 11, 6, 1, 59), EDTs),
(datetime(2016, 11, 6, 3, 1), ESTs)]
with TZWinContext('Eastern Standard Time'):
tw = tz.tzwinlocal()
for t_date, expected in transition_dates:
self.assertEqual(t_date.replace(tzinfo=tw).tzname(), expected)
def testTzWinLocalRepr(self):
tw = tz.tzwinlocal()
self.assertEqual(repr(tw), 'tzwinlocal()')
@unittest.skipUnless(TZWinContext.tz_change_allowed(),
'Skipping unless tz changes are allowed.')
def testTzwinLocalRepr(self):
# https://github.com/dateutil/dateutil/issues/143
with TZWinContext('Eastern Standard Time'):
tw = tz.tzwinlocal()
self.assertEqual(str(tw), 'tzwinlocal(' +
repr('Eastern Standard Time') + ')')
with TZWinContext('Pacific Standard Time'):
tw = tz.tzwinlocal()
self.assertEqual(str(tw), 'tzwinlocal(' +
repr('Pacific Standard Time') + ')')
@unittest.skipUnless(TZWinContext.tz_change_allowed(),
'Skipping unless tz changes are allowed.')
def testTzwinLocalEquality(self):
tw_est = tz.tzwin('Eastern Standard Time')
tw_pst = tz.tzwin('Pacific Standard Time')
with TZWinContext('Eastern Standard Time'):
twl1 = tz.tzwinlocal()
twl2 = tz.tzwinlocal()
self.assertEqual(twl1, twl2)
self.assertEqual(twl1, tw_est)
self.assertNotEqual(twl1, tw_pst)
with TZWinContext('Pacific Standard Time'):
twl1 = tz.tzwinlocal()
twl2 = tz.tzwinlocal()
tw = tz.tzwin('Pacific Standard Time')
self.assertEqual(twl1, twl2)
self.assertEqual(twl1, tw)
self.assertEqual(twl1, tw_pst)
self.assertNotEqual(twl1, tw_est)
@unittest.skipUnless(TZWinContext.tz_change_allowed(),
'Skipping unless tz changes are allowed.')
def testTzwinLocalTimeOnlyDST(self):
# For zones with DST, .dst() should return None
with TZWinContext('Eastern Standard Time'):
twl = tz.tzwinlocal()
self.assertIs(dt_time(14, 10, tzinfo=twl).dst(), None)
# This zone has no DST, so .dst() can return 0
with TZWinContext('South Africa Standard Time'):
twl = tz.tzwinlocal()
self.assertEqual(dt_time(14, 10, tzinfo=twl).dst(), timedelta(0))
@unittest.skipUnless(TZWinContext.tz_change_allowed(),
'Skipping unless tz changes are allowed.')
def testTzwinLocalTimeOnlyUTCOffset(self):
# For zones with DST, .utcoffset() should return None
with TZWinContext('Eastern Standard Time'):
twl = tz.tzwinlocal()
self.assertIs(dt_time(14, 10, tzinfo=twl).utcoffset(), None)
# This zone has no DST, so .utcoffset() returns standard offset
with TZWinContext('South Africa Standard Time'):
twl = tz.tzwinlocal()
self.assertEqual(dt_time(14, 10, tzinfo=twl).utcoffset(),
timedelta(hours=2))
@unittest.skipUnless(TZWinContext.tz_change_allowed(),
'Skipping unless tz changes are allowed.')
def testTzwinLocalTimeOnlyTZName(self):
# For zones with DST, the name defaults to standard time
with TZWinContext('Eastern Standard Time'):
twl = tz.tzwinlocal()
self.assertEqual(dt_time(14, 10, tzinfo=twl).tzname(),
'Eastern Standard Time')
# For zones with no DST, this should work normally.
with TZWinContext('South Africa Standard Time'):
twl = tz.tzwinlocal()
self.assertEqual(dt_time(14, 10, tzinfo=twl).tzname(),
'South Africa Standard Time')
from six import PY3
__all__ = ['tzname_in_python2']
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
+1
-1
# -*- coding: utf-8 -*-
__version__ = "2.5.0"
__version__ = "2.5.1"

@@ -5,2 +5,5 @@ # -*- coding: utf-8 -*-

import operator
from math import copysign
from six import integer_types

@@ -161,15 +164,24 @@ from warnings import warn

months = (dt1.year * 12 + dt1.month) - (dt2.year * 12 + dt2.month)
# 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:
while dt1 > dtm:
months += 1
self._set_months(months)
dtm = self.__radd__(dt2)
compare = operator.gt
increment = 1
else:
while dt1 < dtm:
months -= 1
self._set_months(months)
dtm = self.__radd__(dt2)
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

@@ -198,3 +210,2 @@ self.seconds = delta.seconds + delta.days * 86400

# Absolute information
if any(x is not None and int(x) != x

@@ -239,3 +250,3 @@ for x in (year, month, day, hour,

if abs(self.microseconds) > 999999:
s = self.microseconds // abs(self.microseconds)
s = _sign(self.microseconds)
div, mod = divmod(self.microseconds * s, 1000000)

@@ -245,3 +256,3 @@ self.microseconds = mod * s

if abs(self.seconds) > 59:
s = self.seconds // abs(self.seconds)
s = _sign(self.seconds)
div, mod = divmod(self.seconds * s, 60)

@@ -251,3 +262,3 @@ self.seconds = mod * s

if abs(self.minutes) > 59:
s = self.minutes//abs(self.minutes)
s = _sign(self.minutes)
div, mod = divmod(self.minutes * s, 60)

@@ -257,3 +268,3 @@ self.minutes = mod * s

if abs(self.hours) > 23:
s = self.hours//abs(self.hours)
s = _sign(self.hours)
div, mod = divmod(self.hours * s, 24)

@@ -263,3 +274,3 @@ self.hours = mod * s

if abs(self.months) > 11:
s = self.months // abs(self.months)
s = _sign(self.months)
div, mod = divmod(self.months * s, 12)

@@ -285,6 +296,6 @@ self.months = mod * s

if abs(self.months) > 11:
s = self.months//abs(self.months)
div, mod = divmod(self.months*s, 12)
self.months = mod*s
self.years = div*s
s = _sign(self.months)
div, mod = divmod(self.months * s, 12)
self.months = mod * s
self.years = div * s
else:

@@ -525,2 +536,5 @@ self.years = 0

def _sign(x):
return int(copysign(1, x))
# vim:ts=4:sw=4:et

@@ -68,2 +68,3 @@ # -*- coding: utf-8 -*-

raise ValueError("Can't create weekday with n == 0")
self.weekday = weekday

@@ -96,2 +97,15 @@ self.n = n

def _invalidates_cache(f):
"""
Decorator for rruleset methods which may invalidate the
cached length.
"""
def inner_func(self, *args, **kwargs):
rv = f(self, *args, **kwargs)
self._invalidate_cache()
return rv
return inner_func
class rrulebase(object):

@@ -102,8 +116,7 @@ def __init__(self, cache=False):

self._cache_lock = _thread.allocate_lock()
self._cache_gen = self._iter()
self._cache_complete = False
self._invalidate_cache()
else:
self._cache = None
self._cache_complete = False
self._len = None
self._len = None

@@ -118,2 +131,13 @@ def __iter__(self):

def _invalidate_cache(self):
if self._cache is not None:
self._cache = []
self._cache_complete = False
self._cache_gen = self._iter()
if self._cache_lock.locked():
self._cache_lock.release()
self._len = None
def _iter_cached(self):

@@ -311,2 +335,25 @@ i = 0

.. note::
Per RFC section 3.3.10, recurrence instances falling on invalid dates
and times are ignored rather than coerced:
Recurrence rules may generate recurrence instances with an invalid
date (e.g., February 30) or nonexistent local time (e.g., 1:30 AM
on a day where the local time is moved forward by an hour at 1:00
AM). Such recurrence instances MUST be ignored and MUST NOT be
counted as part of the recurrence set.
This can lead to possibly surprising behavior when, for example, the
start date occurs at the end of the month:
>>> from dateutil.rrule import rrule, MONTHLY
>>> from datetime import datetime
>>> start_date = datetime(2014, 12, 31)
>>> list(rrule(freq=MONTHLY, count=4, dtstart=start_date))
... # doctest: +NORMALIZE_WHITESPACE
[datetime.datetime(2014, 12, 31, 0, 0),
datetime.datetime(2015, 1, 31, 0, 0),
datetime.datetime(2015, 3, 31, 0, 0),
datetime.datetime(2015, 5, 31, 0, 0)]
Additionally, it supports the following keyword arguments:

@@ -335,7 +382,15 @@

How many occurrences will be generated.
.. note::
As of version 2.5.0, the use of the ``until`` keyword together
with the ``count`` keyword is deprecated per RFC-2445 Sec. 4.3.10.
:param until:
If given, this must be a datetime instance, that will specify the
limit of the recurrence. If a recurrence instance happens to be the
same as the datetime instance given in the until keyword, this will
be the last occurrence.
limit of the recurrence. The last recurrence in the rule is the greatest
datetime that is less than or equal to the value specified in the
``until`` parameter.
.. note::
As of version 2.5.0, the use of the ``until`` keyword together
with the ``count`` keyword is deprecated per RFC-2445 Sec. 4.3.10.
:param bysetpos:

@@ -1284,2 +1339,3 @@ If given, it must be either an integer, or a sequence of integers,

@_invalidates_cache
def rrule(self, rrule):

@@ -1290,2 +1346,3 @@ """ Include the given :py:class:`rrule` instance in the recurrence set

@_invalidates_cache
def rdate(self, rdate):

@@ -1296,2 +1353,3 @@ """ Include the given :py:class:`datetime` instance in the recurrence

@_invalidates_cache
def exrule(self, exrule):

@@ -1304,2 +1362,3 @@ """ Include the given rrule instance in the recurrence set exclusion

@_invalidates_cache
def exdate(self, exdate):

@@ -1403,3 +1462,3 @@ """ Include the given datetime instance in the recurrence set

n = int(splt[1][:-1])
else:
elif len(wday):
# If it's of the form +1MO

@@ -1413,2 +1472,5 @@ for i in range(len(wday)):

n = int(n)
else:
raise ValueError("Invalid (empty) BYDAY specification.")
l.append(weekdays[self._weekday_map[w]](n))

@@ -1415,0 +1477,0 @@ rrkwargs["byweekday"] = l

from .tz import *
from six import PY3
__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange",
"tzstr", "tzical", "tzwin", "tzwinlocal", "gettz"]
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

@@ -17,3 +17,3 @@ # -*- coding: utf-8 -*-

from six import string_types, PY3
from .__init__ import tzname_in_python2
from ._common import tzname_in_python2

@@ -311,6 +311,6 @@ try:

# Not used, for now
# if leapcnt:
# leap = struct.unpack(">%dl" % (leapcnt*2),
# fileobj.read(leapcnt*8))
# Not used, for now (but read anyway for correct file position)
if leapcnt:
leap = struct.unpack(">%dl" % (leapcnt*2),
fileobj.read(leapcnt*8))

@@ -317,0 +317,0 @@ # Then there are tzh_ttisstdcnt standard/wall

@@ -6,2 +6,3 @@ # This code was originally contributed by Jeffrey Harris.

from six.moves import winreg
from six import text_type

@@ -15,3 +16,3 @@ try:

from .__init__ import tzname_in_python2
from ._common import tzname_in_python2

@@ -115,2 +116,3 @@ __all__ = ["tzwin", "tzwinlocal", "tzres"]

class tzwinbase(datetime.tzinfo):

@@ -138,3 +140,7 @@ """tzinfo class based on win32's timezones available in the registry."""

def utcoffset(self, dt):
if self._isdst(dt):
isdst = self._isdst(dt)
if isdst is None:
return None
elif isdst:
return datetime.timedelta(minutes=self._dstoffset)

@@ -145,3 +151,7 @@ else:

def dst(self, dt):
if self._isdst(dt):
isdst = self._isdst(dt)
if isdst is None:
return None
elif isdst:
minutes = self._dstoffset - self._stdoffset

@@ -177,2 +187,5 @@ return datetime.timedelta(minutes=minutes)

return False
elif dt is None:
return None
dston = picknthweekday(dt.year, self._dstmonth, self._dstdayofweek,

@@ -197,4 +210,4 @@ self._dsthour, self._dstminute,

with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle:
with winreg.OpenKey(handle,
"%s\%s" % (TZKEYNAME, name)) as tzkey:
tzkeyname = text_type("{kn}\{name}").format(kn=TZKEYNAME, name=name)
with winreg.OpenKey(handle, tzkeyname) as tzkey:
keydict = valuestodict(tzkey)

@@ -245,4 +258,5 @@

try:
with winreg.OpenKey(
handle, "%s\%s" % (TZKEYNAME, self._stdname)) as tzkey:
tzkeyname = text_type('{kn}\{sn}').format(kn=TZKEYNAME,
sn=self._stdname)
with winreg.OpenKey(handle, tzkeyname) as tzkey:
_keydict = valuestodict(tzkey)

@@ -249,0 +263,0 @@ self._display = _keydict["Display"]

include LICENSE NEWS zonefile_metadata.json updatezinfo.py
recursive-include dateutil/test *
global-exclude __pycache__
global-exclude *.py[co]
+34
-10

@@ -0,1 +1,26 @@

Version 2.5.1
-------------
- Updated zoneinfo to 2016b
- Changed MANIFEST.in to explicitly include test suite in source distributions,
with help from @koobs (gh issue #193, pr #194, #201, #221)
- Explicitly set all line-endings to LF, except for the NEWS file, on a
per-repository basis (gh pr #218)
- Fixed an issue with improper caching behavior in rruleset objects (gh issue
#104, pr #207)
- Changed to an explicit error when rrulestr strings contain a missing BYDAY
(gh issue #162, pr #211)
- tzfile now correctly handles files containing leapcnt (although the leapcnt
information is not actually used). Contributed by @hjoukl (gh issue #146, pr
#147)
- Fixed recursive import issue with tz module (gh pr #204)
- Added compatibility between tzwin objects and datetime.time objects (gh issue
#216, gh pr #219)
- Refactored monolithic test suite by module (gh issue #61, pr #200 and #206)
- Improved test coverage in the relativedelta module (gh pr #215)
- Adjusted documentation to reflect possibly counter-intuitive properties of
RFC-5545-compliant rrules, and other documentation improvements in the rrule
module (gh issue #105, gh issue #149 - pointer to the solution by @phep,
pr #213).
Version 2.5.0

@@ -83,3 +108,3 @@ -------------

download is now retried a number of times (with a delay) (gh pr #177)
- Many failing doctests were fixed by @moreati. (gh pr #120)
- Many failing doctests were fixed by @moreati. (gh pr #120)
- Many fixes to the documentation (gh pr #103, gh pr #87 from @radarhere,

@@ -115,3 +140,3 @@ gh pr #154 from @gpoesia, gh pr #156 from @awsum, gh pr #168 from @ja8zyjits)

- Fix and add test for Python 2.x compatibility with boolean checking of
relativedelta objects. Implemented by @nimasmi (gh pr #43) and C�dric Krier
relativedelta objects. Implemented by @nimasmi (gh pr #43) and Cédric Krier
(lp: 1035038)

@@ -145,4 +170,4 @@ - Replaced parse() calls with explicit datetime objects in unit tests unrelated

- The package is now zip-safe, and universal-wheelable, thanks to changes in
the handling of the zoneinfo file.
- The package is now zip-safe, and universal-wheelable, thanks to changes in
the handling of the zoneinfo file.

@@ -233,3 +258,3 @@ - Fixed tzwin silently not imported on windows python2

- Fixed bug in constructor of parser, and converted parser classes to
new-style classes. Original report and patch by Michael Elsd�rfer.
new-style classes. Original report and patch by Michael Elsdörfer.

@@ -251,6 +276,6 @@ - Initialize tzid and comps in tz.py, to prevent the code from ever

since Python's datetime doesn't support sub-minute offsets.
Thanks to Ilpo Nyyss�nen for reporting the issue.
Thanks to Ilpo Nyyssönen for reporting the issue.
- Removed bare string exceptions, as reported and fixed by
Wilfredo S�nchez Vega.
Wilfredo Sánchez Vega.

@@ -287,3 +312,3 @@ - Fix bug in leap count parsing (reported and fixed by Eugene Oden).

- Fixed pickling of timezone types, as reported by
Andreas K�hler.
Andreas Köhler.

@@ -320,3 +345,3 @@ - Implemented internal timezone information with binary

- Fixed rrule.between() for cases where "after" is achieved
before even starting, as reported by Andreas K�hler.
before even starting, as reported by Andreas Köhler.

@@ -329,2 +354,1 @@ - Fixed two digit zero-year parsing (such as 31-Dec-00), as

as reported by Nicholas Piper.
Metadata-Version: 1.1
Name: python-dateutil
Version: 2.5.0
Version: 2.5.1
Summary: Extensions to the standard Python datetime module

@@ -5,0 +5,0 @@ Home-page: https://dateutil.readthedocs.org

Metadata-Version: 1.1
Name: python-dateutil
Version: 2.5.0
Version: 2.5.1
Summary: Extensions to the standard Python datetime module

@@ -5,0 +5,0 @@ Home-page: https://dateutil.readthedocs.org

@@ -15,3 +15,12 @@ LICENSE

dateutil/tzwin.py
dateutil/test/__init__.py
dateutil/test/_common.py
dateutil/test/test_easter.py
dateutil/test/test_imports.py
dateutil/test/test_parser.py
dateutil/test/test_relativedelta.py
dateutil/test/test_rrule.py
dateutil/test/test_tz.py
dateutil/tz/__init__.py
dateutil/tz/_common.py
dateutil/tz/tz.py

@@ -18,0 +27,0 @@ dateutil/tz/win.py

@@ -7,5 +7,5 @@ {

],
"tzdata_file": "tzdata2016a.tar.gz",
"tzdata_file_sha512": "9aa5f61a73afa5070dfb1d1982945d268ea8215663d0cd594216500aff14797ea5591ccfd488dc2280902fa1820bf782623624912b669873728431258fe10ec1",
"tzversion": "2016a",
"tzdata_file": "tzdata2016b.tar.gz",
"tzdata_file_sha512": "6d30215ba3289a5b85a632d635b76a54c3c08d97e426d6bd89f83c4efd252e43959593b21cca9d2b185f3845358908946cc308365accbee94f126ad3057cf838",
"tzversion": "2016b",
"zonegroups": [

@@ -12,0 +12,0 @@ "africa",

Sorry, the diff of this file is not supported yet