|
29 | 29 | import uuid
|
30 | 30 | from collections import OrderedDict, abc
|
31 | 31 | from io import BytesIO
|
| 32 | +from typing import Optional |
32 | 33 |
|
33 | 34 | sys.path[0:0] = [""]
|
34 | 35 |
|
@@ -1301,19 +1302,34 @@ def test_tz_clamping_utc(self):
|
1301 | 1302 | )
|
1302 | 1303 |
|
1303 | 1304 | def test_tz_clamping_non_utc(self):
|
1304 |
| - # Aware clamping non-utc. |
1305 |
| - tz = FixedOffset(60, "Custom") |
| 1305 | + class DivergentTimezone(FixedOffset): |
| 1306 | + """A timezone that reverses the offset for dates before 1970.""" |
| 1307 | + |
| 1308 | + def utcoffset(self, dt: Optional[datetime]) -> datetime.timedelta: |
| 1309 | + if dt is None: |
| 1310 | + raise TypeError("DivergentTimezone.utcoffset requires a datetime") |
| 1311 | + offset = super().utcoffset(dt) |
| 1312 | + if dt.year < 1970: |
| 1313 | + return -offset |
| 1314 | + return offset |
| 1315 | + |
| 1316 | + tz = DivergentTimezone(60, "Custom") |
1306 | 1317 | opts = CodecOptions(
|
1307 | 1318 | datetime_conversion=DatetimeConversion.DATETIME_CLAMP, tz_aware=True, tzinfo=tz
|
1308 | 1319 | )
|
1309 | 1320 | # Min/max values in this timezone which can be represented in both BSON and datetime UTC.
|
1310 |
| - min_tz = datetime.datetime.min.replace(tzinfo=utc).astimezone(tz) |
| 1321 | + min_tz = ( |
| 1322 | + datetime.datetime.min.replace(tzinfo=utc) + datetime.timedelta(minutes=60) |
| 1323 | + ).astimezone(tz) |
1311 | 1324 | max_tz = (
|
1312 |
| - (datetime.datetime.max - datetime.timedelta(minutes=60)) |
1313 |
| - .replace(tzinfo=utc) |
1314 |
| - .astimezone(tz) |
1315 |
| - .replace(microsecond=999000) |
1316 |
| - ) |
| 1325 | + datetime.datetime.max.replace(tzinfo=utc, microsecond=999000) |
| 1326 | + - datetime.timedelta(minutes=60) |
| 1327 | + ).astimezone(tz) |
| 1328 | + # Sanity check: |
| 1329 | + self.assertEqual(min_tz, datetime.datetime.min.replace(tzinfo=tz)) |
| 1330 | + self.assertEqual(max_tz, datetime.datetime.max.replace(tzinfo=tz, microsecond=999000)) |
| 1331 | + self.assertEqual(tz.utcoffset(datetime.datetime.min), datetime.timedelta(minutes=-60)) |
| 1332 | + self.assertEqual(tz.utcoffset(datetime.datetime.max), datetime.timedelta(minutes=60)) |
1317 | 1333 | for in_range in [
|
1318 | 1334 | min_tz,
|
1319 | 1335 | min_tz + datetime.timedelta(milliseconds=1),
|
|
0 commit comments