python-dateutil
Advanced tools
| 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 |
| # -*- 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 |
+69
-7
@@ -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 |
+21
-7
@@ -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"] |
+3
-0
| 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. | ||
+1
-1
| 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
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
667695
80.28%36
33.33%10283
136.07%