[formatter] fix local DST datetime offsets for ':O'
'O' would get the *current* local UTC offset and apply it to all 'datetime' objects it gets applied to. This would result in a wrong offset if the current offset includes DST and the target 'datetime' does not or vice-versa. 'O' now determines the correct local UTC offset while respecting DST for each individual 'datetime'.
This commit is contained in:
@@ -375,18 +375,18 @@ def _parse_offset(format_spec, default):
|
||||
fmt = _build_format_func(format_spec, default)
|
||||
|
||||
if not offset or offset == "local":
|
||||
is_dst = time.daylight and time.localtime().tm_isdst > 0
|
||||
offset = -(time.altzone if is_dst else time.timezone)
|
||||
def off(dt):
|
||||
local = time.localtime(util.datetime_to_timestamp(dt))
|
||||
return fmt(dt + datetime.timedelta(0, local.tm_gmtoff))
|
||||
else:
|
||||
hours, _, minutes = offset.partition(":")
|
||||
offset = 3600 * int(hours)
|
||||
if minutes:
|
||||
offset += 60 * (int(minutes) if offset > 0 else -int(minutes))
|
||||
offset = datetime.timedelta(0, offset)
|
||||
|
||||
offset = datetime.timedelta(seconds=offset)
|
||||
|
||||
def off(obj):
|
||||
return fmt(obj + offset)
|
||||
def off(obj):
|
||||
return fmt(obj + offset)
|
||||
return off
|
||||
|
||||
|
||||
|
||||
@@ -31,8 +31,9 @@ class TestFormatter(unittest.TestCase):
|
||||
"h": "<p>foo </p> & bar <p> </p>",
|
||||
"u": "'< / >'",
|
||||
"t": 1262304000,
|
||||
"dt": datetime.datetime(2010, 1, 1),
|
||||
"ds": "2010-01-01T01:00:00+0100",
|
||||
"dt": datetime.datetime(2010, 1, 1),
|
||||
"dt_dst": datetime.datetime(2010, 6, 1),
|
||||
"name": "Name",
|
||||
"title1": "Title",
|
||||
"title2": "",
|
||||
@@ -236,19 +237,18 @@ class TestFormatter(unittest.TestCase):
|
||||
self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z/O1}", "2010-01-01 01:00:00")
|
||||
self._run_test("{t!d:O2}", "2010-01-01 02:00:00")
|
||||
|
||||
orig_daylight = time.daylight
|
||||
orig_timezone = time.timezone
|
||||
orig_altzone = time.altzone
|
||||
try:
|
||||
time.daylight = False
|
||||
time.timezone = -3600
|
||||
self._run_test("{dt:O}", "2010-01-01 01:00:00")
|
||||
time.timezone = 7200
|
||||
self._run_test("{dt:Olocal}", "2009-12-31 22:00:00")
|
||||
finally:
|
||||
time.daylight = orig_daylight
|
||||
time.timezone = orig_timezone
|
||||
time.altzone = orig_altzone
|
||||
def test_offset_local(self):
|
||||
ts = self.kwdict["dt"].replace(tzinfo=datetime.UTC).timestamp()
|
||||
offset = time.localtime(ts).tm_gmtoff
|
||||
dt = self.kwdict["dt"] + datetime.timedelta(seconds=offset)
|
||||
self._run_test("{dt:O}", str(dt))
|
||||
self._run_test("{dt:Olocal}", str(dt))
|
||||
|
||||
ts = self.kwdict["dt_dst"].replace(tzinfo=datetime.UTC).timestamp()
|
||||
offset = time.localtime(ts).tm_gmtoff
|
||||
dt = self.kwdict["dt_dst"] + datetime.timedelta(seconds=offset)
|
||||
self._run_test("{dt_dst:O}", str(dt))
|
||||
self._run_test("{dt_dst:Olocal}", str(dt))
|
||||
|
||||
def test_sort(self):
|
||||
self._run_test("{l:S}" , "['a', 'b', 'c']")
|
||||
|
||||
Reference in New Issue
Block a user