Skip to content

Conversation

@cssherry
Copy link
Contributor

@cssherry cssherry commented Jun 8, 2018

Summary of changes

As described in python bug tracker (https://bugs.python.org/issue5288), datetime now allows offsets that are not an integer number of minutes. Dateutil now accounts for this when running in newer versions of python

  • Add "Africa/Monrovia" to test_resolve_imaginary test for python 3.6 or newer
  • Test that partial minutes is supported in python 3.6 or newer for tz.tzfile and datetime.utcoffset
  • Enable partial minutes in both tz.tzoffset and tz.tzfile
  • For now, don't warn user when rounding to nearest minute for python pre-3.6

Closes #582

Pull Request Checklist

  • Changes have tests
  • Authors have been added to AUTHORS.md
  • News fragment added in changelog.d. See CONTRIBUTING.md for details

@cssherry cssherry force-pushed the partial_minutes_582 branch from 630a6fe to 091c496 Compare June 8, 2018 16:38
@cssherry cssherry force-pushed the partial_minutes_582 branch 3 times, most recently from 8d88191 to d2600d8 Compare June 8, 2018 16:56
return (dt.replace(tzinfo=None) - EPOCH).total_seconds()


def supports_seconds():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not like to change the public API at all with this, there should be no way to query this.

Also, this has a runtime cost when I would prefer an import-time cost.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, made private and calculate correct function at import

self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
"1900-01-01 00:00:00+01:40")
# For python version pre-3.6, this will be rounded
set_as_old_python()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to mock out the old behavior - we don't need to verify that this behavior is accurate on all versions of Python. It's best to split this into two tests, one for pre-3.6 and one for 3.6+, and then use pytest.skipif to run them selectively based on version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@cssherry cssherry force-pushed the partial_minutes_582 branch 2 times, most recently from b81d332 to 6413db4 Compare June 8, 2018 23:29
def testPartialMinuteSupport(self):
# If user running python 3.6 or newer, exact offset is used
tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI)))
self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would prefer a test that looks like this:

assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset() == timedelta(hours=1, minutes=39, seconds=52)

Though I am a bit torn because I will admit that the "compare the string" version sure is easy to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original was with string (see testRoundNonFullMinutes), but I can change them both to timedelta.

However, note that the two would test slightly different things (assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset() == timedelta(hours=1, minutes=39, seconds=52) tests the date offset through utcoffset function, while the current version tests just the date formation from specified offset)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make the change, but in separate commit for easy undo in case we decide to go with original method

self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
"1900-01-01 00:00:00+01:39:52")

delta = timedelta(hours=12, seconds=30)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer this to be a separate test (or better yet, a parametrized test).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, made this and second part of testRoundNonFullMinutes separate tests

@cssherry cssherry force-pushed the partial_minutes_582 branch from dbc0a17 to 29605a0 Compare June 10, 2018 13:26
Copy link
Contributor Author

@cssherry cssherry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed there's also offset in tzlocal class and tzfile.fromutc function. Not sure where/if that needs to get trimmed, but haven't touched them

assert dt_r == dt_exp
assert dt_r.tzname() == dt_exp.tzname()
assert dt_r.utcoffset() == dt_exp.utcoffset()
if tz.supports_seconds() or tzi != tz.gettz('Africa/Monrovia'):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, just remove Africa/Monrovia test from this set of tests

sys.version_info[0] > 3


def get_supported_offset(offset):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also offset in tzlocal class. Not sure where/if that needs to get trimmed

self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
"1900-01-01 00:00:00+01:40")
# For python version pre-3.6, this will be rounded
set_as_old_python()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return (dt.replace(tzinfo=None) - EPOCH).total_seconds()


def supports_seconds():
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, made private and calculate correct function at import

self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
"1900-01-01 00:00:00+01:39:52")

delta = timedelta(hours=12, seconds=30)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, made this and second part of testRoundNonFullMinutes separate tests

def testPartialMinuteSupport(self):
# If user running python 3.6 or newer, exact offset is used
tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI)))
self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original was with string (see testRoundNonFullMinutes), but I can change them both to timedelta.

However, note that the two would test slightly different things (assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset() == timedelta(hours=1, minutes=39, seconds=52) tests the date offset through utcoffset function, while the current version tests just the date formation from specified offset)

def testPartialMinuteSupport(self):
# If user running python 3.6 or newer, exact offset is used
tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI)))
self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make the change, but in separate commit for easy undo in case we decide to go with original method

tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI)))
self.assertEqual(str(datetime(1900, 1, 1, 0, 0, tzinfo=tzc)),
"1900-01-01 00:00:00+01:40")
assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset(), timedelta(hours=1, minutes=40)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be:

assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset() == timedelta(hours=1, minutes=40)

@cssherry cssherry force-pushed the partial_minutes_582 branch 2 times, most recently from 0ed3eb6 to d676718 Compare June 18, 2018 21:18
@pganssle pganssle force-pushed the partial_minutes_582 branch from d676718 to 44e4a6c Compare June 18, 2018 22:54
cssherry and others added 2 commits June 18, 2018 19:09
- Add "Africa/Monrovia" to test_resolve_imaginary test for python 3.6 or newer
- Test that partial minutes is supported in python 3.6 or newer for tz.tzfile and datetime.utcoffset
- Enable partial minutes in both tz.tzoffset and tz.tzfile
- For now, don't warn user when rounding to nearest minute for python pre-3.6
@pganssle pganssle force-pushed the partial_minutes_582 branch from 44e4a6c to 41e5176 Compare June 18, 2018 23:09
@pganssle pganssle merged commit 6dde5d6 into dateutil:master Jun 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tzfile does not support non-integer minute offsets

2 participants