Skip to content

Commit

Permalink
Fix DateField for GMT+ users (#4371)
Browse files Browse the repository at this point in the history
* convert to timezone only if datetime is tzaware; add exposing test
  • Loading branch information
swheaton authored May 9, 2024
1 parent cfa2c6e commit 89f312d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
10 changes: 8 additions & 2 deletions fiftyone/core/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,14 @@ def to_python(self, value):

# Explicitly converting to UTC is important here because PyMongo loads
# everything as `datetime`, which will respect `fo.config.timezone`,
# but we always need UTC here for the conversion back to `date`
return value.astimezone(pytz.utc).date()
# but we always need UTC here for the conversion back to `date` because
# we write to the DB in UTC time.
# If value is timezone unaware, then do not convert because it will be
# assumed to be in local timezone and date will be wrong for GMT+
# localities.
if value.tzinfo is not None:
value = value.astimezone(pytz.utc)
return value.date()

def validate(self, value):
if not isinstance(value, date):
Expand Down
2 changes: 1 addition & 1 deletion fiftyone/core/odm/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ def get_async_db_conn(use_global=False):
def _apply_options(db):
timezone = fo.config.timezone

if not timezone or timezone.lower() == "utc":
if not timezone:
return db

if timezone.lower() == "local":
Expand Down
17 changes: 17 additions & 0 deletions tests/unittests/dataset_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
| `voxel51.com <https://voxel51.com/>`_
|
"""
import time
from copy import deepcopy, copy
from datetime import date, datetime, timedelta
import gc
Expand Down Expand Up @@ -558,6 +559,22 @@ def test_date_fields(self):
self.assertEqual(type(sample.date), date)
self.assertEqual(int((sample.date - date1).total_seconds()), 0)

# Now change system time to something GMT+
system_timezone = os.environ.get("TZ")
try:
os.environ["TZ"] = "Europe/Madrid"
time.tzset()
dataset.reload()
finally:
if system_timezone is None:
del os.environ["TZ"]
else:
os.environ["TZ"] = system_timezone
time.tzset()

self.assertEqual(type(sample.date), date)
self.assertEqual(int((sample.date - date1).total_seconds()), 0)

@drop_datasets
def test_datetime_fields(self):
dataset = fo.Dataset()
Expand Down

0 comments on commit 89f312d

Please sign in to comment.