# -*- coding: utf-8 -*-
#
# badidatetime/test/test_datetime.py
#
__docformat__ = "restructuredtext en"
import os
import re
import locale
import time
import pickle
import importlib
import unittest
from unittest.mock import patch, PropertyMock
from zoneinfo import ZoneInfo
from .. import enable_geocoder
from ..badi_calendar import BahaiCalendar
datetime = importlib.import_module('badidatetime.datetime')
[docs]
class NoneTimeZone(datetime.tzinfo):
"""
Creates a Timezone which defaults to None for the utcoffset, tzname,
and dst methods.
"""
def __init__(self):
self._VALUES = {'utcoffset': None, 'tzname': None, 'dst': None}
[docs]
def utcoffset(self, dt):
return self._VALUES['utcoffset']
[docs]
def set_utcoffset(self, value):
self._VALUES['utcoffset'] = value
[docs]
def tzname(self, dt):
return self._VALUES['tzname']
[docs]
def set_tzname(self, value):
self._VALUES['tzname'] = value
[docs]
def dst(self, dt):
return self._VALUES['dst']
[docs]
def set_dst(self, value):
self._VALUES['dst'] = value
[docs]
class TestBadiDatetime__module__(unittest.TestCase):
"""
Test that all classes that are defined in the datetime.py module have
their internal __module__ changed to `badidatetime`.
"""
def __init__(self, name):
super().__init__(name)
#@unittest.skip("Temporarily skipped")
[docs]
def test_date(self):
import badidatetime
data = (
(datetime.date.today(), 'badidatetime.datetime'),
(badidatetime.date.today(), 'badidatetime.datetime')
)
msg = "Expected {}, found {}."
for instance, expected_result in data:
result = isinstance(instance, badidatetime.date)
self.assertTrue(result, msg.format(expected_result, result))
module = instance.__class__.__module__
self.assertEqual(expected_result, module, msg.format(
expected_result, module))
#@unittest.skip("Temporarily skipped")
[docs]
def test_datetime(self):
import badidatetime
data = (
(datetime.datetime.now(), 'badidatetime.datetime'),
(badidatetime.datetime.now(), 'badidatetime.datetime')
)
msg = "Expected {}, found {}."
for instance, expected_result in data:
result = isinstance(instance, badidatetime.datetime)
self.assertTrue(result, msg.format(expected_result, result))
module = instance.__class__.__module__
self.assertEqual(expected_result, module, msg.format(
expected_result, module))
#@unittest.skip("Temporarily skipped")
[docs]
def test_time(self):
import badidatetime
data = (
(datetime.time.fromisoformat("T12"), 'badidatetime.datetime'),
(badidatetime.time.fromisoformat("T12"), 'badidatetime.datetime')
)
msg = "Expected {}, found {}."
for instance, expected_result in data:
result = isinstance(instance, badidatetime.time)
self.assertTrue(result, msg.format(expected_result, result))
module = instance.__class__.__module__
self.assertEqual(expected_result, module, msg.format(
expected_result, module))
#@unittest.skip("Temporarily skipped")
[docs]
def test_timezone(self):
import badidatetime
data = (
(datetime.timezone.badi, 'badidatetime.datetime'),
(badidatetime.timezone.badi, 'badidatetime.datetime')
)
msg = "Expected {}, found {}."
for instance, expected_result in data:
result = isinstance(instance, badidatetime.timezone)
self.assertTrue(result, msg.format(expected_result, result))
module = instance.__class__.__module__
self.assertEqual(expected_result, module, msg.format(
expected_result, module))
#@unittest.skip("Temporarily skipped")
[docs]
def test_timedelta(self):
"""
The 'timedelta` class is borrowed from the Python datetime package.
"""
import badidatetime
data = (
(datetime.timedelta(1), 'datetime'),
(badidatetime.timedelta(1), 'datetime')
)
msg = "Expected {}, found {}."
for instance, expected_result in data:
result = isinstance(instance, datetime.timedelta)
self.assertTrue(result, msg.format(expected_result, result))
module = instance.__class__.__module__
self.assertEqual(expected_result, module, msg.format(
expected_result, module))
#@unittest.skip("Temporarily skipped")
[docs]
def test_tzinfo(self):
"""
The 'tzinfo` class is borrowed from the Python datetime package.
"""
import zoneinfo
data = (
(zoneinfo.ZoneInfo('America/New_York'), 'zoneinfo'),
)
msg = "Expected {}, found {}."
for instance, expected_result in data:
result = isinstance(instance, datetime.tzinfo)
self.assertTrue(result, msg.format(expected_result, result))
module = instance.__class__.__module__
self.assertEqual(expected_result, module, msg.format(
expected_result, module))
[docs]
class TestBadiDatetimeFunctions(unittest.TestCase):
def __init__(self, name):
super().__init__(name)
[docs]
@classmethod
def setUpClass(cls):
os.environ['LC_ALL'] = 'en_US.UTF-8'
locale.setlocale(locale.LC_TIME, 'en_US.UTF-8')
[docs]
def setUp(self):
self._bc = BahaiCalendar()
#@unittest.skip("Temporarily skipped")
[docs]
def test__cmp(self):
"""
Test that the _cmp method returns the the correct value for the
caparison.
"""
data = (
(10, 10, 0),
(10, 9, 1),
(10, 11, -1),
)
msg = "Expected {} with x {} and y {}, found {}."
for x, y, expected_result in data:
result = datetime._cmp(x, y)
self.assertEqual(expected_result, result, msg.format(
expected_result, x, y, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__divide_and_round(self):
"""
Test that the _divide_and_round function returns the correct result.
"""
data = (
((7, 3), 2),
((99, 4), 25),
((99, 3), 33),
)
msg = "Expected {} with values {}, found {}."
for values, expected_result in data:
result = datetime._divide_and_round(*values)
self.assertEqual(expected_result, result, msg.format(
expected_result, values, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__check_offset(self):
"""
Test that the _check_utc_offset function returns the correct result.
"""
err_msg0 = ("Invalid name argument '{}' must be one of "
"('utcoffset', 'badioffset', 'dst').")
err_msg1 = "tzinfo.{}() must return None or timedelta, not {}"
err_msg2 = ("{}()={}, must be strictly between -timedelta(hours=24) "
"and timedelta(hours=24), not {}")
data = (
('utcoffset', datetime.timedelta(hours=10), False, None),
('dst', datetime.timedelta(hours=1), False, None),
('utcoffset', None, False, None),
('junk', None, True, err_msg0.format('junk')),
('utcoffset', 10, True, err_msg1.format('utcoffset', type(10))),
('utcoffset', datetime.timedelta(hours=24), True,
err_msg2.format('utcoffset', '1 day, 0:00:00',
'datetime.timedelta(days=1)')),
)
msg = "Expected {} with name {} and offset {}, found {}."
for name, offset, validity, expected_result in data:
if validity:
try:
result = datetime._check_offset(name, offset)
except (AssertionError, TypeError, ValueError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(
f"With {name} and {offset} an error is "
f"not raised, with result {result}.")
else:
result = datetime._check_offset(name, offset)
self.assertEqual(expected_result, result, msg.format(
expected_result, name, offset, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__check_tzinfo_arg(self):
"""
Test that the _check_tzinfo_arg function returns the correct result.
"""
err_msg0 = ("tzinfo argument must be None or of a tzinfo subclass, "
"not {!r}")
data = (
(datetime.BADI, False, None),
('JUNK', True, err_msg0.format('str')),
)
msg = "Expected {} with tz {}, found {}."
for tz, validity, expected_result in data:
if validity:
try:
result = datetime._check_tzinfo_arg(tz)
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(
f"With {tz} an error is not raised, with "
f"result {result}.")
else:
result = datetime._check_tzinfo_arg(tz)
self.assertEqual(expected_result, result, msg.format(
expected_result, tz, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__cmperror(self):
"""
Test that the _cmperror
"""
err_msg0 = "Cannot compare {} to {}"
data = (
((181, 1, 1), (181, 1, 1),
err_msg0.format("'date'", "'datetime'")),
)
msg = "date0 {} and date1 {}."
for date0, date1, expected_result in data:
d = datetime.date(*date0)
dt = datetime.datetime(*date1)
try:
datetime._cmperror(d, dt)
except TypeError as e:
self.assertEqual(expected_result, str(e),
msg.format(date0, date1))
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
[docs]
def test__check_tzname(self):
"""
Test that the _check_tzname function raises a TypeError is the name
argument is not None or a string.
"""
err_msg0 = "tzinfo.tzname() must return None or string, not {!r}"
data = (
('', False, ''),
(None, False, ''),
(100, True, err_msg0.format('int')),
)
for name, validity, expected_result in data:
if validity:
try:
datetime._check_tzname(name)
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
raise AssertionError(
f"With {name} an error is not raised.")
else:
datetime._check_tzname(name)
#@unittest.skip("Temporarily skipped")
[docs]
def test__get_class_module(self):
"""
Test that the _get_class_module function returns the correct module
name.
"""
data = (
(datetime.date.today(), 'badidatetime'),
(datetime._IsoCalendarDate(182, 6, 1), 'badidatetime'),
(datetime.time(12, 30, 30), 'badidatetime'),
(datetime.datetime(182, 6, 4), 'badidatetime'),
(datetime.timezone.badi, 'badidatetime'),
(datetime.timedelta(1), 'datetime'),
(datetime.tzinfo(), 'datetime'),
)
msg = "Expected {} with instance {}, found {}."
for instance, expected_result in data:
result = datetime._get_class_module(instance)
self.assertEqual(expected_result, result, msg.format(
expected_result, repr(instance), result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__module_name(self):
"""
Test that the _module_name function returns the module path without
the base directory.
"""
data = (
((181, 1, 1), '__module__', 'datetime'),
((181, 1, 1), '__name__', 'date'),
((181, 1, 1, None, None, 12, 30, 30), '__module__', 'datetime'),
((181, 1, 1, None, None, 12, 30, 30), '__name__', 'datetime'),
)
msg = "Expected {} with date {} and module {}, found {}."
for date, mod, expected_result in data:
d_len = len(date)
if d_len < 6:
obj = datetime.date(*date)
else:
obj = datetime.datetime(*date)
result = datetime._module_name(getattr(obj.__class__, mod))
self.assertEqual(expected_result, result, msg.format(
expected_result, date, mod, result))
[docs]
class TestBadiDatetime_date(unittest.TestCase):
def __init__(self, name):
super().__init__(name)
[docs]
@classmethod
def setUpClass(cls):
os.environ['LC_ALL'] = 'en_US.UTF-8'
locale.setlocale(locale.LC_TIME, 'en_US.UTF-8')
#@unittest.skip("Temporarily skipped")
[docs]
def test___new__(self):
"""
Test that the __new__ method creates an instance from both a pickle
object and a normal instantiation.
"""
err_msg0 = ("Invalid kull-i-shay {}, it must be in the range "
"of [-5, 4].")
err_msg1 = "Invalid string {} had length of {} for pickle."
err_msg2 = ("A full short or long form Badí' date must be used, found "
"{} fields.")
err_msg3 = ("Failed to encode latin1 string when unpickling a date or "
"datetime instance. pickle.load(data, encoding='latin1') "
"is assumed.")
data = (
((1, 1, 1), False, '0001-01-01'),
((1, 1, 1, 1, 1), False, '01-01-01-01-01'),
((b'\x073\x01\x01',), False, '0001-01-01'),
((b'\x14\x01\x01\x01\x01',), False, '01-01-01-01-01'),
((b'\x073\x01\x01\x01',), True, err_msg0.format(-12)),
((b'\x14\x01\x01\x01\x01\x01',), True, err_msg1.format(
b'\x14\x01\x01\x01\x01\x01', 6)),
((100,), True, err_msg2.format(1)),
(('\u2190\x01\x01\x01',), True, err_msg3),
)
msg = "Expected {} with value {}, found {}."
for value, validity, expected_result in data:
if validity:
try:
result = datetime.date(*value)
except (AssertionError, ValueError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {value} an error is not "
f"raised, with result {result}.")
else:
result = datetime.date(*value)
self.assertEqual(expected_result, str(result),
msg.format(expected_result, value, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_is_short(self):
"""
Test that the is_short property properly indicates if the Badi
date is in the short or long form.
"""
data = (
((181, 9, 16), True),
((1, 10, 10, 9, 16), False),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.is_short
self.assertEqual(expected_result, result,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', datetime.GMT_COORD)
def test_fromtimestamp_utc(self):
"""
Test that the fromtimestamp class method creates an instance of
date from a POSIX timestamp for UTC time.
"""
data = (
# 1761683890 -> 2025-10-28T20:38:10Z
# Sunset before = 16:40 -> 20:28:10 - 16:40 = 03:58:10 ->
# 0182-12-15T03:58:10
(1761683890, True, '0182-12-15'),
# 2025-11-02T06:59:00Z -> Sunset bay before = 16:33
# This about 10.5 hours too early.
(1762084740, True, '0182-12-19'),
# 2025-11-02T16:00:00Z -> Sunset = 16:31
(1762117200, True, '0182-13-01'),
# 2025-11-02T22:19:00Z -> Sunset = 16:31
(1762121940, True, '0182-13-01'),
)
msg = "Expected {} with timestamp {}, found {}."
for ts, short, expected_result in data:
result = datetime.date.fromtimestamp(ts, short=short)
self.assertEqual(expected_result, str(result),
msg.format(expected_result, ts, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test_fromtimestamp_local(self):
"""
Test that the fromtimestamp class method creates an instance of
date from a POSIX timestamp for local time.
"""
data = (
(0, True, '0126-16-02'),
# 2024-08-07T19:04:27Z -> 2024-08-07T14:04:27-05:00
# Sunset day before 19:14 -> 24:00 - 19:14 = 04:46 ->
# 04:46 + 14:04:27 = 01-10-10-08-08T18:50:27
#(1723057467.0619307, False, '01-10-10-08-08'), # 01-10-10-08-09
#(1723057467.0619307, True, '0181-08-08'),
# *** TODO *** Fix the two above
# 2025-10-28T17:23:43Z -> 2025-10-28T12:23:43-05:00
# Sunset day before = 17:24 -> 24:00 - 17:24 = 06:36
# 06:36 + 12:23:43 = 18:59:43
(1761672223.8864158, True, '0182-12-14'),
# 2025-10-28T22:23:00Z -> 2025-10-28T17:23:00-05:00
# Sunset day before = 17:24 -> 24:00 - 17:24 = 06:36
# 06:36 + 17:23:00 = 23:59:00
(1761690180, True, '0182-12-14'),
# 2025-11-02T17:18:36Z -> 2025-11-02T12:18:36-05:00
# Sunset day before = 17:20 -> 24:00 - 17:20 = 06:40 ->
# 06:40 + 12:18:36 = 18:58:36
(1762103916.6480098, True, '0182-12-19'),
# 2025-11-02T22:19:00Z -> 2025-11-02T17:19:00-05:00
# Sunset 17:19 -> 17:19 - 17:19 = 00:00
(1762121940, True, '0182-13-01'),
)
msg = "Expected {} with timestamp {}, found {}."
for ts, short, expected_result in data:
result = datetime.date.fromtimestamp(ts, short=short)
self.assertEqual(expected_result, str(result),
msg.format(expected_result, ts, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', datetime.BADI_COORD)
def test_fromtimestamp_tehran(self):
"""
Test that the fromtimestamp class method creates an instance of
date from a POSIX timestamp for Tehran time.
"""
data = (
# 2025-10-28T17:12:39Z -> 2025-10-28T20:42:39
# Sunset = 17:14 -> 20:42:39 - 17:14 = 03:28:39
(1761671559.2112039, True, '0182-12-15'),
(1761690180, True, '0182-12-15'), # Sunset and day change
# Wrong is almost 5 hours early ()
#(1762103916.6480098, True, '0182-12-19'),
(1762121940, True, '0182-13-01'), # Sunset and day change
)
msg = "Expected {} with timestamp {}, found {}."
for ts, short, expected_result in data:
result = datetime.date.fromtimestamp(ts, short=short)
self.assertEqual(expected_result, str(result),
msg.format(expected_result, ts, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_today(self):
"""
Test that the today class method creates an instance of date
for today.
"""
dt_reg = r'badidatetime\.datetime\.date\((?P<date>.+)\)'
data = (
(False, 5),
(True, 3),
)
msg = "Expected {}, found {}."
for short, num in data:
result = datetime.date.today(short=short)
date_str = re.search(dt_reg, str(result))
if date_str:
date = [int(num.strip())
for num in date_str.group('date').split(',')]
self.assertEqual(len(date), num, msg.format(num, len(date)))
else:
self.assertIsNone(date_str, (
f"For short {short} and num {num}, could not get a "
"value from the regex."))
#@unittest.skip("Temporarily skipped")
[docs]
def test_fromordinal(self):
"""
Test that the fromordinal class method creates a date instance
from a date ordinal number.
local coords (35.5894, -78.7792, -5.0)
"""
err_msg = ("Astronomical JD {} lies in the Gregorian reform gap "
"(1582-10-05 through 1582-10-14); no Meeus JD exists.")
data = (
(78, False, True, '-05-18-01-01-01'),
(78, True, True, '-1842-01-01'),
(79, True, True, '-1842-01-02'),
(444, True, True, '-1841-01-01'),
(577724, True, True, '-261-11-08'), # 1582-10-04
(577735, True, True, '-261-11-19'), # 1582-10-15
(577736, True, True, '-261-12-01'), # 1582-10-16
(639785, True, True, '-091-09-16'),
(639786, True, True, '-091-09-17'),
(639796, True, True, '-091-10-08'),
(639797, True, True, '-091-10-09'),
(738964, True, True, '0181-01-01'),
# Error conditions, the JDs are shown not the ordinal.
(577725, True, False, err_msg.format(2299148.5)), # 1582-10-05
(577734, True, False, err_msg.format(2299157.5)), # 1582-10-14
)
msg = "Expected {} with ordinal {}, found {}."
for n, short, valid, expected_result in data:
if valid:
result = datetime.date.fromordinal(n, short=short)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, n, result))
else:
with self.assertRaises(ValueError) as cm:
datetime.date.fromordinal(n, short=short)
message = str(cm.exception)
self.assertEqual(expected_result, message)
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
[docs]
def test_fromisocalendar(self):
"""
Test that the fromisocalendar class method creates a date instance
from an ISO calendar date.
"""
err_msg = "Invalid weekday: {} (range is [1, 7])"
data = (
# year, week, day in week
((181, 1, 1), False, False, '01-10-09-19-17'),
((181, 1, 1), True, False, '0180-19-17'),
((181, 24, 7), True, False, '0181-09-13'),
((181, 1, 10), False, True, err_msg.format(10)),
)
msg = "Expected {} with iso {} and short {}, found {}."
for date, short, validity, expected_result in data:
if validity:
with self.assertRaises(AssertionError) as cm:
datetime.date.fromisocalendar(*date, short=short)
message = str(cm.exception)
self.assertEqual(expected_result, message)
else:
result = datetime.date.fromisocalendar(*date, short=short)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, short, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___repr__(self):
"""
Test that the __repr__ returns the expected formatted text.
"""
data = (
((181, 9, 16), 'badidatetime.date(181, 9, 16)'),
((1, 10, 10, 9, 16), 'badidatetime.date(1, 10, 10, 9, 16)'),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = repr(d)
self.assertEqual(expected_result, result,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
[docs]
def test_ctime(self):
"""
Test that the ctime method creates a string indicating the date.
All days before 1752-09-14 in the Gregorian Calendar will seem wrong
when compaired to the Badi Calendar in UK and the US. This is when
The Gregorian Calendar was adopted and compinsated 11 days.
"""
data = (
# 0001-03-19 Saturday (Kamál -> Monday)
#((-1842, 1, 1), 'Kamál Bahá 1 00:00:00 -1842'),
# 1582-10-04 Thursday (Jalál -> Saturday)
((-261, 11, 7), 'Jalál Mashíyyat 7 00:00:00 -0261'),
# 1582-10-15 Monday (Idāl -> Wednesday)
((-261, 11, 18), '`Idāl Mashíyyat 18 00:00:00 -0261'),
# 1700-03-19 Tuesday (Istiqlāl -> Friday)
((-143, 1, 1), 'Istiqlāl Bahá 1 00:00:00 -0143'),
# 1752-09-02 Wednesday (Istiqlāl -> Friday)
((-91, 9, 15), "Istiqlāl Asmá' 15 00:00:00 -0091"),
# 1752-09-14 Thursday
((-91, 10, 9), "Istijlāl 'Izzat 9 00:00:00 -0091"),
# 1800-03-20 Thursday
((-43, 1, 1), 'Istijlāl Bahá 1 00:00:00 -0043'),
# 1817-11-12 Wednesday Birthday of Bahá’u’lláh
((-26, 13, 10), '`Idāl Qudrat 10 00:00:00 -0026'),
# 1825-03-20 Saturday
((-18, 1, 1), 'Jamál Bahá 1 00:00:00 -0018'),
# 1843-03-20 Monday
((0, 1, 1), 'Kamál Bahá 1 00:00:00 0000'),
# 1844-03-19 Tuesday
((1, 1, 1), 'Fiḍāl Bahá 1 00:00:00 0001'),
# 1862-03-20 Thursday
((19, 1, 1), 'Istijlāl Bahá 1 00:00:00 0019'),
# 1881-03-19 Saturday
((38, 1, 1), 'Jalál Bahá 1 00:00:00 0038'),
# 1900-03-20 Tuesday
((57, 1, 1), 'Fiḍāl Bahá 1 00:00:00 0057'),
# 2014-03-20 Thursday
((171, 1, 1), 'Istijlāl Bahá 1 00:00:00 0171'),
# 2024-03-19 Tuesday
((181, 1, 1), 'Fiḍāl Bahá 1 00:00:00 0181'),
# 2024-08-14 Wednesday
((181, 8, 16), '`Idāl Kamál 16 00:00:00 0181'),
# 2024-08-14 Wednesday
((1, 10, 10, 8, 16), '`Idāl Kamál 16 00:00:00 0181'),
# 2024-08-15 Thursday
((1, 10, 10, 8, 17), 'Istijlāl Kamál 17 00:00:00 0181'),
# 2033-03-19 Saturday
((190, 1, 1), 'Jalál Bahá 1 00:00:00 0190'),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.ctime()
self.assertEqual(expected_result, str(result),
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch('badidatetime._timedateutils.TimeDateUtils.date_format',
new_callable=PropertyMock)
def test_strftime(self, mock_property):
"""
Test that the strftime method returns a formatted date time string.
We need to mock the date_format property because everywhere is not
here.
"""
mock_property.return_value = ['/', 'm', 'd', 'Y']
data = (
((181, 19, 1), '%D', '19/01/81'),
((1, 10, 10, 19, 1), '%D', '19/01/81'),
((1, 1, 1), '%x', '01/01/0001'),
((181, 11, 17), '%c', 'Isq Mas 17 00:00:00 0181'),
)
msg = "Expected {} with date {} and format {}, found {}."
for date, fmt, expected_result in data:
d = datetime.date(*date)
result = d.strftime(fmt)
self.assertEqual(expected_result, result,
msg.format(expected_result, date, fmt, result))
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
[docs]
def test___str__(self):
"""
Test that the __str__ method returns the ISO formated version of
the date represented by the class object.
"""
data = (
((181, 1, 1), '0181-01-01'),
((1, 10, 10, 8, 15), '01-10-10-08-15'),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
result = datetime.date(*date)
self.assertEqual(expected_result, str(result),
msg.format(expected_result, date, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
def test_kull_i_shay(self):
"""
Test that the kull_i_shay property returns the kull_i_shay value.
"""
data = (
((1, 10, 10, 1, 1), 1),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.kull_i_shay
self.assertEqual(expected_result, d.kull_i_shay,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_vahid(self):
"""
Test that the vahid property returns the vahid value.
"""
data = (
((1, 10, 10, 1, 1), 10),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.vahid
self.assertEqual(expected_result, d.vahid,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_year(self):
"""
Test that the year property returns the year value.
"""
data = (
((181, 1, 1), 181),
((1, 10, 10, 1, 1), 10),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.year
self.assertEqual(expected_result, d.year,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_month(self):
"""
Test that the month property returns the month value.
"""
data = (
((181, 1, 1), 1),
((1, 10, 10, 1, 1), 1),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.month
self.assertEqual(expected_result, d.month,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_day(self):
"""
Test that the day property returns the day value.
"""
data = (
((181, 1, 1), 1),
((1, 10, 10, 1, 1), 1),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.day
self.assertEqual(expected_result, d.day,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_timetuple(self):
"""
Test that the timetuple returns the correct long or short form object.
"""
data = (
((181, 9, 6),
"structures.ShortFormStruct(tm_year=181, tm_mon=9, tm_mday=6, "
"tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=158, "
"tm_isdst=-1)"),
((1, 10, 10, 9, 6),
"structures.LongFormStruct(tm_kull_i_shay=1, tm_vahid=10, "
"tm_year=10, tm_mon=9, tm_mday=6, tm_hour=0, tm_min=0, tm_sec=0, "
"tm_wday=6, tm_yday=158, tm_isdst=-1)")
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.timetuple()
self.assertEqual(expected_result, str(result),
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_toordinal(self):
"""
Test that the toordinal method returns a proleptic Badi ordinal.
"""
data = (
#((-1842, 1, 1), 78),
((1, 1, 1), 673220),
((181, 1, 1), 738964),
((181, 8, 15), 739111),
((1, 10, 10, 8, 15), 739111),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.toordinal()
self.assertEqual(expected_result, result,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_replace(self):
"""
Test that the replace method returns a new date object with the
replaced values.
"""
def execute_replace(date2):
if short:
year, month, day = date2
result = d.replace(year=year, month=month, day=day)
else:
kull_i_shay, vahid, year, month, day = date2
result = d.replace(kull_i_shay=kull_i_shay, vahid=vahid,
year=year, month=month, day=day)
return result
err_msg0 = "Cannot convert from a short to a long form date."
err_msg1 = ("Cannot convert from a long to a short form date. The "
"value {} is not valid for long form dates.")
data = (
# Normal replace for a short date
((181, 1, 1), (182, None, None), True, False, '0182-01-01'),
((181, 1, 1), (None, 9, 12), True, False, '0181-09-12'),
# Normal replace for a long date
((1, 10, 10, 1, 1), (None, None, 11, None, None), False, False,
'01-10-11-01-01'),
((1, 10, 10, 1, 1), (None, 9, None, None, None), False, False,
'01-09-10-01-01'),
((1, 10, 10, 1, 1), (None, 9, 10, None, None), False, False,
'01-09-10-01-01'),
# Error conditions.
((181, 1, 1), (1, 10, None, None, None), False, True, err_msg0),
((1, 10, 10, 1, 1), (181, 1, None), True, True,
err_msg1.format(181)),
)
msg = "Expected {} with date1 {}, date2 {}, and short {}, found {}."
for date1, date2, short, validity, expected_result in data:
d = datetime.date(*date1)
if validity:
try:
result = execute_replace(date2)
except ValueError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date1}' an error is not "
f"raised, with result {result}.")
else:
result = execute_replace(date2)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date1, date2, short, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
def test___eq__(self):
"""
Test that the __eq__ method returns True if equal and False if
not equal.
"""
data = (
((181, 9, 14), (181, 9, 14), True),
((181, 9, 14), (181, 9, 13), False),
((181, 9, 14), (181, 9, 15), False),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 14), True),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 13), False),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 15), False),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, date1, expected_result in data:
d0 = datetime.date(*date0)
d1 = datetime.date(*date1)
result = d0 == d1
self.assertEqual(expected_result, result,
msg.format(expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___le__(self):
"""
Test that the __le__ method returns True if less than or equal and
False if not less than or equal.
"""
data = (
((181, 9, 14), (181, 9, 14), True),
((181, 9, 14), (181, 9, 13), False),
((181, 9, 14), (181, 9, 15), True),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 14), True),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 13), False),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 15), True),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, date1, expected_result in data:
d0 = datetime.date(*date0)
d1 = datetime.date(*date1)
result = d0 <= d1
self.assertEqual(expected_result, result,
msg.format(expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___lt__(self):
"""
Test that the __lt__ method returns True if less than and False
if not less than.
"""
data = (
((181, 9, 14), (181, 9, 14), False),
((181, 9, 14), (181, 9, 13), False),
((181, 9, 14), (181, 9, 15), True),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 14), False),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 13), False),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 15), True),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, date1, expected_result in data:
d0 = datetime.date(*date0)
d1 = datetime.date(*date1)
result = d0 < d1
self.assertEqual(expected_result, result,
msg.format(expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___ge__(self):
"""
Test that the __ge__ method returns True if greater than or equal
and False if not greater than or equal.
"""
data = (
((181, 9, 14), (181, 9, 14), True),
((181, 9, 14), (181, 9, 13), True),
((181, 9, 14), (181, 9, 15), False),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 14), True),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 13), True),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 15), False),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, date1, expected_result in data:
d0 = datetime.date(*date0)
d1 = datetime.date(*date1)
result = d0 >= d1
self.assertEqual(expected_result, result,
msg.format(expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___gt__(self):
"""
Test that the __gt__ method returns True if greater than and False
if not greater than.
"""
data = (
((181, 9, 14), (181, 9, 14), False),
((181, 9, 14), (181, 9, 13), True),
((181, 9, 14), (181, 9, 15), False),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 14), False),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 13), True),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 15), False),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, date1, expected_result in data:
d0 = datetime.date(*date0)
d1 = datetime.date(*date1)
result = d0 > d1
self.assertEqual(expected_result, result,
msg.format(expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__cmp(self):
"""
Test that the _cmp method returns 1 if the two dates are equal, +1
if the current date is greater than the test date, and -1 if the
inverse.
"""
data = (
((181, 9, 14), (181, 9, 14), 0),
((181, 9, 14), (181, 9, 13), 1),
((181, 9, 14), (181, 9, 15), -1),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 14), 0),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 13), 1),
((1, 10, 10, 9, 14), (1, 10, 10, 9, 15), -1),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, date1, expected_result in data:
d0 = datetime.date(*date0)
d1 = datetime.date(*date1)
result = d0._cmp(d1)
self.assertEqual(expected_result, result,
msg.format(expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___hash__(self):
"""
Test that the __hash__ method returns a valid hash for both short
and long form dates.
"""
data = (
(datetime.MINYEAR, 1, 1),
(-5, 18, 1, 1, 1),
(1, 1, 1),
(1, 1, 1, 1, 1),
)
msg = "date {}, found {}."
for date in data:
d = datetime.date(*date)
result = hash(d)
self.assertTrue(len(str(result)) > 15, msg.format(date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___add__(self):
"""
Test that the __add__ method can correctly add a date to a timedelta.
"""
err_msg0 = "unsupported operand type(s) for +: 'date' and '{}'"
err_msg1 = "Result out of range."
data = (
((1, 1, 1), (1,), False, (1, 1, 2)),
((1, 1, 1), (366,), False, (2, 1, 1)), # Leap year
((181, 1, 1), (365,), False, (182, 1, 1)), # Non leap year
((1, 1, 1, 1, 1), (366,), False, (1, 1, 2, 1, 1)), # Leap year
((1, 1, 1), None, True, err_msg0.format('NoneType')),
((-1842, 1, 1), (-1,), True, err_msg1),
((1161, 19, 19), (1,), True, err_msg1),
)
msg = "Expected {} with date {} and timedelta {}, found {}"
for date, td, validity, expected_result in data:
d0 = datetime.date(*date)
if validity:
if isinstance(td, tuple):
td0 = datetime.timedelta(*td)
else:
td0 = td
try:
result = d0 + td0
except (OverflowError, TypeError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date}' an error is not "
f"raised, with result {result}.")
else:
td0 = datetime.timedelta(*td)
d1 = d0 + td0
if d1.is_short:
result = (d1.year, d1.month, d1.day)
else:
result = (d1.kull_i_shay, d1.vahid, d1.year,
d1.month, d1.day)
self.assertEqual(expected_result, result, msg.format(
expected_result, date, td, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___sub__(self):
"""
Test that the __sub__ method returns the correct results of a
timedelta object subtracted from a date object.
"""
err_msg0 = "unsupported operand type(s) for -: 'date' and '{}'"
data = (
((1, 1, 1), 1, False, (0, 19, 19)),
((2, 1, 1), 366, False, (1, 1, 1)), # Leap year
((181, 1, 1), 365, False, (180, 1, 1)), # Non Leap year
((182, 1, 1), (181, 1, 1), False, (365, 0, 0)),
((1, 1, 1), None, True, err_msg0.format('NoneType')),
)
msg = "Expected {} with date {} and value {}, found {}"
for date, value, validity, expected_result in data:
d0 = datetime.date(*date)
if validity:
try:
result = d0 - value
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date}' an error is not "
f"raised, with result {result}.")
else:
if isinstance(value, int):
dt = datetime.timedelta(value)
d1 = d0 - dt
result = (d1.year, d1.month, d1.day)
else:
d1 = datetime.date(*value)
dt = d0 - d1
result = (dt.days, dt.seconds, dt.microseconds)
self.assertEqual(expected_result, result, msg.format(
expected_result, date, value, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_weekday(self):
"""
Test that the weekday method returns the correct weekday number.
"""
data = (
((181, 1, 1), 3), # Fiḍāl
((181, 10, 8), 6), # Istiqlāl
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.weekday()
self.assertEqual(expected_result, result,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_isoweekday(self):
"""
Test that the weekday method returns the correct weekday number.
"""
data = (
((181, 1, 1), 4), # Fiḍāl -> Tuesday
((181, 10, 8), 7), # Istiqlāl -> Friday
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d.isoweekday()
self.assertEqual(expected_result, result,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_isocalendar(self):
"""
Test that the isocalendar method the correct ISO Calendar tuple.
"""
data = (
((181, 1, 1), (181, 1, 4)), # Short form
((1, 10, 10, 1, 1), (181, 1, 4)), # Long form
((181, 0, 1), (181, 50, 3)), # 0 < week < 53
((181, 19, 19), (181, 53, 4)), # 0 < week < 53
((182, 1, 1), (181, 53, 5)), # Week >= 52 starts in previous year
((183, 19, 19), (183, 52, 7)), # Week >= 52 starts in previous year
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = tuple(d.isocalendar())
self.assertEqual(expected_result, result,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__is_pickle_data(self):
"""
Test that the _is_pickle_data classmethod returns the correct results
depending on the incoming data.
"""
err_msg0 = "Invalid string {} had length of {} for pickle."
err_msg1 = ("Failed to encode latin1 string when unpickling a date or "
"datetime instance. pickle.load(data, encoding='latin1') "
"is assumed.")
data = (
((b'\x073\x01\x01', None), False, True),
((b'\x14\x01\x01\x01\x01', None), False, False),
((181, 10), False, None),
((b'\x073\x20\x01', None), False, None),
((b'\x14\x01\x01\x14\x01', None), False, None),
((b'\x14\x01\x01\x01\x01\x01', None), True, err_msg0.format(
b'\x14\x01\x01\x01\x01\x01', 6)),
(('\u2190\x01\x01\x01', None), True, err_msg1),
)
msg = "Expected {} with value {}, found {}."
for value, validity, expected_result in data:
if validity:
try:
result = datetime.date._is_pickle_data(*value)
except (AssertionError, ValueError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {value} an error is not "
f"raised, with result {result}.")
else:
result = datetime.date._is_pickle_data(*value)
self.assertEqual(expected_result, result,
msg.format(expected_result, value, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__getstate(self):
"""
Test that the _getstate method returns the state of the class.
"""
data = (
((datetime.MINYEAR, 1, 1), (b'\x00\x00\x01\x01',)),
((-5, 18, 1, 1, 1), (b'\x0e\x12\x01\x01\x01',)),
((1, 1, 1), (b'\x073\x01\x01',)),
((1, 1, 1, 1, 1), (b'\x14\x01\x01\x01\x01',)),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime.date(*date)
result = d._getstate()
self.assertEqual(expected_result, result,
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___setstate(self):
"""
Test that the __setstate method sets the date properly.
"""
data = (
((datetime.MINYEAR, 1, 1), b'\x00\x00\x01\x01'),
((-5, 18, 1, 1, 1), b'\x0e\x12\x01\x01\x01'),
((1, 1, 1), b'\x073\x01\x01'),
((1, 1, 1, 1, 1), b'\x14\x01\x01\x01\x01'),
)
msg = "Expected {} with bytes_str {}, found {}."
for date, bytes_str in data:
d = datetime.date(*date)
d._date__setstate(bytes_str)
if len(date) == 3:
result = (d._year, d._month, d._day)
else:
result = (d._kull_i_shay, d._vahid, d._year, d._month, d._day)
self.assertEqual(date, result, msg.format(date, bytes_str, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___reduce__(self):
"""
Test that the __reduce__ method works for both short and long
form Badi dates.
"""
data = (
(datetime.MINYEAR, 1, 1),
(1, 1, 1),
(1, 1, 1, 1, 1),
(datetime.MAXYEAR, 1, 1),
)
msg = "Expected {}, with date {}, found {}"
for date in data:
date0 = datetime.date(*date)
obj = pickle.dumps(date0)
date1 = pickle.loads(obj)
if len(date) == 3:
b_date0 = (date0._year, date0._month, date0._day)
b_date1 = (date1._year, date1._month, date1._day)
else:
b_date0 = (date0._kull_i_shay, date0._vahid,
date0._year, date0._month, date0._day)
b_date1 = (date1._kull_i_shay, date1._vahid,
date1._year, date1._month, date1._day)
self.assertEqual(b_date0, b_date1, msg.format(
b_date0, date, b_date1))
[docs]
class TestBadiDatetime__IsoCalendarDate(unittest.TestCase):
def __init__(self, name):
super().__init__(name)
#@unittest.skip("Temporarily skipped")
[docs]
def test_year(self):
"""
Test that the year property returns the year.
"""
data = (
# year, week, weekday
((1, 1, 1), 1),
)
msg = "Expected {}, with date {}, found {}"
for date, expected_result in data:
d = datetime._IsoCalendarDate(*date)
result = d.year
self.assertEqual(expected_result, result, msg.format(
expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_week(self):
"""
Test that the week property returns the week.
"""
data = (
# year, week, weekday
((1, 1, 1), 1),
)
msg = "Expected {}, with date {}, found {}"
for date, expected_result in data:
d = datetime._IsoCalendarDate(*date)
result = d.week
self.assertEqual(expected_result, result, msg.format(
expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_weekday(self):
"""
Test that the weekday property returns the weekday.
"""
data = (
# year, week, weekday
((1, 1, 1), 1),
)
msg = "Expected {}, with date {}, found {}"
for date, expected_result in data:
d = datetime._IsoCalendarDate(*date)
result = d.weekday
self.assertEqual(expected_result, result, msg.format(
expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___reduce__(self):
"""
Test that the __reduce__ method works for both short and long
form Badi dates.
"""
data = (
(datetime.MINYEAR, 1, 1),
(1, 1, 1),
(datetime.MAXYEAR, 1, 1),
)
msg = "Expected {}, with date {}, found {}"
for date in data:
date0 = datetime._IsoCalendarDate(*date)
obj = pickle.dumps(date0)
date1 = pickle.loads(obj)
b_date0 = (date0.year, date0.week, date0.weekday)
b_date1 = (date1[0], date1[1], date1[2])
self.assertEqual(b_date0, b_date1, msg.format(
b_date0, date, b_date1))
#@unittest.skip("Temporarily skipped")
[docs]
def test___repr__(self):
"""
Test that the __repr__ returns the expected formatted text.
"""
data = (
((181, 9, 16), '_IsoCalendarDate(year=181, week=9, weekday=16)'),
((1, 1, 1), '_IsoCalendarDate(year=1, week=1, weekday=1)'),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
d = datetime._IsoCalendarDate(*date)
result = repr(d)
self.assertEqual(expected_result, str(result),
msg.format(expected_result, date, result))
[docs]
class TestBadiDatetime_time(unittest.TestCase):
def __init__(self, name):
super().__init__(name)
[docs]
@classmethod
def setUpClass(cls):
os.environ['LC_ALL'] = 'en_US.UTF-8'
locale.setlocale(locale.LC_TIME, 'en_US.UTF-8')
#@unittest.skip("Temporarily skipped")
[docs]
def test___new__(self):
"""
Test that the __new__ method creates an instance from both a pickle
object and a normal instantiation.
"""
err_msg0 = ("Failed to encode latin1 string when unpickling a time "
"instance. pickle.load(data, encoding='latin1') is "
"assumed.")
data = (
((12, 30), None, 0, False, '12:30:00'),
((12, 30, 30), None, 0, False, '12:30:30'),
((12, 30, 30, 10), None, 0, False, '12:30:30.000010'),
((12, 30, 30, 50000), datetime.BADI, 0, False,
'12:30:30.050000+03:30'),
((12, 30, 30, 50000), None, 0, False, '12:30:30.050000'),
# Test errors when picking
(('\u2190\x0c\x1e\x1e\x07\xa1', None), None, 0, True, err_msg0),
)
msg = "Expected {} with value {}, found {}."
for value, tz, fold, validity, expected_result in data:
if validity:
try:
result = datetime.time(*value, tzinfo=tz, fold=fold)
except (AssertionError, ValueError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {value} an error is not "
f"raised, with result {result}.")
else:
result = datetime.time(*value, tzinfo=tz, fold=fold)
self.assertEqual(expected_result, str(result),
msg.format(expected_result, value, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_hour(self):
"""
Test that the hour property returns the correct value.
"""
data = (
((12, 30), 12),
((24, 0), 24),
)
msg = "Expected {} with time {}, found {}."
for time, expected_result in data:
td = datetime.time(*time)
result = td.hour
self.assertEqual(expected_result, result, msg.format(
expected_result, time, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
def test_minute(self):
"""
Test that the minute returns the correct value.
"""
data = (
((12, 30), 30),
((24, 10), 10),
)
msg = "Expected {} with time {}, found {}."
for time, expected_result in data:
td = datetime.time(*time)
result = td.minute
self.assertEqual(expected_result, result, msg.format(
expected_result, time, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
def test_second(self):
"""
Test that the second returns the correct value.
"""
data = (
((12, 30, 30), 30),
((24, 10, 20), 20),
)
msg = "Expected {} with time {}, found {}."
for time, expected_result in data:
td = datetime.time(*time)
result = td.second
self.assertEqual(expected_result, result, msg.format(
expected_result, time, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
def test_microsecond(self):
"""
Test that the microsecond returns the correct value.
"""
data = (
((12, 30, 30, 1), 1),
((24, 10, 20, 999999), 999999),
)
msg = "Expected {} with time {}, found {}."
for time, expected_result in data:
td = datetime.time(*time)
result = td.microsecond
self.assertEqual(expected_result, result, msg.format(
expected_result, time, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
def test_tzinfo(self):
"""
Test that the tzinfo returns the correct value.
"""
data = (
((12, 30, 30), datetime.BADI,
'35.69435, 51.288701, 3.5, Asia/Tehran'),
((24, 10, 20), datetime.UTC, '51.477928, -0.001545, 0, UTC'),
)
msg = "Expected {} with time {}, found {}."
for time, tz, expected_result in data:
td = datetime.time(*time, tzinfo=tz)
result = td.tzinfo
self.assertEqual(expected_result, str(result), msg.format(
expected_result, time, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
def test_fold(self):
"""
Test that the fold returns the correct value.
"""
data = (
((12, 30, 30, 1), 0, 0),
((24, 10, 20, 999999), 1, 1),
)
msg = "Expected {} with time {}, found {}."
for time, fold, expected_result in data:
td = datetime.time(*time, fold=fold)
result = td.fold
self.assertEqual(expected_result, result, msg.format(
expected_result, time, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
def test___eq__(self):
"""
Test that the __eq__ method returns True if equal and False if
not equal.
"""
data = (
((12, 30, 30, 10000), (12, 30, 30, 10000), True),
((12, 30, 30), (12, 30, 29), False),
((12, 30, 30), (12, 30, 31), False),
)
msg = "Expected {} with time0 {} and time1 {}, found {}."
for time0, time1, expected_result in data:
t0 = datetime.time(*time0)
t1 = datetime.time(*time1)
result = t0 == t1
self.assertEqual(expected_result, result, msg.format(
expected_result, time0, time1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___le__(self):
"""
Test that the __le__ method returns True if less than or equal and
False if not less than or equal.
"""
data = (
((12, 30, 30, 10000), (12, 30, 30, 10000), True),
((12, 30, 30), (12, 30, 29), False),
((12, 30, 30), (12, 30, 31), True),
)
msg = "Expected {} with time0 {} and time1 {}, found {}."
for time0, time1, expected_result in data:
t0 = datetime.time(*time0)
t1 = datetime.time(*time1)
result = t0 <= t1
self.assertEqual(expected_result, result, msg.format(
expected_result, time0, time1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___lt__(self):
"""
Test that the __lt__ method returns True if less than and False
if not less than.
"""
data = (
((12, 30, 30, 10000), (12, 30, 30, 10000), False),
((12, 30, 30), (12, 30, 29), False),
((12, 30, 30), (12, 30, 31), True),
)
msg = "Expected {} with time0 {} and time1 {}, found {}."
for time0, time1, expected_result in data:
t0 = datetime.time(*time0)
t1 = datetime.time(*time1)
result = t0 < t1
self.assertEqual(expected_result, result, msg.format(
expected_result, time0, time1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___ge__(self):
"""
Test that the __ge__ method returns True if greater than or equal
and False if not greater than or equal.
"""
data = (
((12, 30, 30, 10000), (12, 30, 30, 10000), True),
((12, 30, 30), (12, 30, 29), True),
((12, 30, 30), (12, 30, 31), False),
)
msg = "Expected {} with time0 {} and time1 {}, found {}."
for time0, time1, expected_result in data:
t0 = datetime.time(*time0)
t1 = datetime.time(*time1)
result = t0 >= t1
self.assertEqual(expected_result, result, msg.format(
expected_result, time0, time1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___gt__(self):
"""
Test that the __gt__ method returns True if greater than and False
if not greater than.
"""
data = (
((12, 30, 30, 10000), (12, 30, 30, 10000), False),
((12, 30, 30), (12, 30, 29), True),
((12, 30, 30), (12, 30, 31), False),
)
msg = "Expected {} with time0 {} and time1 {}, found {}."
for time0, time1, expected_result in data:
t0 = datetime.time(*time0)
t1 = datetime.time(*time1)
result = t0 > t1
self.assertEqual(expected_result, result, msg.format(
expected_result, time0, time1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__cmp(self):
"""
Test that the _cmp method returns 1 if the two times are equal, +1
if the current time is greater than the test time, and -1 if the
inverse.
"""
err_msg0 = "Invalid time module, found {}."
err_msg1 = "Cannot compare naive and aware times."
data = (
((12, 30, 30, 10000), None, 0, True,
(12, 30, 30, 10000), None, 0, False, 0),
((12, 30, 30), None, 0, False, (12, 30, 29), None, 0, False, 1),
((12, 30, 30), None, 0, False, (12, 30, 31), None, 0, False, -1),
((12, 30, 30, 10000), datetime.BADI, 0, True,
(12, 30, 30, 10000), datetime.BADI, 0, False, 0),
# Timezone infos are different
((12, 30, 30, 10000), datetime.BADI, 0, False,
(12, 30, 30, 10000), datetime.UTC, 0, False, -1),
((12, 30, 30, 10000), datetime.UTC, 0, False,
(12, 30, 30, 10000), datetime.BADI, 0, False, 1),
# If allow_mixed is True and timezones are different.
((12, 30, 30, 10000), datetime.BADI, 0, True,
(12, 30, 30, 10000), None, 0, False, 2),
# Errors
((12, 30, 30, 10000), None, 0, False,
(), None, 0, True, err_msg0.format(None)),
((12, 30, 30, 10000), datetime.BADI, 0, False,
(12, 30, 30, 10000), None, 0, True, err_msg1),
)
msg = "Expected {} with time0 {} and time1 {}, found {}."
for (time0, tz0, fold0, am, time1, tz1, fold1,
validity, expected_result) in data:
t0 = datetime.time(*time0, tzinfo=tz0, fold=fold0)
if validity:
try:
if time1 == ():
t1 = None
else:
t1 = datetime.time(*time1, tzinfo=tz1, fold=fold1)
result = t0._cmp(t1, allow_mixed=am)
except (AssertionError, TypeError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {time0} an error is not "
f"raised, with result {result}.")
else:
t1 = datetime.time(*time1, tzinfo=tz1, fold=fold1)
result = t0._cmp(t1, allow_mixed=am)
self.assertEqual(expected_result, result, msg.format(
expected_result, time0, time1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___hash__(self):
"""
Test that the __hash__ method returns the proper hash of the class.
"""
data = (
((1, 30, 30), None, 0),
((1, 30, 30), None, 1),
((1, 30, 30, 500000), None, 0),
((3, 30), datetime.BADI, 0),
# Test for negative hours.
((0, 30), datetime.BADI, 0),
)
msg = "time {}, timezone {}, and fold {}, found {}."
for time, tz, fold in data:
t = datetime.time(*time, tzinfo=tz, fold=fold)
result = str(hash(t))
self.assertTrue(len(result) > 15, msg.format(
time, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__tzstr(self):
"""
Test that the _tzstr method returns a formatted timezone offset.
"""
tz0 = ZoneInfo('US/Eastern')
data = (
((1, 30, 30, 500000), datetime.BADI, 0, '+03:30'),
# tzinfo object without a datetime always returns None for offset.
((12, 16, 4, 500000), tz0, 0, ''),
)
msg = "Expected {} with time {}, timezone {}, and fold {}, found {}."
for time, tz, fold, expected_result in data:
t = datetime.time(*time, tzinfo=tz, fold=fold)
result = t._tzstr()
self.assertEqual(expected_result, result, msg.format(
expected_result, time, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___repr__(self):
"""
Test that the __repr__ method returns the correct string.
"""
data = (
((0, 0, 0, 0), None, 0, 'badidatetime.time(0, 0)'),
((1, 30), None, 0, 'badidatetime.time(1, 30)'),
((1, 30, 30), None, 0, 'badidatetime.time(1, 30, 30)'),
((1, 30, 30, 50000), None, 0,
'badidatetime.time(1, 30, 30, 50000)'),
((1, 30, 30, 50000), datetime.BADI, 0,
'badidatetime.time(1, 30, 30, 50000, '
'tzinfo=35.69435, 51.288701, 3.5, Asia/Tehran)'),
((1, 30, 30, 50000), datetime.BADI, 1,
'badidatetime.time(1, 30, 30, 50000, '
'tzinfo=35.69435, 51.288701, 3.5, Asia/Tehran, fold=1)'),
)
msg = "Expected {} with time {}, timezone {}, and fold {}, found {}."
for time, tz, fold, expected_result in data:
d = datetime.time(*time, tzinfo=tz, fold=fold)
result = repr(d)
self.assertEqual(expected_result, result, msg.format(
expected_result, time, tz, fold, result))
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
[docs]
def test_strftime(self):
"""
Test that the strftime method returns a correctly formatting string.
"""
tz = ZoneInfo(datetime.BADI_IANA)
tz0 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.BADI_COORD)
data = (
((1, 30, 30), '%X', None, '01:30:30'),
((1, 30, 30), '%r', None, '01:30:30 AM'),
((1, 30, 30), '%c', None, 'Jal Bah 01 01:30:30 0001'),
((1, 30, 30, 500000), '%T.%f', None, '01:30:30.500000'),
((1, 30, 30, 500000), 'T%H:%M:%S.%f', None, 'T01:30:30.500000'),
((1, 30, 30, 500000), '%z', tz0, '+0350'),
((1, 30, 30, 500000), '%Z', tz0, 'Asia/Tehran'),
((1, 30, 30, 500000), '%%', None, '%'),
((1, 30, 30, 500000), '%', None, ''),
)
msg = "Expected {} with time {}, format {}, and tz {} found {}."
for time, fmt, tz, expected_result in data:
result = datetime.time(*time, tzinfo=tz).strftime(fmt)
self.assertEqual(expected_result, result, msg.format(
expected_result, time, fmt, tz, result))
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
[docs]
def test_utcoffset(self):
"""
Test that the utcoffset method returns the correct timezone offset.
"""
tz0 = ZoneInfo('US/Eastern')
data = (
((1, 30, 30, 500000), None, 0, 'None'),
((1, 30, 30, 500000), datetime.BADI, 0, '3:30:00'),
((1, 30, 30, 500000), tz0, 0, 'None'),
)
msg = "Expected {} with time {}, timezone {}, and fold {}, found {}."
for time, tz, fold, expected_result in data:
t = datetime.time(*time, tzinfo=tz, fold=fold)
result = t.utcoffset()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, time, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_badioffset(self):
"""
Test that the badioffset
"""
tz0 = ZoneInfo('US/Eastern')
data = (
((1, 30, 30, 500000), None, 0, 'None'),
((1, 30, 30, 500000), datetime.BADI, 0, '0:00:00'),
((1, 30, 30, 500000), tz0, 0, 'None'),
((1, 30, 30, 500000), datetime.UTC, 0, '-1 day, 20:30:00'),
)
msg = "Expected {} with time {}, timezone {}, and fold {}, found {}."
for time, tz, fold, expected_result in data:
t = datetime.time(*time, tzinfo=tz, fold=fold)
result = t.badioffset()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, time, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_tzname(self):
"""
Test that the tzname method returns the timezone name.
"""
tz0 = ZoneInfo('US/Eastern')
data = (
((12, 30, 30), None, 0, None),
((1, 30, 30, 500000), datetime.BADI, 0, 'Asia/Tehran'),
((1, 30, 30, 500000), tz0, 0, None),
((1, 30, 30, 500000), datetime.UTC, 0, 'UTC'),
)
msg = "Expected {} with time {}, timezone {}, and fold {}, found {}."
for time, tz, fold, expected_result in data:
t = datetime.time(*time, tzinfo=tz, fold=fold)
result = t.tzname()
self.assertEqual(expected_result, result, msg.format(
expected_result, time, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test_dst(self):
"""
Test that the dst method returns either 0 or 1 if DST is in effect.
"""
tz0 = ZoneInfo('US/Eastern')
tz1 = datetime.TZWithCoords(*datetime.LOCAL_COORD)
tz2 = datetime.TZWithCoords.fromzoneinfo(tz0, *datetime.LOCAL_COORD)
data = (
((12, 30, 30), None, 0, None),
((1, 30, 30, 500000), datetime.BADI, 0, '0:00:00'),
((1, 30, 30, 500000), tz0, 0, None),
((1, 30, 30, 500000), tz1, 0, '0:00:00'),
((1, 30, 30, 500000), tz2, 0, '0:00:00'),
((1, 30, 30, 500000), datetime.UTC, 0, '0:00:00'),
)
msg = "Expected {} with time {}, timezone {}, and fold {}, found {}."
for time, tz, fold, expected_result in data:
t = datetime.time(*time, tzinfo=tz, fold=fold)
dst = t.dst()
result = dst if dst is None else str(dst)
self.assertEqual(expected_result, result, msg.format(
expected_result, time, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_replace(self):
"""
Test that the replace
"""
data = (
((12, 30, 30, 500000), None, 0,
(6, None), None, None, '06:30:30.500000'),
((12, 30, 30, 500000), None, 0,
(None, 15), None, None, '12:15:30.500000'),
((12, 30, 30, 500000), None, 0,
(None, None, 15), None, None, '12:30:15.500000'),
((12, 30, 30, 500000), None, 0,
(None, None, None, 999999), None, None, '12:30:30.999999'),
((12, 30, 30, 500000), None, 0,
(), datetime.BADI, None, '12:30:30.500000+03:30'),
((12, 30, 30, 500000), None, 0, (), None, 1, '12:30:30.500000'),
)
msg = "Expected {} with time0 {}, and time1 {}, found {} "
for time0, tz0, fold0, time1, tz1, fold1, expected_result in data:
t = datetime.time(*time0, tzinfo=tz0, fold=fold0)
result = t.replace(*time1, tzinfo=tz1, fold=fold1)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, time0, time1, str(result)))
if tz0 != tz1:
self.assertEqual(tz1, result.tzinfo, msg.format(
expected_result, time0, time1, result.tzinfo))
if fold1 is not None and fold0 != fold1:
self.assertEqual(fold1, result.fold, msg.format(
expected_result, time0, time1, result.fold))
#@unittest.skip("Temporarily skipped")
[docs]
def test__getstate(self):
"""
Test that the _getstate method returns the state of the class.
"""
data = (
((12, 30, 30, 500000), None, 0, r"(b'\x0c\x1e\x1e\x07\xa1 ',)"),
((24, 30, 30, 500000), None, 0, r"(b'\x18\x1e\x1e\x07\xa1 ',)"),
((12, 30, 30, 500000), datetime.BADI, 0,
r"(b'\x0c\x1e\x1e\x07\xa1 ', badidatetime.BADI)"),
)
msg = "Expected {} with time {}, timezone {}, and fold {}, found {}."
for time, tz, fold, expected_result in data:
t = datetime.time(*time, tzinfo=tz, fold=fold)
result = t._getstate()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, time, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___setstate(self):
"""
Test that the __setstate method sets the correct state for pickeling.
"""
err_msg0 = ("tzinfo argument must be None or of a tzinfo subclass, "
"not {!r}")
data = (
((12, 30, 30, 500000), None, 0, b'\x0c\x1e\x1e\x07\xa1 ',
False, ''),
((24, 30, 30, 500000), None, 0, b'\x18\x1e\x1e\x07\xa1 ',
False, ''),
((0, 30, 30, 500000), None, 1, b'\x80\x1e\x1e\x07\xa1 ',
False, ''),
((12, 30, 30, 500000), None, 0, b'', True, err_msg0.format('str')),
)
msg = ("Expected {} with time {}, tz {}, fold {}, "
"and bytes_str {}, found {}.")
for time, tz, fold, bytes_str, validity, expected_result in data:
t = datetime.time(*time, tzinfo=tz, fold=fold)
if validity:
try:
result = t._time__setstate(bytes_str, '')
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {time} an error is not "
f"raised, with result {result}.")
else:
t._time__setstate(bytes_str, tz)
result = (t.hour, t.minute, t.second,
t.microsecond, t.tzinfo, t.fold)
expected_result = time + (tz, fold)
self.assertEqual(expected_result, result, msg.format(
expected_result, time, tz, fold, bytes_str, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___reduce_ex__(self):
"""
Test that the __reduce_ex__ method creates the correct pickle value
for protocol 3.
"""
data = (
((12, 30, 30, 500000), datetime.BADI, 0),
((12, 30, 30, 500000), datetime.UTC, 1),
)
msg = "Expected {}, with time {}, found {}"
for time, tz, fold in data:
t0 = datetime.time(*time, tzinfo=tz, fold=fold)
obj = pickle.dumps(t0)
t1 = pickle.loads(obj)
t0_result = (t0.hour, t0.minute, t0.second, t0.microsecond,
t0.tzinfo, t0.fold)
t1_result = (t1.hour, t1.minute, t1.second, t1.microsecond,
t1.tzinfo, t1.fold)
self.assertEqual(t0_result, t1_result, msg.format(
t0_result, time, tz, fold, t1_result))
[docs]
class TestBadiDatetime_datetime(unittest.TestCase):
def __init__(self, name):
super().__init__(name)
self._time_fields = ('hour', 'minute', 'second', 'microsecond')
[docs]
@classmethod
def setUpClass(cls):
enable_geocoder()
datetime.LOCAL = datetime.timezone.local = datetime.timezone._create(
datetime.timedelta(hours=-5.0))
[docs]
def _get_time(self, time):
t_len = len(time)
hh = time[0] if t_len > 0 else 0
mm = time[1] if t_len > 1 else 0
ss = time[2] if t_len > 2 else 0
us = time[3] if t_len > 3 else 0
return hh, mm, ss, us
#@unittest.skip("Temporarily skipped")
[docs]
def test___new__(self):
"""
Test that the __new__ method creates an instance from both a pickle
object and a normal instantiation.
"""
# err_msg0 = ("A full short or long form Badi date must be used, found "
# "{} fields.")
err_msg1 = ("A fractional value cannot be followed by a least "
"significant value.")
data = (
((1, 1, 1, None, None, 12, 30, 30), None, 0, False,
'0001-01-01T12:30:30'),
((1, 1, 1, None, None, 12, 30, 30, 500000), None, 0, False,
'0001-01-01T12:30:30.500000'),
((1, 1, 1, 1, 1), None, 0, False, '01-01-01-01-01T00:00:00'),
# Test _create_time
((181, 1, 1, None, None, 12.123456789), None, 0, False,
'0181-01-01T12:07:24.444420'),
((181, 1, 1, None, None, 12, 30.123456789), None, 0, False,
'0181-01-01T12:30:07.407407'),
((181, 1, 1, None, None, 12, 30, 30.123456789), None, 0, False,
'0181-01-01T12:30:30.123457'),
# Test pickling
# Short form
((b'\x00\x00\x01\x01\x0c\x1e\x1e\x07\xa1 ',), None, 0, False,
'-1842-01-01T12:30:30.500000'),
# Long form
((b'\x0e\x12\x01\x01\x01\x0c\x1e\x1e\x07\xa1 ',), None, 0, False,
'-05-18-01-01-01T12:30:30.500000'),
# Short form
((b'\x073\x01\x01\x00\x00\x00\x00\x00\x00', datetime.BADI),
datetime.timezone.badi, 0, False, '0001-01-01T00:00:00+03:30'),
# Long form
((b'\x14\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00', datetime.BADI),
datetime.timezone.badi, 0, False, '01-01-01-01-01T00:00:00+03:30'),
((181, 1, 1, None, None, 12.123, 30.5), None, 0, True, err_msg1),
((181, 1, 1, None, None, 12.123, 0, 0.5), None, 0, True, err_msg1),
((181, 1, 1, None, None, 12, 30.5, 30.5), None, 0, True, err_msg1),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, validity, expected_result in data:
if validity:
try:
result = datetime.datetime(*date, tzinfo=tz, fold=fold)
except (AssertionError, ValueError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {date} an error is not "
f"raised, with result {result}.")
else:
result = datetime.datetime(*date, tzinfo=tz, fold=fold)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_hour(self):
"""
Test that the hour property returns the correct value.
"""
data = (
((1, 1, 1, None, None, 12, 30, 30), None, 0, 12),
((1, 1, 1, 1, 1, 12, 30, 30), None, 0, 12)
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.hour
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_minute(self):
"""
Test that the minute returns the correct value.
"""
data = (
((1, 1, 1, None, None, 12, 30, 30), None, 0, 30),
((1, 1, 1, 1, 1, 12, 30, 30), None, 0, 30)
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.minute
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_second(self):
"""
Test that the second returns the correct value.
"""
data = (
((1, 1, 1, None, None, 12, 30, 30), None, 0, 30),
((1, 1, 1, 1, 1, 12, 30, 30), None, 0, 30)
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.second
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_microsecond(self):
"""
Test that the microsecond returns the correct value.
"""
data = (
((1, 1, 1, None, None, 12, 30, 30, 500000), None, 0, 500000),
((1, 1, 1, 1, 1, 12, 30, 30, 999999), None, 0, 999999)
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.microsecond
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_tzinfo(self):
"""
Test that the tzinfo returns the correct value.
"""
data = (
((1, 1, 1, None, None, 12, 30, 30), None, 0, None),
((1, 1, 1, 1, 1, 12, 30, 30), datetime.BADI, 0, datetime.BADI)
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.tzinfo
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_fold(self):
"""
Test that the fold returns the correct value.
"""
data = (
((1, 1, 1, None, None, 12, 30, 30), None, 0, 0),
((1, 1, 1, 1, 1, 12, 30, 30), None, 1, 1)
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.fold
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (51.477928, -0.001545, 0.0))
def test__fromtimestamp_gmt(self):
"""
Test that the _fromtimestamp classmethod creates an instance
of datetime.
.. note::
The tests marked 'Latitude and Longitude dependent' will break
if datetime.LOCAL_COORD is not patched when run in a different
locale.
"""
tz = ZoneInfo(datetime.BADI_IANA)
tz0 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.BADI_COORD)
tz = ZoneInfo('UTC')
tz1 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.GMT_COORD)
tz = ZoneInfo('US/Eastern')
tz2 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.LOCAL_COORD)
data = (
# 1970-01-01T00:00:00Z ->
# Sunset = 17:02 -> 19:00 - 17:02 = 01:58
(0, None, True, '0126-16-02T07:59:32.492400'),
# 1970-01-01T00:00:00Z
(0, tz1, True, '0126-16-02T07:59:32.492400+00:00'),
(0, datetime.UTC, True, '0126-16-02T07:59:32.492400+00:00'),
# 1970-01-01T00:00:00+00:00Z -> 1969-12-31T19:00:00Z
# Sunset = 16:00 -> 19:00 - 16:00 = 03:00 ->
# 0126-16-02T03:00:00.0+00:00
(-18000, tz1, True, '0126-16-02T02:59:32.492400+00:00'),
# 1969-12-31T19:00:00Z -> 1969-12-31T22:30:00:00+03:30 ->
# Sunset = 17:01 -> 22:30 - 17:01 = 05:29
(-18000, tz0, True, '0126-16-02T05:28:46.142400+03:30'),
(-18000, datetime.BADI, True, '0126-16-02T05:28:46.142400+03:30'),
# 1970-01-01T00:00:00Z -> 1970-01-01T03:30:00+03:30
# Sunset day before = 17:01 -> 24:00 - 17:01 = 06:59
# 06:59 + 03:30 = 10:29
(0, tz0, True, '0126-16-02T10:28:46.142400+03:30'),
# 1969-12-31T19:00:00 -> 1969-12-31T14:00:00-05:00 ->
# Sunset = 17:12 -> 24:00 - 17:12 = 06:48 -> 06:48 + 14:00 = 20:48
(-18000, tz2, True, '0126-16-02T02:59:32.492400+00:00'),
)
msg = ("Expected {} with timestamp {}, timezone {}, and short {}, "
"found {}.")
for t, tz, short, expected_result in data:
result = datetime.datetime._fromtimestamp(t, tz, short=short)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, t, tz, short, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test__fromtimestamp_local(self):
"""
Test that the _fromtimestamp classmethod creates an instance
of datetime.
.. note::
The tests marked 'Latitude and Longitude dependent' will break
if datetime.LOCAL_COORD is not patched when run in a different
locale.
"""
tz = ZoneInfo(datetime.BADI_IANA)
tz0 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.BADI_COORD)
tz = ZoneInfo('UTC')
tz1 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.GMT_COORD)
tz = ZoneInfo('US/Eastern')
tz2 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.LOCAL_COORD)
data = (
# 1970-01-01T00:00:00Z -> 1969-12-31T19:00:00-05:00
# Sunset = 17:02 -> 19:00 - 17:02 = 01:58
(0, None, True, '0126-16-02T01:47:57.141600'),
# 1970-01-01T00:00:00Z
(0, tz1, True, '0126-16-02T07:59:32.492400+00:00'),
(0, datetime.UTC, True, '0126-16-02T07:59:32.492400+00:00'),
# 1969-12-31T19:00:00+00:00Z ->
# Sunset = 16:00 -> 19:00 - 16:00 = 03:00
(-18000, tz1, True, '0126-16-02T02:59:32.492400+00:00'),
# 1969-12-31T19:00:00Z -> 1969-12-31T22:30:00:00+03:30 ->
# Sunset = 17:01 -> 22:30 - 17:01 = 05:29
(-18000, tz0, True, '0126-16-02T05:28:46.142400+03:30'),
(-18000, datetime.BADI, True, '0126-16-02T05:28:46.142400+03:30'),
# 1970-01-01T00:00:00Z -> 1970-01-01T03:30:00+03:30
# Sunset day before = 17:01 -> 24:00 - 17:01 = 06:59
# 06:59 + 03:30 = 10:29
(0, tz0, True, '0126-16-02T10:28:46.142400+03:30'),
# 1969-12-31T19:00:00 -> 1969-12-31T14:00:00-05:00 ->
# Sunset = 17:12 -> 24:00 - 17:12 = 06:48 -> 06:48 + 14:00 = 20:48
(-18000, tz2, True, '0126-16-01T20:48:41.256000-05:00'),
)
msg = ("Expected {} with timestamp {}, timezone {}, and short {}, "
"found {}.")
for t, tz, short, expected_result in data:
result = datetime.datetime._fromtimestamp(t, tz, short=short)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, t, tz, short, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test_fromtimestamp(self):
"""
Test that the fromtimestamp classmethod creates a correct instance
of datetime with a -5.0 time zone.
.. note::
The tests marked 'Latitude and Longitude dependent' will break
if datetime.LOCAL_COORD is not patched when run in a different
locale.
"""
tz = ZoneInfo(datetime.BADI_IANA)
tz0 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.BADI_COORD)
tz = ZoneInfo('UTC')
tz1 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.GMT_COORD)
tz = ZoneInfo('US/Eastern')
tz2 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.LOCAL_COORD)
data = (
# 1970-01-01T00:00:00Z -> 1969-12-31T19:00:00-05:00
# Sunset = 17:12 -> 19:00 - 17:12 = 01:48
(0, None, True, '0126-16-02T01:47:57.141600'),
# 1970-01-01T00:00:00Z ->
# Sunset = 16:00 -> 24:00 - 16:00 = 08:00
(0, tz1, True, '0126-16-02T07:59:32.492400+00:00'),
# 1970-01-01T00:00:00Z
(0, tz0, True, '0126-16-02T10:28:46.142400+03:30'),
# 2024-11-30T20:24:13.327577-05:00
# arrive at the correct time. Off by 03:54:10.915200 hrs.
(1733016253.327577, None, True, '0181-14-10T03:22:10.081200'),
(1733016253.327577, tz2, True, '0181-14-10T03:22:10.081200-05:00'),
# Some long form datetimes.
(0, None, False, '01-07-12-16-02T01:47:57.141600'),
(0, tz1, False, '01-07-12-16-02T07:59:32.492400+00:00'),
(0, tz0, False, '01-07-12-16-02T10:28:46.142400+03:30'),
)
msg = ("Expected {} with timestamp {}, timezone {}, and short {}, "
"found {}.")
for t, tz, short, expected_result in data:
result = datetime.datetime.fromtimestamp(t, tz, short=short)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, t, tz, short, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_now(self):
"""
Test that the now classmethod creates an instance of datetime. It is
not possible to test actual dates and time as they will change every
second.
"""
tz0 = ZoneInfo(datetime.BADI_IANA)
tz1 = ZoneInfo('UTC')
tz2 = ZoneInfo('US/Eastern')
data = (
(None, True, 11),
(tz0, True, 11),
(tz1, True, 11),
(tz2, True, 11),
(None, False, 13),
(tz0, False, 13),
(tz1, False, 13),
(tz2, False, 13),
)
msg = "Expected {} with timezone {} and short {}, found {}."
for tz, short, expected_result in data:
dt = datetime.datetime.now(tz=tz, short=short)
ttup = dt.timetuple()
result = len(ttup)
self.assertEqual(expected_result, result, msg.format(
expected_result, tz, short, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_combine(self):
"""
Test that the combine classmethod creates an instance of datetime
from an instance of a date and time object.
"""
err_msg0 = "The date argument must be a date instance, found {}."
err_msg1 = "The time argument must be a time instance, found {}."
data = (
((181, 1, 1), (12, 30, 30), True, False, '0181-01-01T12:30:30'),
((1, 10, 10, 1, 1), (12, 30, 30), True, False,
'01-10-10-01-01T12:30:30'),
((181, 13, 3), (12, 30, 30, 500000), True, False,
'0181-13-03T12:30:30.500000'),
((181, 1, 1), (12, 30, 30), datetime.BADI, False,
'0181-01-01T12:30:30+03:30'),
((), (12, 30, 30), True, True, err_msg0.format('None')),
((181, 1, 1), (), True, True, err_msg1.format('None')),
)
msg = "Expected {} with date {}, time {}, and timezone {}, found {}."
for date, time, tz, validity, expected_result in data:
if validity:
if date == ():
d = None
t = datetime.time(*time,
tzinfo=tz if tz is not True else None)
elif time == ():
d = datetime.date(*date)
t = None
try:
result = datetime.datetime.combine(d, t, tzinfo=tz)
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {date} and {time} an error is "
f"not raised, with result {result}.")
else:
d = datetime.date(*date)
t = datetime.time(*time, tzinfo=tz if tz is not True else None)
result = datetime.datetime.combine(d, t, tzinfo=tz)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, time, tz, result))
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
[docs]
def test_timetuple(self):
"""
Test that the timetuple method returns either a short or long form
timetuple.
"""
tz = ZoneInfo('US/Eastern')
tz0 = datetime.TZWithCoords.fromzoneinfo(tz, *datetime.LOCAL_COORD)
data = (
((181, 13, 9, None, None, 12, 30, 30), None, 0,
'structures.ShortFormStruct(tm_year=181, tm_mon=13, tm_mday=9, '
'tm_hour=12, tm_min=30, tm_sec=30, tm_wday=1, tm_yday=237, '
'tm_isdst=-1)'),
((1, 10, 10, 13, 9, 12, 30, 30), None, 0,
'structures.LongFormStruct(tm_kull_i_shay=1, tm_vahid=10, '
'tm_year=10, tm_mon=13, tm_mday=9, tm_hour=12, tm_min=30, '
'tm_sec=30, tm_wday=1, tm_yday=237, tm_isdst=-1)'),
((181, 13, 9, None, None, 12, 30, 30), datetime.BADI, 0,
'structures.ShortFormStruct(tm_year=181, tm_mon=13, tm_mday=9, '
'tm_hour=12, tm_min=30, tm_sec=30, tm_wday=1, tm_yday=237, '
'tm_isdst=0)'),
((1, 10, 10, 13, 9, 12, 30, 30), datetime.BADI, 0,
'structures.LongFormStruct(tm_kull_i_shay=1, tm_vahid=10, '
'tm_year=10, tm_mon=13, tm_mday=9, tm_hour=12, tm_min=30, '
'tm_sec=30, tm_wday=1, tm_yday=237, tm_isdst=0)'),
((181, 2, 1), tz0, 0, 'structures.ShortFormStruct(tm_year=181, '
'tm_mon=2, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, '
'tm_yday=20, tm_isdst=1)'),
)
msg = "Expected {} with date {}, and timezone {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz)
result = dt.timetuple()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', datetime.GMT_COORD)
def test__mktime_gmt(self):
"""
Test that the _mktime method finds the POSIX time in seconds for
local GMT time. All tests below will only work with GMT set at the
local time set in the above patch.
https://www.epochconverter.com/timezones
https://www.suntoday.org/sunrise-sunset/
"""
# All results below indicate local time.
data = (
((-1842, 16, 3, None, None, 7, 57, 52.704), -62104060800.05673),
((-1747, 16, 4, None, None, 7, 57, 5.0112), -59106067200.0177),
((-1643, 16, 2, None, None, 7, 56, 31.7472), -55824249600.00815),
((-1540, 16, 1, None, None, 7, 56, 3.4992), -52573968033.03408),
((-1491, 16, 2, None, None, 7, 55, 33.6), -51027580800.009796),
((-1347, 16, 4, None, None, 7, 54, 38.2176), -46483286400.0034),
((-1243, 16, 2, None, None, 7, 53, 52.08), -43201468800.01112),
((-1187, 16, 3, None, None, 7, 53, 28.6656), -41434243200.03607),
((-1071, 16, 3, None, None, 7, 52, 41.1456), -37773648000.04056),
((-947, 16, 4, None, None, 7, 51, 44.4672), -33860505600.007504),
((-887, 16, 3, None, None, 7, 51, 17.9424), -31967136000.00513),
((-779, 16, 3, None, None, 7, 50, 27.3984), -28559001600.012352),
((-691, 16, 2, None, None, 7, 49, 48.3456), -25782019200.01046),
((-547, 16, 4, None, None, 7, 58, 39.4848), -21237724200.034355),
((-498, 16, 3, None, None, 7, 48, 32.2272), -19691510400.005028),
((-390, 16, 2, None, None, 7, 47, 39.0048), -16283375999.980446),
((-291, 16, 2, None, None, 7, 46, 27.984), -13159238399.978153),
((60, 16, 1, None, None, 8, 0, 19.8432), -2082844800.0390663),
# Sunset on 1969-12-31T16:00:00+00:00 is the start of the Badi day
# before the POSIX epoch. This is 08:00:00 before UTC midnight
# the POSIX epoch. The local UTC time on the epoch was
# 1970-01-01T00:00:00+00:00
((126, 16, 2, None, None, 8, 0), 27.507957816124),
((216, 16, 3, None, None, 7, 59, 30.9408), 2840140799.953249),
((249, 16, 4, None, None, 7, 58, 30.72), 3881606399.951801),
((356, 16, 3, None, None, 7, 59, 38.6304), 7258118399.979682),
((360, 16, 2, None, None, 8, 0, 36.1728), 7384262400.020639),
((460, 16, 1, None, None, 8, 1, 3.3024), 10539935999.97421),
((475, 16, 2, None, None, 8, 0, 42.9984), 11013321599.946892),
((645, 16, 4, None, None, 7, 59, 14.9568), 16378156800.007645),
((810, 16, 3, None, None, 8, 0, 30.4704), 21584966399.9895),
((860, 16, 1, None, None, 8, 1, 36.2208), 23162716799.95365),
((876, 16, 2, None, None, 8, 1, 31.728), 23667638399.9549),
((1041, 16, 4, None, None, 7, 59, 52.1952), 28874707199.998993),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
dt = datetime.datetime(*date)
result = dt._mktime()
self.assertEqual(expected_result, result, msg.format(
expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test__mktime_local(self):
"""
Test that the _mktime method finds the POSIX time in seconds for
local time EST. All tests below will only work with the local time
set in the above patch.
"""
# All results below indicate local time.
data = (
# 1970-01-01T05:00:00Z -> 1970-01-01T00:00:00-05:00
# Sunset day before = 17:12 -> 24:00 - 17.12 = 06:48
((126, 16, 2, None, None, 6, 48), 18002.857571840286),
# 1970-01-01T00:00:00Z -> 1969-12-31T19:00:00-05:00
# Sunset day before = 17:12 -> 24:00 - 17.12 = 06:48 ->
# 06:48 + 19:00 = 01T01:48
((126, 16, 2, None, None, 1, 48), 2.857598662376),
# 2025-02-25T05:00:00Z -> 2025-02-25T00:00:00-05:00
# 1st day of Ayyam-i-Ha -> 1740459600
# Sunset day before = 18:07 -> 24:00 - 18:07 = 05:53
((181, 0, 1, None, None, 5, 53), 1740459543.2414398),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
dt = datetime.datetime(*date)
result = dt._mktime()
self.assertEqual(expected_result, result, msg.format(
expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', BahaiCalendar._BAHAI_LOCATION[:3])
def test__mktime_tehran(self):
"""
Test that the _mktime method finds the POSIX time in seconds for
local time in Terhan. All tests below will only work with Terhan
set as the local time set in the above patch.
https://www.epochconverter.io/timezones-converter
"""
# All results below indicate local time.
data = (
# 1970-01-01T:00:00:00Z -> 1970-01-01-T03:30:00+03:30
# Sunset day before = 17:01 -> 24:00 - 17:01 = 06:59 ->
# 06:59 + 03:30 = 10:29 -> Approximately -12600
((126, 16, 2, None, None, 10, 29), 13.858504593372),
# POSIX epoch 1969-12-31T20:60:00Z -> 1970-01-01T00:00:00+03:30
# Sunset day before = 17:01 -> 24:00 - 17:01 = 06:59 ->
# Approximatly 0.0
((126, 16, 2, None, None, 6, 59), -12586.141508817673),
# 2025-01-01T00:00:00Z -> 2025-01-01T03:30:00+03:30
# Sunset day before 17:02 -> 24:00 - 17:02 = 06:58 ->
# 06:58 + 03:30 = 10:28 -> 1735689600 *** TODO *** Fix this
((181, 16, 2, None, None, 10, 28), 1735603132.1160793),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
dt = datetime.datetime(*date)
result = dt._mktime()
self.assertEqual(expected_result, result, msg.format(
expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test_timestamp(self):
"""
Test that the timestamp method returns either the POSIX time for
local or for the timezone provided.
https://www.unixtimestamp.com
https://www.epochconverter.com
"""
tz0 = ZoneInfo(datetime.BADI_IANA)
tz1 = ZoneInfo('UTC')
tz2 = ZoneInfo('US/Eastern')
data = (
# 2024-03-19T18:15:57.312+03:30 -> 1710873957.0
# 0181-01-01T00:00:00+03:30
# 2460387.262245 = sunset on 0181-01-01T00:00:00+03:30
# 0.3125 = T07:30:00
# 0.550255 = 0.5 - 0.262245 + 0.3125 = T13:12:22.032
((181, 1, 1), tz0, 0, 1710851427.5076),
# 2024-03-19T18:15:57.312Z -> 1710886557
# 0181-01-01T00:00:00Z
((181, 1, 1), tz1, 0, 1710864027.5076),
# 2024-03-19T18:15:57.312-04:00
# 0181-01-01T00:00:00-04:00
((181, 1, 1), tz2, 0, 1710878427.5076),
# POSIX epoch
# 0126-16-02T07:59:32.4924Z -> 0126-16-02T11:29:32.4924+03:30
((126, 16, 2, None, None, 11, 29, 32.4924), tz0, 0, 0.0),
# 0126-16-02T07:59:32.4924Z
((126, 16, 2, None, None, 7, 59, 32.4924), tz1, 0, 0.0),
# 0126-16-02T07:59:32.4924Z
((126, 16, 2, None, None, 7, 59, 32.4924), datetime.UTC, 0, 0.0),
# 0126-16-02T07:59:32.4924Z -> 0126-16-02T02:59:32.4924-05:00
((126, 16, 2, None, None, 2, 59, 32.4924), tz2, 0, 0.0),
# Local dates and times
# 0181-16-02T08:00:00Z -> 2024-12-30T14:00:01.8648-05:00 ->
# 2024-12-30T19:00:01.8648 -> 1735585201 (26.5076 seconds off)
((181, 16, 2, None, None, 3), tz1, 0, 1735585227.5076),
# 0181-16-02T08:00:00Z -> 0181-16-02T03:00:00-05:00
# 2024-12-30T20:11:58.2504-05:00 -> 1735607518 (1.2079634 hrs off)
((181, 16, 2, None, None, 3), tz2, 0, 1735603227.5076),
# 1735607518 (4.99526331 hrs off)
((181, 16, 2, None, None, 3), None, 0, 1735607500.9440825),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.timestamp()
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_utctimetuple(self):
"""
Test that the utctimetuple method returns a timetuple object.
"""
data = (
((181, 1, 1, None, None, 12, 30, 30), None, 0,
'structures.ShortFormStruct(tm_year=181, tm_mon=1, tm_mday=1, '
'tm_hour=12, tm_min=30, tm_sec=30, tm_wday=3, tm_yday=1, '
'tm_isdst=0)'),
((181, 1, 1, None, None, 12, 30, 30), datetime.UTC, 0,
'structures.ShortFormStruct(tm_year=181, tm_mon=1, tm_mday=1, '
'tm_hour=12, tm_min=30, tm_sec=30, tm_wday=3, tm_yday=1, '
'tm_isdst=0)'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.utctimetuple()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__timetuple(self):
"""
Test that the _timetuple method returns a timetuple object.
"""
#tz0 = ZoneInfo(datetime.BADI_IANA)
tz1 = ZoneInfo('UTC')
tz2 = ZoneInfo('US/Eastern')
offset0 = datetime.timedelta(0)
offset1 = datetime.timedelta(hours=-5)
data = (
((181, 14, 15), None, 0, offset0,
'structures.ShortFormStruct(tm_year=181, tm_mon=14, tm_mday=15, '
'tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=262, '
'tm_isdst=0)'),
((181, 14, 15), tz1, 0, offset0,
'structures.ShortFormStruct(tm_year=181, tm_mon=14, tm_mday=15, '
'tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=262, '
'tm_isdst=0)'),
((181, 14, 15), None, 0, offset1,
'structures.ShortFormStruct(tm_year=181, tm_mon=14, tm_mday=15, '
'tm_hour=5, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=262, '
'tm_isdst=0)'),
((181, 14, 15), tz2, 0, offset1,
'structures.ShortFormStruct(tm_year=181, tm_mon=14, tm_mday=15, '
'tm_hour=5, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=262, '
'tm_isdst=0)'),
)
msg = ("Expected {} with date {}, timezone {}, fold {}, and "
"offset {}, found {}.")
for date, tz, fold, offset, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt._timetuple(offset)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, fold, offset, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_date(self):
"""
Test that thedate method returns a date object with the same date as
the originating datetime object.
"""
data = (
((181, 1, 1, None, None, 12, 30, 30), None, 0, '0181-01-01'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.date()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_time(self):
"""
Test that the time method a time object with the same time as
the originating datetime object.
"""
data = (
((181, 1, 1, None, None, 12, 30, 30), None, 0, '12:30:30'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.time()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_timetz(self):
"""
Test that the timetz method a time object with the same time and
tzinfo as the originating datetime object.
"""
data = (
((181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0,
'12:30:30+03:30'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.timetz()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_replace(self):
"""
Test that the replace method a new datetime object with the
replaced values.
"""
err_msg0 = "Cannot convert from a short to a long form date."
err_msg1 = ("Cannot convert from a long to a short form date. The "
"value {} is not valid for long form dates.")
data = (
# Normal replace for a short date
((181, 1, 1, None, None), None, 0, (None, None, 182, None, None),
None, 0, False, '0182-01-01T00:00:00'),
((181, 1, 1, None, None), None, 0, (None, None, None, 9, 12),
None, 0, False, '0181-09-12T00:00:00'),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
(None, None, None, None, None, 23, None, None),
None, 0, False, '0181-01-01T23:30:30'),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
(None, None, None, None, None, None, 15, 15),
None, 0, False, '0181-01-01T12:15:15'),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
(None, None, None, None, None, None, None, None,),
datetime.BADI, 0, False, '0181-01-01T12:30:30+03:30'),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
(None, None, None, None, None, None, None, None,),
None, 1, False, '0181-01-01T12:30:30'),
# Normal replace for a long date
((1, 10, 10, 1, 1), None, 0, (None, None, 11, None, None), None, 0,
False, '01-10-11-01-01T00:00:00'),
((1, 10, 10, 1, 1), None, 0, (None, 9, None, None, None), None, 0,
False, '01-09-10-01-01T00:00:00'),
((1, 10, 10, 1, 1), None, 0, (None, 9, 10, None, None), None, 0,
False, '01-09-10-01-01T00:00:00'),
((1, 10, 10, 1, 1, 12, 30, 30), None, 0,
(None, None, None, None, None, 23, None, None), None, 0,
False, '01-10-10-01-01T23:30:30'),
((1, 10, 10, 1, 1, 12, 30, 30), None, 0,
(None, None, None, None, None, None, 15, 15), None, 0,
False, '01-10-10-01-01T12:15:15'),
((1, 10, 10, 1, 1, 12, 30, 30), None, 0,
(None, None, None, None, None, None, None, None,),
datetime.BADI, 0, False, '01-10-10-01-01T12:30:30+03:30'),
((1, 10, 10, 1, 1, 12, 30, 30), None, 0,
(None, None, None, None, None, None, None, None,),
None, 1, False, '01-10-10-01-01T12:30:30'),
# Error conditions.
((181, 1, 1, None, None), None, 0, (1, 10, None, None, None),
None, 0, True, err_msg0),
((1, 10, 10, 1, 1), None, 0, (None, None, 181, 1, None),
None, 0, True, err_msg1.format(181)),
)
msg = "Expected {} with date1 {} and date2 {}, found {}."
for (date1, tz0, fold0, date2, tz1, fold1,
validity, expected_result) in data:
dt = datetime.datetime(*date1, tzinfo=tz0, fold=fold0)
if validity:
try:
result = dt.replace(*date2, tzinfo=tz1, fold=fold1)
except ValueError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date1}' an error is not "
f"raised, with result {result}.")
else:
result = dt.replace(*date2, tzinfo=tz1, fold=fold1)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date1, date2, str(result)))
self.assertEqual(fold1, result.fold,
f"Expected fold {fold1}, found {result.fold}")
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test__local_timezone(self):
"""
Test that the _local_timezone method returns the local time offset.
"""
data = (
((181, 1, 1), None, 'UTC-05:00'),
((1, 1, 1), datetime.BADI, 'UTC-05:00'),
((1, 1, 1, 1, 1), datetime.BADI, 'UTC-05:00'),
)
msg = "Expected {} with date {}, found {}."
for date, tz, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz)
result = dt._local_timezone()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test_astimezone(self):
"""
Test that the astimezone method returns a datetime object with a
replaced the timezone tzinfo object.
"""
err_msg0 = "tz argument must be an instance of tzinfo, found {}."
data = (
((126, 16, 2, None, None, 6, 47, 57.12), None, datetime.UTC, False,
'0126-16-02T11:47:57.120000+00:00'),
# The next two are the date and time with timezone -5 for
# the Badi epoch.
((0, 19, 19, 19, 19, 15, 30), None, datetime.BADI, False,
'01-01-01-01-01T00:00:00+03:30'),
((0, 19, 19, None, None, 15, 30), None, datetime.BADI, False,
'0001-01-01T00:00:00+03:30'),
# Test with a current timezone.
((0, 19, 19, None, None, 15, 30), datetime.LOCAL, datetime.BADI,
False, '0001-01-01T00:00:00+03:30'),
# Test with timezone as None.
((181, 1, 1), None, None, False, '0181-01-01T00:00:00-05:00'),
# The offset is None for the tzinfo in datetime.datetime.
((182, 1, 18), NoneTimeZone(), datetime.UTC, False,
'0182-01-18T05:00:00+00:00'),
# Same timezone
((182, 1, 18), datetime.UTC, datetime.UTC, False,
'0182-01-18T00:00:00+00:00'),
# Errors
((1, 1, 1), None, 0, True, err_msg0.format("<class 'int'>")),
)
msg = "Expected {} with date {}, timezone {}, found {}."
for date, tz0, tz1, validity, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz0)
if validity:
try:
result = dt.astimezone(tz=tz1)
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date}' an error is not "
f"raised, with result {result}.")
else:
result = dt.astimezone(tz=tz1)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_ctime(self):
"""
Test that the ctime method creates a string indicating the date
and time.
All days before 1752-09-14 in the Gregorian Calendar will seem wrong
when compaired to the Badi Calendar in UK and the US. This is when
The Gregorian Calendar was adopted and compinsated 11 days.
"""
data = (
# 0001-03-20 Saturday (Kamál -> Monday)
#((-1842, 1, 1), 'Kamál Bahá 1 00:00:00 -1842'),
#((-1842, 1, 1, None, None, 12, 30, 30),
# 'Kamál Bahá 1 12:30:30 -1842'),
# 1582-10-04 Thursday (Jalál -> Saturday)
((-261, 11, 7), 'Jalál Mashíyyat 7 00:00:00 -0261'),
((-261, 11, 7, None, None, 6, 15, 15),
'Jalál Mashíyyat 7 06:15:15 -0261'),
# 1843-03-20 Monday
((0, 1, 1), 'Kamál Bahá 1 00:00:00 0000'),
((0, 1, 1, None, None, 12, 30, 30), 'Kamál Bahá 1 12:30:30 0000'),
# 1844-03-19 Tuesday
((1, 1, 1), 'Fiḍāl Bahá 1 00:00:00 0001'),
((1, 1, 1, None, None, 12, 30, 30), 'Fiḍāl Bahá 1 12:30:30 0001'),
# 2024-03-19 Tuesday
((181, 1, 1), 'Fiḍāl Bahá 1 00:00:00 0181'),
((181, 1, 1, None, None, 12, 30, 30),
'Fiḍāl Bahá 1 12:30:30 0181'),
# 2024-08-14 Wednesday
((181, 8, 16, None, None, 12, 30, 30),
'`Idāl Kamál 16 12:30:30 0181'),
((181, 8, 16), '`Idāl Kamál 16 00:00:00 0181'),
((181, 8, 16, None, None, 12, 30, 30),
'`Idāl Kamál 16 12:30:30 0181'),
# 2024-08-14 Wednesday
((1, 10, 10, 8, 16), '`Idāl Kamál 16 00:00:00 0181'),
((1, 10, 10, 8, 16, 12, 30, 30), '`Idāl Kamál 16 12:30:30 0181'),
# 2024-08-15 Thursday
((1, 10, 10, 8, 17), 'Istijlāl Kamál 17 00:00:00 0181'),
((1, 10, 10, 8, 17, 12, 30, 30), 'Istijlāl Kamál 17 12:30:30 0181'),
)
msg = "Expected {} with date {}, found {}."
for date, expected_result in data:
dt = datetime.datetime(*date)
result = dt.ctime()
self.assertEqual(expected_result, str(result),
msg.format(expected_result, date, result))
#@unittest.skip("Temporarily skipped")
#@unittest.skip("Temporarily skipped")
[docs]
def test___repr__(self):
"""
Test that the __repr__ method returns a string of the object.
"""
data = (
((181, 1, 1, None, None, 12, 30), None, 0,
'badidatetime.datetime(181, 1, 1, None, None, 12, 30)'),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
'badidatetime.datetime(181, 1, 1, None, None, 12, 30, 30)'),
((181, 1, 1, None, None, 12, 30, 30, 500000), None, 0,
'badidatetime.datetime(181, 1, 1, None, None, 12, 30, 30, '
'500000)'),
((181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0,
'badidatetime.datetime(181, 1, 1, None, None, 12, 30, 30, '
'tzinfo=badidatetime.BADI)'),
((181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 1,
'badidatetime.datetime(181, 1, 1, None, None, 12, 30, 30, '
'tzinfo=badidatetime.BADI, fold=1)'),
((1, 10, 10, 15, 14), None, 0,
'badidatetime.datetime(1, 10, 10, 15, 14, 0, 0)'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = repr(dt)
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__dt_str_conversion(self):
"""
Test that the _dt_str_conversion method returns a string of the object.
"""
data = (
((181, 1, 1, None, None, 12, 30), None, 0, '0181-01-01T12:30:00'),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
'0181-01-01T12:30:30'),
((181, 1, 1, None, None, 12, 30, 30, 500000), None, 0,
'0181-01-01T12:30:30.500000'),
((181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0,
'0181-01-01T12:30:30+03:30'),
((181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 1,
'0181-01-01T12:30:30+03:30'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = str(dt)
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_strptime(self):
"""
Test that the strptime method parses a date from a string and
returns a datetime class object.
"""
data = (
('0001-01-01', '%Y-%m-%d', '0001-01-01T00:00:00'),
('Jal Bah 05 12:30:30 1', '%a %b %d %H:%M:%S %Y',
'0001-01-05T12:30:30'),
)
msg = "Expected {} with str_date {} and format {}, found {}."
for str_date, fmt, expected_result in data:
dt = datetime.datetime.strptime(str_date, fmt)
result = str(dt)
self.assertEqual(expected_result, result, msg.format(
expected_result, str_date, fmt, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_utcoffset(self):
"""
Test that the utcoffset method returns a timedelta object relative
to the UTC time zone..
"""
tz0 = ZoneInfo(datetime.BADI_IANA)
tz1 = ZoneInfo('UTC')
tz2 = ZoneInfo('US/Eastern')
tz3 = datetime.timezone(datetime.timedelta(hours=3.5))
data = (
((181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0, '3:30:00'),
((181, 1, 1, None, None, 12, 30, 30), tz0, 0, '3:30:00'),
((181, 1, 1, None, None, 12, 30, 30), datetime.UTC, 0, '0:00:00'),
((181, 1, 1, None, None, 12, 30, 30), tz1, 0, '0:00:00'),
((181, 1, 1, None, None, 12, 30, 30), tz2, 0, '-1 day, 20:00:00'),
((181, 1, 1, None, None, 12, 30, 30), tz3, 0, '3:30:00'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.utcoffset()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_tzname(self):
"""
Test that the tzname method returns the timezone associated with
the datetime object.
"""
data = (
((181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0,
'Asia/Tehran'),
((181, 1, 1, None, None, 12, 30, 30), datetime.UTC, 0, 'UTC'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.tzname()
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_dst(self):
"""
Test that the dst method returns the daylight savings time
associated with the datetime object.
"""
tz0 = ZoneInfo(datetime.BADI_IANA)
tz1 = ZoneInfo('UTC')
tz2 = ZoneInfo('US/Eastern')
data = (
((181, 1, 1, None, None, 12, 30, 30), tz0, 0, '0:00:00'),
((181, 1, 1, None, None, 12, 30, 30), tz1, 0, '0:00:00'),
((181, 7, 1), tz2, 0, '1:00:00'),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt.dst()
self.assertEqual(expected_result, str(result), msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___eq__(self):
"""
Test that the __eq__ method returns True if equal and False if
not equal.
"""
data = (
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 30), None, False, True),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 29), None, False, False),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 31), None, False, False),
((181, 9, 14, None, None, 12, 30, 30), datetime.UTC,
(181, 9, 14, None, None, 12, 30, 30), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 30), None, False, True),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 29), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 31), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), datetime.UTC,
(1, 10, 10, 9, 14, 12, 30, 31), None, False, False),
((181, 9, 14), None, (181, 9, 14), None, True, False),
((181, 9, 14), None, 1.5, None, False, False),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, tz0, date1, tz1, is_date, expected_result in data:
dt0 = datetime.datetime(*date0, tzinfo=tz0)
if isinstance(date1, float):
dt1 = date1
elif is_date:
dt1 = datetime.date(*date1)
else:
dt1 = datetime.datetime(*date1, tzinfo=tz1)
result = dt0 == dt1
self.assertEqual(expected_result, result, msg.format(
expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___le__(self):
"""
Test that the __le__ method returns True if less than or equal and
False if not less than or equal.
"""
err_msg0 = "Cannot compare 'datetime' to '{}'"
err_msg1 = "'<=' not supported between instances of 'datetime' and '{}'"
data = (
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 30), None, False, True),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 29), None, False, False),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 31), None, False, True),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 30), None, False, True),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 29), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 31), None, False, True),
((181, 9, 14), None, (181, 9, 14), None, True,
err_msg0.format('date')),
((181, 9, 14), None, 1.5, None, True, err_msg1.format('float')),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, tz0, date1, tz1, validity, expected_result in data:
dt0 = datetime.datetime(*date0, tzinfo=tz0)
if validity:
if isinstance(date1, float):
dt1 = date1
else:
dt1 = datetime.date(*date1)
try:
result = dt0 <= dt1
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date0}' an error is not "
f"raised, with result {result}.")
else:
if isinstance(date1, float):
dt1 = date1
else:
dt1 = datetime.datetime(*date1, tzinfo=tz1)
result = dt0 <= dt1
self.assertEqual(expected_result, result, msg.format(
expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___lt__(self):
"""
Test that the __lt__ method returns True if less than and False
if not less than.
"""
err_msg0 = "Cannot compare 'datetime' to '{}'"
err_msg1 = "'<' not supported between instances of 'datetime' and '{}'"
data = (
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 30), None, False, False),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 29), None, False, False),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 31), None, False, True),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 30), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 29), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 31), None, False, True),
((181, 9, 14), None, (181, 9, 14), None, True,
err_msg0.format('date')),
((181, 9, 14), None, 1.5, None, True, err_msg1.format('float')),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, tz0, date1, tz1, validity, expected_result in data:
dt0 = datetime.datetime(*date0, tzinfo=tz0)
if validity:
if isinstance(date1, float):
dt1 = date1
else:
dt1 = datetime.date(*date1)
try:
result = dt0 < dt1
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date0}' an error is not "
f"raised, with result {result}.")
else:
dt1 = datetime.datetime(*date1, tzinfo=tz1)
result = dt0 < dt1
self.assertEqual(expected_result, result, msg.format(
expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___ge__(self):
"""
Test that the __ge__ method returns True if greater than or equal
and False if not greater than or equal.
"""
err_msg0 = "Cannot compare 'datetime' to '{}'"
err_msg1 = "'>=' not supported between instances of 'datetime' and '{}'"
data = (
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 30), None, False, True),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 29), None, False, True),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 31), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 30), None, False, True),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 29), None, False, True),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 31), None, False, False),
((181, 9, 14), None, (181, 9, 14), None, True,
err_msg0.format('date')),
((181, 9, 14), None, 1.5, None, True, err_msg1.format('float')),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, tz0, date1, tz1, validity, expected_result in data:
dt0 = datetime.datetime(*date0, tzinfo=tz0)
if validity:
if isinstance(date1, float):
dt1 = date1
else:
dt1 = datetime.date(*date1)
try:
result = dt0 >= dt1
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date0}' an error is not "
f"raised, with result {result}.")
else:
dt1 = datetime.datetime(*date1, tzinfo=tz1)
result = dt0 >= dt1
self.assertEqual(expected_result, result, msg.format(
expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___gt__(self):
"""
Test that the __gt__ method returns True if greater than and False
if not greater than.
"""
err_msg0 = "Cannot compare 'datetime' to '{}'"
err_msg1 = "'>' not supported between instances of 'datetime' and '{}'"
data = (
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 30), None, False, False),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 29), None, False, True),
((181, 9, 14, None, None, 12, 30, 30), None,
(181, 9, 14, None, None, 12, 30, 31), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 30), None, False, False),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 29), None, False, True),
((1, 10, 10, 9, 14, 12, 30, 30), None,
(1, 10, 10, 9, 14, 12, 30, 31), None, False, False),
((181, 9, 14), None, (181, 9, 14), None, True,
err_msg0.format('date')),
((181, 9, 14), None, 1.5, None, True, err_msg1.format('float')),
)
msg = "Expected {} with date0 {} and date1 {}, found {}."
for date0, tz0, date1, tz1, validity, expected_result in data:
dt0 = datetime.datetime(*date0, tzinfo=tz0)
if validity:
if isinstance(date1, float):
dt1 = date1
else:
dt1 = datetime.date(*date1)
try:
result = dt0 > dt1
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date0}' an error is not "
f"raised, with result {result}.")
else:
dt1 = datetime.datetime(*date1, tzinfo=tz1)
result = dt0 > dt1
self.assertEqual(expected_result, result, msg.format(
expected_result, date0, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test__cmp(self):
"""
Test that the _cmp method returns 1 if the two dates are equal, +1
if the current date is greater than the test date, and -1 if the
inverse.
"""
err_msg0 = "The other must be a datetime instance, found '{}'."
err_msg1 = "Cannot compare naive and aware datetimes."
tz0 = ZoneInfo('US/Pacific')
data = (
((181, 9, 14, None, None, 12, 30, 30), None, 0,
(181, 9, 14, None, None, 12, 30, 30), None, 0, False, False, 0),
((181, 9, 14, None, None, 12, 30, 30), None, 0,
(181, 9, 14, None, None, 12, 30, 29), None, 0, False, False, 1),
((181, 9, 14, None, None, 12, 30, 30), None, 0,
(181, 9, 14, None, None, 12, 30, 31), None, 0, False, False, -1),
((1, 10, 10, 9, 14, 12, 30, 30), None, 0,
(1, 10, 10, 9, 14, 12, 30, 30), None, 0, False, False, 0),
((1, 10, 10, 9, 14, 12, 30, 30), None, 0,
(1, 10, 10, 9, 14, 12, 30, 29), None, 0, False, False, 1),
((1, 10, 10, 9, 14, 12, 30, 30), None, 0,
(1, 10, 10, 9, 14, 12, 30, 31), None, 0, False, False, -1),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
(181, 1, 1, None, None, 12, 30, 30), None, 0, True, False, 0),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
(181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0, True,
False, 2),
((181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0,
(181, 1, 1, None, None, 12, 30, 30), datetime.UTC, 0, True,
False, -1),
((181, 1, 1, None, None, 12, 30, 30), datetime.UTC, 0,
(181, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0, True,
False, 1),
# Fold on 2024-11-03T02:00:00 -> 0181-10-01T08:41:37.2768
((181, 10, 1, None, None, 8, 41, 37.2768), datetime.LOCAL, 0,
(181, 10, 1, None, None, 8, 41, 37.2768), None, 0, True,
False, 2),
((181, 1, 1, None, None, 12, 30, 30), None, 0, None, None, 0,
False, True, err_msg0.format("<class 'NoneType'>")),
((181, 1, 1, None, None, 12, 30, 30), None, 0,
(182, 1, 1, None, None, 12, 30, 30), datetime.BADI, 0, False,
True, err_msg1),
)
msg = "Expected {} with date0 {}, date1 {}, and mixed {}, found {}."
for (date0, tz0, fold0, date1, tz1, fold1, mixed,
validity, expected_result) in data:
dt0 = datetime.datetime(*date0, tzinfo=tz0)
if date1 is not None:
dt1 = datetime.datetime(*date1, tzinfo=tz1, fold=fold1)
else:
dt1 = date1
if validity:
try:
result = dt0._cmp(dt1, allow_mixed=mixed)
except (AssertionError, TypeError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {time} an error is not "
f"raised, with result {result}.")
else:
result = dt0._cmp(dt1, allow_mixed=mixed)
self.assertEqual(expected_result, result, msg.format(
expected_result, date0, date1, mixed, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___add__(self):
"""
Test that the __add__ method can correctly add a datetime to
a timedelta.
"""
err_msg0 = "Result out of range."
err_msg1 = "unsupported operand type(s) for +: 'datetime' and '{}'"
data = (
((1, 1, 1), (1,), False, (1, 1, 2)),
((1, 1, 1), (-1,), False, (0, 19, 19)),
((1, 1, 1), (366,), False, (2, 1, 1)), # Leap year
((181, 1, 1), (365,), False, (182, 1, 1)), # Non leap year
((1, 1, 1, 1, 1), (366,), False, (1, 1, 2, 1, 1)), # Leap year
((-1842, 1, 1), (-1,), True, err_msg0),
((1161, 19, 19), (1,), True, err_msg0),
((181, 1, 1), 1.5, True, err_msg1.format('float'))
)
msg = "Expected {} with date {} and timedelta {}, found {}"
for date, td, validity, expected_result in data:
dt0 = datetime.datetime(*date)
if validity:
if isinstance(td, tuple):
td0 = datetime.timedelta(*td)
else:
td0 = td
try:
result = dt0 + td0
except (OverflowError, TypeError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date}' an error is not "
f"raised, with result {result}.")
else:
td0 = datetime.timedelta(*td)
dt1 = dt0 + td0
if dt1.is_short:
result = (dt1.year, dt1.month, dt1.day)
else:
result = (dt1.kull_i_shay, dt1.vahid, dt1.year,
dt1.month, dt1.day)
self.assertEqual(expected_result, result, msg.format(
expected_result, date, td, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___sub__(self):
"""
Test that the __sub__ method returns the correct results of a
timedelta object subtracted from a datetime object.
"""
err_msg0 = "Result out of range."
err_msg1 = "unsupported operand type(s) for -: 'datetime' and '{}'"
err_msg2 = "Cannot mix naive and timezone-aware time."
data = (
((1, 1, 1), None, (1,), (), False, (0, 19, 19)),
((1, 1, 1), None, (366,), (), False, (-1, 19, 19)), # Leap year
((181, 1, 1), None, (365,), (), False, (180, 1, 1)), # Non leap year
# Leap year
((1, 1, 1, 1, 1), None, (366,), (), False, (0, 19, 18, 19, 19)),
((181, 1, 2), None, (), (181, 1, 1), False, (1, 0, 0, 86400.0)),
((-1842, 1, 1), None, (1,), (), True, err_msg0),
((1161, 19, 19), None, (-1,), (), True, err_msg0),
((181, 1, 1), None, 1.5, (), True, err_msg1.format('float')),
((181, 1, 2), datetime.UTC, NoneTimeZone(), (181, 1, 1), True,
err_msg2),
)
msg = "Expected {} with date0 {}, timedelta {}, and date1 {}, found {}"
for date0, tz, td, date1, validity, expected_result in data:
dt0 = datetime.datetime(*date0, tzinfo=tz)
if validity:
if isinstance(td, tuple):
obj = datetime.timedelta(*td)
elif isinstance(date1, tuple) and len(date1) > 0:
obj = datetime.datetime(*date1)
else:
obj = td
try:
result = dt0 - obj
except (TypeError, OverflowError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With '{date0}' an error is not "
f"raised, with result {result}.")
else:
if td:
obj = datetime.timedelta(*td)
else:
obj = datetime.datetime(*date1)
dt1 = dt0 - obj
if isinstance(dt1, datetime.timedelta):
result = (dt1.days, dt1.seconds, dt1.microseconds,
dt1.total_seconds())
elif dt1.is_short:
result = (dt1.year, dt1.month, dt1.day)
else:
result = (dt1.kull_i_shay, dt1.vahid, dt1.year,
dt1.month, dt1.day)
self.assertEqual(expected_result, result, msg.format(
expected_result, date0, td, date1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___hash__(self):
"""
Test that the __hash__ method returns a valid hash for both short
and long form datetimes.
"""
data = (
((datetime.MINYEAR, 1, 1, None, None, 12, 30, 30), None, 0),
((-5, 18, 1, 1, 1, 12, 30, 30), None, 0),
((1, 1, 1, None, None, 12, 30, 30), None, 0),
((1, 1, 1, 1, 1, 12, 30, 30), None, 0),
((1, 1, 1), datetime.BADI, 0),
((1, 1, 1), datetime.BADI, 1),
)
msg = "date {}, found {}."
for date, tz, fold in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = hash(dt)
self.assertTrue(len(str(result)) > 15, msg.format(date, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__is_pickle_data(self):
"""
Test that the _is_pickle_data classmethod returns the correct results
depending on the incoming data.
"""
err_msg0 = "Invalid string {} had length of {} for pickle."
err_msg1 = ("Failed to encode latin1 string when unpickling a date or "
"datetime instance. pickle.load(data, encoding='latin1') "
"is assumed.")
data = (
((b'\x00\x00\x01\x01\x0c\x1e\x1e\x07\xa1 ', None), False, True),
((b'\x0e\x12\x01\x01\x01\x0c\x1e\x1e\x07\xa1 ', None), False,
False),
((181, 10), False, None),
((b'\x073\x01\x01\x00\x00\x00\x00\x00\x00', datetime.BADI), False,
True),
((b'\x14\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00', datetime.BADI),
False, False),
(((181, 1, 1, None, None), None), False, None),
(('\x00\x00\xf3\x01\x0c\x1e\x1e\x07\xa1 ', None), False, None),
(('\x0e\x12\x01\xf3\x01\x0c\x1e\x1e\x07\xa1 ', None), False, None),
((b'\x14\x01\x01\x01\x01\x01', None), True, err_msg0.format(
b'\x14\x01\x01\x01\x01\x01', 6)),
(('\u2190\x01\x01\x011\x01\x1e\x1e\x07\xa1 ', None), True,
err_msg1),
)
msg = "Expected {} with value {}, found {}."
for value, validity, expected_result in data:
if validity:
try:
result = datetime.datetime._is_pickle_data(*value)
except (AssertionError, ValueError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {value} an error is not "
f"raised, with result {result}.")
else:
result = datetime.datetime._is_pickle_data(*value)
self.assertEqual(expected_result, result, msg.format(
expected_result, value, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__getstate(self):
"""
Test that the _getstate method returns the correct state for pickling.
"""
data = (
((datetime.MINYEAR, 1, 1, None, None, 12, 30, 30, 500000), None, 0,
(b'\x00\x00\x01\x01\x0c\x1e\x1e\x07\xa1 ',)),
((-5, 18, 1, 1, 1, 12, 30, 30, 500000), None, 0,
(b'\x0e\x12\x01\x01\x01\x0c\x1e\x1e\x07\xa1 ',)),
((1, 1, 1, None, None), datetime.BADI, 0,
(b'\x073\x01\x01\x00\x00\x00\x00\x00\x00',
datetime.timezone.badi)),
((1, 1, 1, 1, 1), datetime.BADI, 0,
(b'\x14\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00',
datetime.timezone.badi)),
((181, 1, 1, None, None, 12, 30, 30, 500000), datetime.BADI, 0,
(b'\x07\xe7\x01\x01\x0c\x1e\x1e\x07\xa1 ',
datetime.timezone.badi)),
)
msg = "Expected {} with date {}, timezone {}, and fold {}, found {}."
for date, tz, fold, expected_result in data:
dt = datetime.datetime(*date, tzinfo=tz, fold=fold)
result = dt._getstate()
self.assertEqual(expected_result, result, msg.format(
expected_result, date, tz, fold, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___setstate(self):
"""
Test that the __setstate method sets the datetime properly.
"""
err_msg0 = "Bad tzinfo state arg."
data = (
((datetime.MINYEAR, 1, 1, None, None, 12, 30, 30, 500000), None,
b'\x00\x00\x01\x01\x0c\x1e\x1e\x07\xa1 ', False),
((-5, 18, 1, 1, 1, 12, 30, 30, 500000), None,
b'\x0e\x12\x01\x01\x01\x0c\x1e\x1e\x07\xa1 ', False),
((1, 1, 1, None, None, 0, 0, 0, 0), datetime.BADI,
b'\x073\x01\x01\x00\x00\x00\x00\x00\x00', False),
((1, 1, 1, 1, 1, 0, 0, 0, 0), datetime.BADI,
b'\x14\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00', False),
((datetime.MINYEAR, 1, 1, None, None, 12, 30, 30, 500000), None,
b'\x00\x00\x01\x01\x0c\x1e\x1e\x07\xa1 ', True),
)
msg = "Expected {} with bytes_str {}, found {}."
for date, tz, bytes_str, validity in data:
dt = datetime.datetime(*date, tzinfo=tz)
if validity:
try:
dt._datetime__setstate(bytes_str, dt)
except TypeError as e:
self.assertEqual(err_msg0, str(e))
else:
raise AssertionError(f"With {date} an error is not raised.")
else:
dt._datetime__setstate(bytes_str, tz)
if dt.is_short:
result = (dt.year, dt.month, dt.day, None, None, dt.hour,
dt.minute, dt.second, dt.microsecond)
else:
result = (dt.kull_i_shay, dt.vahid, dt.year, dt.month,
dt.day, dt.hour, dt.minute, dt.second,
dt.microsecond)
self.assertEqual(date, result, msg.format(
date, bytes_str, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___reduce_ex__(self):
"""
Test that the __reduce_ex__ method creates the correct pickle value
for protocol 3.
"""
data = (
((181, 1, 1, None, None, 12, 30, 30, 500000), datetime.BADI, 0),
((181, 1, 1, None, None, 12, 30, 30, 500000), datetime.UTC, 1),
)
msg = "Expected {}, with date {}, timezone {}, and fold {}, found {}"
for date, tz, fold in data:
dt0 = datetime.datetime(*date, tzinfo=tz, fold=fold)
obj = pickle.dumps(dt0)
dt1 = pickle.loads(obj)
if dt0.is_short:
dt0_result = (dt0.year, dt0.month, dt0.day, dt0.hour,
dt0.minute, dt0.second, dt0.microsecond,
dt0.tzinfo, dt0.fold)
dt1_result = (dt1.year, dt1.month, dt1.day, dt1.hour,
dt1.minute, dt1.second, dt1.microsecond,
dt1.tzinfo, dt1.fold)
else:
dt0_result = (dt0.kull_i_shay, dt0.vahid, dt0.year, dt0.month,
dt0.day, dt0.hour, dt0.minute, dt0.second,
dt0.microsecond, dt0.tzinfo, dt0.fold)
dt1_result = (dt1.kull_i_shay, dt1.vahid, dt1.year, dt1.month,
dt1.day, dt1.hour, dt1.minute, dt1.second,
dt1.microsecond, dt1.tzinfo, dt1.fold)
self.assertEqual(dt0_result, dt1_result, msg.format(
dt0_result, date, tz, fold, dt1_result))
[docs]
class TestBadiDatetime_timezone(unittest.TestCase):
def __init__(self, name):
super().__init__(name)
#@unittest.skip("Temporarily skipped")
[docs]
def test___new__(self):
"""
Test that the __new__ method creates an instance from both a pickle
object and a normal instantiation.
"""
err_msg0 = "offset must be a timedelta"
err_msg1 = "name must be a string"
err_msg2 = ("offset must be a timedelta strictly between "
"-timedelta(hours=24) and timedelta(hours=24), not {}.")
td = datetime.timedelta(hours=datetime.BADI_COORD[2])
IANA = datetime.BADI_IANA
data = (
(td, IANA, False, IANA),
(td, datetime.timezone._Omitted, False, 'UTC+03:30'),
(td, '', False, ''),
(object, IANA, True, err_msg0),
(td, object, True, err_msg1),
(datetime.timedelta(hours=25), '', True,
err_msg2.format('datetime.timedelta(days=1, seconds=3600)')),
)
msg = "Expected {} with offset {} and name {}, found {}."
for offset, name, validity, expected_result in data:
if validity:
try:
result = datetime.timezone(offset, name)
except (TypeError, ValueError) as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {time} an error is not "
f"raised, with result {result}.")
else:
result = datetime.timezone(offset, name)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, offset, name, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___eq__(self):
"""
Test that the __eq__ method returns True if equal and False if
not equal.
"""
td0 = datetime.timedelta(hours=datetime.BADI_COORD[2])
td1 = datetime.timedelta(seconds=18000)
IANA = datetime.BADI_IANA
data = (
(td0, IANA, td0, IANA, True),
(td0, IANA, td1, 'US/Eastern', False),
)
msg = "Expected {} with td0 {} and td1 {}, found {}."
for offset0, name0, offset1, name1, expected_result in data:
tz0 = datetime.timezone(offset0, name0)
tz1 = datetime.timezone(offset1, name1)
result = tz0 == tz1
self.assertEqual(expected_result, result, msg.format(
expected_result, td0, td1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___repr__(self):
"""
Test that the __repr__ method returns the correctly formatted string.
"""
td0 = datetime.timedelta(hours=datetime.BADI_COORD[2])
td1 = datetime.timedelta(0)
td2 = datetime.timedelta()
IANA = datetime.BADI_IANA
data = (
(td0, IANA, "badidatetime.timezone("
"badidatetime.timedelta(seconds=12600), 'Asia/Tehran')"),
(td1, 'UTC', "badidatetime.timezone(badidatetime.timedelta(0), "
"'UTC')"),
(td2, '', "badidatetime.timezone(badidatetime.timedelta(0), '')"),
(td2, None, "badidatetime.timezone(badidatetime.timedelta(0))"),
('UTC', 'UTC', 'badidatetime.timezone.utc'),
('BADI', IANA, 'badidatetime.BADI'),
)
msg = "Expected {} with offset {} and name {}, found {}."
for offset, name, expected_result in data:
if name is None:
tz = datetime.timezone._create(offset, name)
elif offset == 'UTC':
tz = datetime.UTC
elif offset == 'BADI':
tz = datetime.BADI
else:
tz = datetime.timezone(offset, name)
result = repr(tz)
self.assertEqual(expected_result, result, msg.format(
expected_result, offset, name, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___str__(self):
"""
Test that the __str__ method returns the correctly formatted string.
"""
td0 = datetime.timedelta(hours=datetime.BADI_COORD[2])
td1 = datetime.timedelta(seconds=18000)
IANA = datetime.BADI_IANA
data = (
(td0, IANA, IANA),
(td1, 'US/Eastern', 'US/Eastern'),
)
msg = "Expected {} with offset {}, found {}."
for offset, name, expected_result in data:
result = datetime.timezone(offset, name)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, offset, str(result)))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test_utcoffset(self):
"""
Test that the utcoffset method returns the correct timezone offset
for the UTC coordinates.
"""
err_msg0 = "utcoffset() argument must be a datetime instance or None"
td0 = datetime.timedelta(hours=datetime.BADI_COORD[2])
td1 = datetime.timedelta(hours=datetime.LOCAL_COORD[2])
data = (
(td0, (181, 1, 1), False, '3:30:00'),
(td1, (181, 1, 1), False, '-1 day, 19:00:00'),
(td1, None, False, '-1 day, 19:00:00'),
(td0, (12, 30, 30), True, err_msg0),
)
msg = "Expected {} with offset {}, date {}, and timezone {}, found {}."
for offset, date, validity, expected_result in data:
tz0 = datetime.timezone(offset)
if validity:
try:
t = datetime.time(*date)
result = tz0.utcoffset(t)
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {offset} an error is not "
f"raised, with result {result}.")
else:
if isinstance(date, tuple):
dt = datetime.datetime(*date)
else:
dt = date
result = tz0.utcoffset(dt)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, offset, date, tz0, result))
#@unittest.skip("Temporarily skipped")
[docs]
@patch.object(datetime, 'LOCAL_COORD', (35.5894, -78.7792, -5.0))
def test_badioffset(self):
"""
Test that the badioffset returns the correct timezone offset for the
Badi coordinates.
"""
err_msg0 = "badioffset() argument must be a datetime instance or None"
td0 = datetime.timedelta(hours=datetime.BADI_COORD[2])
td1 = datetime.timedelta(hours=datetime.LOCAL_COORD[2])
data = (
(td0, (181, 1, 1), False, '0:00:00'),
(td1, (181, 1, 1), False, '-1 day, 15:30:00'),
(td1, None, False, '-1 day, 15:30:00'),
(td0, (12, 30, 30), True, err_msg0),
)
msg = "Expected {} with offset {}, date {}, and timezone {}, found {}."
for offset, date, validity, expected_result in data:
tz0 = datetime.timezone(offset)
if validity:
try:
t = datetime.time(*date)
result = tz0.badioffset(t)
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {offset} an error is not "
f"raised, with result {result}.")
else:
if isinstance(date, tuple):
dt = datetime.datetime(*date)
else:
dt = date
result = tz0.badioffset(dt)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, offset, date, tz0, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_tzname(self):
"""
Test that the tzname method returns the timezone name.
"""
err_msg0 = "tzname() argument must be a datetime instance or None"
td = datetime.timedelta(hours=datetime.BADI_COORD[2])
IANA = datetime.BADI_IANA
data = (
(td, IANA, (181, 1, 1), False, IANA),
(td, IANA, None, False, IANA),
(td, None, None, False, 'UTC+03:30'),
(td, IANA, False, True, err_msg0),
)
msg = "Expected {} with offset {}, name {}, date {}, and , found {}."
for offset, name, date, validity, expected_result in data:
if name is None:
tz0 = datetime.timezone._create(offset, name)
else:
tz0 = datetime.timezone(offset, name)
if date:
dt = datetime.datetime(*date)
elif date is False:
dt = datetime.time()
else:
dt = date
if validity:
try:
result = tz0.tzname(dt)
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {tz0} an error is not "
f"raised, with result {result}.")
else:
result = tz0.tzname(dt)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, offset, name, date, tz0, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_dst(self):
"""
Test that the dst method always returns None.
"""
err_msg0 = "dst() argument must be a datetime instance or None"
td = datetime.timedelta(hours=datetime.BADI_COORD[2])
IANA = datetime.BADI_IANA
data = (
(td, IANA, (181, 1, 1), None, False, None),
(td, IANA, None, None, False, None),
(td, IANA, False, None, True, err_msg0),
)
msg = ("Expected {} with offset {}, name {}, date {}, and "
"timezone {}, found {}.")
for offset, name, date, tz0, validity, expected_result in data:
tz1 = datetime.timezone(offset, name)
if date:
dt = datetime.datetime(*date)
elif date is False:
dt = datetime.time()
else:
dt = date
if validity:
try:
result = tz1.dst(dt)
except TypeError as e:
self.assertEqual(expected_result, str(e))
else:
result = result if result else None
raise AssertionError(f"With {tz1} an error is not "
f"raised, with result {result}.")
else:
result = tz1.dst(dt)
self.assertEqual(expected_result, result, msg.format(
expected_result, offset, name, date, tz1, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_fromutc(self):
"""
Test that the fromutc method correctly returns an updated dateime
object.
"""
err_msg0 = "fromutc: dt.tzinfo is not self"
err_msg1 = "fromutc() argument must be a datetime instance or None"
offset0 = datetime.timedelta(hours=datetime.BADI_COORD[2])
data = (
((1, 1, 1), offset0, datetime.BADI_IANA, False,
'0001-01-01T03:30:00+03:30'),
((1, 1, 1), offset0, '', True, err_msg0),
((1, 1, 1), offset0, 'INVALID', True, err_msg1),
)
msg = "Expected {} with date {}, offset {}, and name {}, found {}."
for date, offset, name, validity, expected_result in data:
tz = datetime.timezone(offset, name)
if validity:
dt = datetime.datetime(*date) if name == '' else None
try:
tz.fromutc(dt)
except (TypeError, ValueError) as e:
self.assertEqual(expected_result, str(e))
else:
dt = datetime.datetime(*date, tzinfo=tz)
result = str(tz.fromutc(dt))
self.assertEqual(expected_result, result, msg.format(
expected_result, date, offset, name, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test__name_from_offset(self):
"""
Test that the _name_from_offset returns a string indicating the
UTC offset.
"""
td0 = datetime.timedelta(0)
td1 = datetime.timedelta(hours=datetime.BADI_COORD[2])
td2 = datetime.timedelta(-1)
td3 = datetime.timedelta(microseconds=500000)
td4 = datetime.timedelta(seconds=50)
data = (
(td0, 'UTC'),
(td1, "UTC+03:30"),
(td2, 'UTC-24:00'),
(td3, 'UTC+00:00:00.500000'),
(td4, 'UTC+00:00:50'),
)
msg = "Expected {} with offset {} found {}."
for offset, expected_result in data:
tz = datetime.timezone(td0, 'UTC')
result = tz._name_from_offset(offset)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, offset, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___getinitargs__(self):
"""
Test that the __getinitargs__ method returns the arguments that the
timezone class was instantiated with.
"""
BADI_INFO = (datetime.BADI_COORD[2], datetime.BADI_IANA)
data = (
(-5, None, '(datetime.timedelta(days=-1, seconds=68400),)'),
(*BADI_INFO, "(datetime.timedelta(seconds=12600),"
" 'Asia/Tehran')"),
)
msg0 = "Expected {} with offset {} and name {}, found {}."
msg1 = "Expected {}, found {}."
for os, name, expected_result in data:
offset = datetime.timedelta(hours=os)
args = (offset, name) if name else (offset,)
tz = datetime.timezone(*args)
result = tz.__getinitargs__()
self.assertEqual(expected_result, str(result), msg0.format(
expected_result, os, name, result))
p_obj = pickle.dumps(tz)
up_obj = pickle.loads(p_obj)
self.assertEqual(up_obj._offset, tz._offset, msg1.format(
up_obj._offset, tz._offset))
self.assertEqual(up_obj._name, tz._name, msg1.format(
up_obj._name, tz._name))
#@unittest.skip("Temporarily skipped")
[docs]
def test___hash__(self):
"""
Test that the __hash__ method returns a valid hash.
"""
td0 = datetime.timedelta(0)
data = (
(td0, 'UTC'),
)
msg = "offset {} with name {}, found {}."
for offset, name in data:
tz = datetime.timezone(offset, name)
result = hash(tz)
self.assertTrue(len(str(result)) > 15, msg.format(
offset, name, result))
[docs]
class TestBadiDatetime_TZWithCoords(unittest.TestCase):
def __init__(self, name):
super().__init__(name)
#@unittest.skip("Temporarily skipped")
[docs]
def test___new__(self):
"""
Test that the __new__ method returns a valid TZWithCoords object.
"""
data = (
(datetime.BADI_COORD, None, '35.69435, 51.288701, 3.5'),
(datetime.BADI_COORD, 'Asia/Tehran',
'35.69435, 51.288701, 3.5, Asia/Tehran'),
)
msg = "Expected {} with coords {} and key {}, found {}."
for coords, key, expected_result in data:
result = str(datetime.TZWithCoords(*coords, key=key))
self.assertEqual(expected_result, result, msg.format(
expected_result, coords, key, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_coordinates(self):
"""
Test that the coordinates property returns the coordinates.
"""
data = (
(datetime.BADI_COORD, 'Asia/Tehran', (35.69435, 51.288701, 3.5)),
)
msg = "Expected {} with coords {} and key {}, found {}."
for coords, key, expected_result in data:
tz = datetime.TZWithCoords(*coords, key=key)
result = tz.coordinates
self.assertEqual(expected_result, result, msg.format(
expected_result, coords, key, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test_dst(self):
"""
Test that the dst method returns the dst (daylight-savings-time).
"""
zi0 = ZoneInfo(datetime.BADI_IANA)
zi1 = ZoneInfo('US/Eastern')
data = (
((1, 1, 1), None, datetime.BADI_COORD, True, '0:00:00'),
((1, 1, 1), zi0, datetime.BADI_COORD, True, '0:00:00'),
((182, 4, 3), zi1, (35.5894, -78.7792, -4.0), True, '1:00:00'),
((182, 4, 3), zi1, (35.5894, -78.7792, -4.0), False, '0:00:00'),
)
msg = "Expected {} with date {}, zoneinfo {}, and coords {}, found {}."
for date, zi, coords, with_dt, expected_result in data:
if zi:
if with_dt:
tz = datetime.TZWithCoords.fromzoneinfo(zi, *coords)
dt = datetime.datetime(*date, tzinfo=tz)
result = str(tz.dst(dt))
self.assertEqual(expected_result, result, msg.format(
expected_result, date, str(zi), coords, result))
else:
tz = datetime.TZWithCoords.fromzoneinfo(zi, *coords)
result = str(tz.dst())
self.assertEqual(expected_result, result, msg.format(
expected_result, date, str(zi), coords, result))
else:
tz = datetime.TZWithCoords(*coords)
dt = datetime.datetime(*date, tzinfo=tz)
result = str(tz.dst(dt))
self.assertEqual(expected_result, result, msg.format(
expected_result, date, str(zi), coords, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___str__(self):
"""
Test that the __str__ method return the correct string.
"""
data = (
(datetime.BADI_COORD, None, '35.69435, 51.288701, 3.5'),
(datetime.BADI_COORD, datetime.BADI_IANA,
'35.69435, 51.288701, 3.5, Asia/Tehran'),
)
msg = "Expected {} with coords {} and key {}, found {}."
for coords, key, expected_result in data:
result = datetime.TZWithCoords(*coords, key=key)
self.assertEqual(expected_result, str(result), msg.format(
expected_result, coords, key, result))
#@unittest.skip("Temporarily skipped")
[docs]
def test___reduce__(self):
"""
Test that the __reduce__ method returns a correct pickle object.
"""
data = (
(datetime.BADI_COORD, None),
(datetime.BADI_COORD, datetime.BADI_IANA),
)
msg = "Expected {} with coords {} and key {}, found {}."
for coords, key in data:
tz = datetime.TZWithCoords(*coords, key=key)
dt = datetime.datetime(1, 1, 1, tzinfo=tz)
obj = pickle.dumps(tz)
tz_new = pickle.loads(obj)
data0 = (tz.key, tz.coordinates, tz.dst(dt))
data1 = (tz_new.key, tz_new.coordinates, tz_new.dst(dt))
self.assertEqual(data0, data1, msg.format(
data0, coords, key, data1))