Skip to content

Instantly share code, notes, and snippets.

@bukzor
Forked from anonymous/-
Created April 18, 2017 01:19
Show Gist options
  • Save bukzor/cf5c774729280a22b5e016cd65d6f057 to your computer and use it in GitHub Desktop.
Save bukzor/cf5c774729280a22b5e016cd65d6f057 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
from datetime import datetime
from datetime import timedelta
import pytz
import tzlocal
from hypothesis import assume
from hypothesis import given
from hypothesis import note
from hypothesis import strategies as st
MAX_DATETIME = pytz.utc.localize(datetime.max)
MIN_DATETIME = pytz.utc.localize(datetime.min)
MAX_TIMEDELTA = datetime.max - datetime.min
ZERO_TIMEDELTA = datetime.min - datetime.min
@st.composite
def timezones(draw):
draw = draw(st.data()).draw
# hypothesis attempts to give examples using the first thing in the list
# so we put the examples we want first
local_timezone = tzlocal.get_localzone().zone
common_timezones = list(pytz.common_timezones)
common_timezones.remove(local_timezone)
common_timezones.remove('UTC')
common_timezones = tuple(['UTC', local_timezone] + common_timezones)
# ValueError: offset must be a timedelta strictly between
# -timedelta(hours=24) and timedelta(hours=24).
# also, the units for pytz.FixedOffset is minutes, apparently
max_delta = 24 * 60 - 1
tz = draw(st.one_of(
# in order of simplest first
st.builds(
pytz.timezone,
st.sampled_from(common_timezones),
),
st.builds(
pytz.FixedOffset,
st.one_of(
st.integers(min_value=0, max_value=max_delta),
st.integers(min_value=-max_delta, max_value=-0),
),
),
))
print(tz)
return tz
@given(timezones())
def test_timezones(tz):
naivenow = datetime(2000, 4, 2, 9, 30)
utcnow = pytz.utc.localize(naivenow)
assert utcnow == naivenow.replace(tzinfo=pytz.utc)
note(utcnow)
note(tz.utcoffset(naivenow))
t1 = utcnow.astimezone(tz)
note(t1)
assert t1.isoformat()
t2 = tz.normalize(utcnow)
assert t2.isoformat()
assert t1 == t2
@st.composite
def timedeltas(
draw,
min_delta=ZERO_TIMEDELTA,
max_delta=MAX_TIMEDELTA,
):
assert min_delta <= max_delta, (min_delta, max_delta)
draw = draw(st.data()).draw
microseconds_max = (
(max_delta.days - min_delta.days) * 24 * 60 * 60 * 1000**2 +
(max_delta.seconds - min_delta.seconds) * 1000**2 +
(max_delta.microseconds - min_delta.microseconds)
)
microseconds = draw(st.integers(0, microseconds_max))
days, microseconds = divmod(microseconds, 24 * 60 * 60 * 1000**2)
seconds, microseconds = divmod(microseconds, 10**9)
delta = timedelta(days, seconds, microseconds)
return min_delta + delta
@given(timedeltas())
def test_timedelta(t):
assert datetime.min + t
assert datetime.max - t
@st.composite
def naive_timestamps(draw, after=datetime.min, min_delta=ZERO_TIMEDELTA, max_delta=MAX_TIMEDELTA):
assert min_delta <= max_delta, (min_delta, max_delta)
draw = draw(st.data()).draw
max_delta = min(max_delta, datetime.max - after)
return after + draw(timedeltas(min_delta, max_delta))
def assert_timestamp(data, strategy, after, max):
t1 = data.draw(strategy(after=after, max_delta=timedelta(500)))
min_delta = data.draw(timedeltas(ZERO_TIMEDELTA, max - t1))
max_delta = data.draw(timedeltas(min_delta))
assert min_delta <= max_delta
t2 = data.draw(strategy(t1, min_delta, max_delta))
delta = t2 - t1
assert ZERO_TIMEDELTA <= min_delta
assert min_delta <= delta
assert delta <= max_delta
assert max_delta <= MAX_TIMEDELTA
return t2
@given(st.data())
def test_naive_timestamps(data):
t2 = assert_timestamp(data, naive_timestamps, datetime(2000, 1, 1), datetime.max)
assert t2.tzinfo is None
@st.composite
def timestamps(draw, after=MIN_DATETIME, min_delta=ZERO_TIMEDELTA, max_delta=MAX_TIMEDELTA, tz=timezones()):
after = after.astimezone(pytz.utc).replace(tzinfo=None)
result = draw(naive_timestamps(after, min_delta, max_delta))
result = pytz.utc.localize(result)
try:
result = result.astimezone(draw(tz))
except OverflowError:
# in rare cases, our chosen time can't be represented in the timezone
assume(False)
return result
@given(st.data())
def test_timestamps(data):
t2 = assert_timestamp(data, timestamps, datetime(2000, 1, 1, tzinfo=pytz.utc), MAX_DATETIME)
assert t2.tzinfo.normalize(t2) == t2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment