Skip to content

Commit 7ccbe68

Browse files
jspricketbabej
authored andcommitted
Simplify timezone handling
astimezone() assumes the system local timezone if called without arguments . https://docs.python.org/3.10/library/datetime.html#datetime.datetime.astimezone This is a API break as it removes the local_zone symbol.
1 parent 2002052 commit 7ccbe68

File tree

6 files changed

+16
-25
lines changed

6 files changed

+16
-25
lines changed

docs/index.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,7 @@ If you want to compare datetime aware value with datetime naive value, you need
359359
to localize the naive value first:
360360

361361
>>> from datetime import datetime
362-
>>> from tasklib.task import local_zone
363-
>>> now = datetime.now().replace(tzinfo=local_zone)
362+
>>> now = datetime.now().astimezone()
364363
>>> t['due'] = now
365364
>>> now
366365
datetime.datetime(2015, 2, 1, 19, 44, 4, 770001, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)

tasklib/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from .backends import TaskWarrior
22
from .task import Task
3-
from .serializing import local_zone
43

54
__version__ = '2.5.0'

tasklib/backends.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
from .task import Task, TaskQuerySet, ReadOnlyDictView
1212
from .filters import TaskWarriorFilter
13-
from .serializing import local_zone
1413

1514
DATE_FORMAT_CALC = '%Y-%m-%dT%H:%M:%S'
1615

@@ -225,7 +224,7 @@ def convert_datetime_string(self, value):
225224
args = value.split()
226225
result = self.execute_command(['calc'] + args)
227226
naive = datetime.datetime.strptime(result[0], DATE_FORMAT_CALC)
228-
localized = naive.replace(tzinfo=local_zone)
227+
localized = naive.astimezone()
229228
return localized
230229

231230
@property

tasklib/serializing.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from .lazy import LazyUUIDTaskSet, LazyUUIDTask
1111

1212
DATE_FORMAT = '%Y%m%dT%H%M%SZ'
13-
local_zone = ZoneInfo('localtime')
1413

1514

1615
class SerializingObject(object):
@@ -86,7 +85,7 @@ def timestamp_deserializer(self, date_str):
8685
# Return timestamp localized in the local zone
8786
naive_timestamp = datetime.datetime.strptime(date_str, DATE_FORMAT)
8887
localized_timestamp = naive_timestamp.replace(tzinfo=ZoneInfo('UTC'))
89-
return localized_timestamp.astimezone(local_zone)
88+
return localized_timestamp.astimezone()
9089

9190
def serialize_entry(self, value):
9291
return self.timestamp_serializer(value)
@@ -228,11 +227,11 @@ def datetime_normalizer(self, value):
228227
):
229228
# Convert to local midnight
230229
value_full = datetime.datetime.combine(value, datetime.time.min)
231-
localized = value_full.replace(tzinfo=local_zone)
230+
localized = value_full.astimezone()
232231
elif isinstance(value, datetime.datetime):
233232
if value.tzinfo is None:
234233
# Convert to localized datetime object
235-
localized = value.replace(tzinfo=local_zone)
234+
localized = value.astimezone()
236235
else:
237236
# If the value is already localized, there is no need to change
238237
# time zone at this point. Also None is a valid value too.

tasklib/task.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import os
88
import sys
99

10-
from .serializing import SerializingObject, local_zone
10+
from .serializing import SerializingObject
1111

1212
DATE_FORMAT = '%Y%m%dT%H%M%SZ'
1313
REPR_OUTPUT_SIZE = 10
@@ -299,7 +299,7 @@ def waiting(self):
299299
if not self['wait']:
300300
return False
301301

302-
return self['wait'] > datetime.datetime.now().replace(tzinfo=local_zone)
302+
return self['wait'] > datetime.datetime.now().astimezone()
303303

304304
@property
305305
def pending(self):

tasklib/tests.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from .backends import TaskWarrior
1919
from .task import Task, ReadOnlyDictView
2020
from .lazy import LazyUUIDTask, LazyUUIDTaskSet
21-
from .serializing import DATE_FORMAT, local_zone
21+
from .serializing import DATE_FORMAT
2222

2323
# http://taskwarrior.org/docs/design/task.html , Section: The Attributes
2424
TASK_STANDARD_ATTRS = (
@@ -1134,10 +1134,9 @@ class TimezoneAwareDatetimeTest(TasklibTest):
11341134

11351135
def setUp(self):
11361136
super(TimezoneAwareDatetimeTest, self).setUp()
1137-
self.zone = local_zone
11381137
self.localdate_naive = datetime.datetime(2015, 2, 2)
11391138
self.localtime_naive = datetime.datetime(2015, 2, 2, 0, 0, 0)
1140-
self.localtime_aware = self.localtime_naive.replace(tzinfo=self.zone)
1139+
self.localtime_aware = self.localtime_naive.astimezone()
11411140
self.utctime_aware = self.localtime_aware.astimezone(ZoneInfo('UTC'))
11421141

11431142
def test_timezone_naive_datetime_setitem(self):
@@ -1219,7 +1218,7 @@ def test_simple_now_conversion(self):
12191218
return
12201219

12211220
t = Task(self.tw, description='test task', due='now')
1222-
now = datetime.datetime.now().replace(tzinfo=local_zone)
1221+
now = datetime.datetime.now().astimezone()
12231222

12241223
# Assert that both times are not more than 5 seconds apart
12251224
if sys.version_info < (2, 7):
@@ -1239,16 +1238,15 @@ def test_simple_eoy_conversion(self):
12391238
return
12401239

12411240
t = Task(self.tw, description='test task', due='eoy')
1242-
now = datetime.datetime.now().replace(tzinfo=local_zone)
1241+
now = datetime.datetime.now().astimezone()
12431242
eoy = datetime.datetime(
12441243
year=now.year,
12451244
month=12,
12461245
day=31,
12471246
hour=23,
12481247
minute=59,
12491248
second=59,
1250-
tzinfo=local_zone
1251-
)
1249+
).astimezone()
12521250
if self.tw.version >= '2.5.2' and self.tw.version < '2.6.0':
12531251
eoy = datetime.datetime(
12541252
year=now.year+1,
@@ -1257,8 +1255,7 @@ def test_simple_eoy_conversion(self):
12571255
hour=0,
12581256
minute=0,
12591257
second=0,
1260-
tzinfo=local_zone
1261-
)
1258+
).astimezone()
12621259
self.assertEqual(eoy, t['due'])
12631260

12641261
def test_complex_eoy_conversion(self):
@@ -1271,16 +1268,15 @@ def test_complex_eoy_conversion(self):
12711268
return
12721269

12731270
t = Task(self.tw, description='test task', due='eoy - 2 months')
1274-
now = datetime.datetime.now().replace(tzinfo=local_zone)
1271+
now = datetime.datetime.now().astimezone()
12751272
due_date = datetime.datetime(
12761273
year=now.year,
12771274
month=12,
12781275
day=31,
12791276
hour=23,
12801277
minute=59,
12811278
second=59,
1282-
tzinfo=local_zone
1283-
) - datetime.timedelta(0, 2 * 30 * 86400)
1279+
).astimezone() - datetime.timedelta(0, 2 * 30 * 86400)
12841280
if self.tw.version >= '2.5.2' and self.tw.version < '2.6.0':
12851281
due_date = datetime.datetime(
12861282
year=now.year+1,
@@ -1289,8 +1285,7 @@ def test_complex_eoy_conversion(self):
12891285
hour=0,
12901286
minute=0,
12911287
second=0,
1292-
tzinfo=local_zone
1293-
) - datetime.timedelta(0, 2 * 30 * 86400)
1288+
).astimezone() - datetime.timedelta(0, 2 * 30 * 86400)
12941289
self.assertEqual(due_date, t['due'])
12951290

12961291
def test_filtering_with_string_datetime(self):

0 commit comments

Comments
 (0)