Skip to content

Commit acad2b1

Browse files
authored
fix: datetime comparison issues (#75)
1 parent cb62570 commit acad2b1

File tree

5 files changed

+49
-11
lines changed

5 files changed

+49
-11
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
## 2.1.2 - 2022-09-15
2+
3+
Changes:
4+
5+
1. Fixes issues with date comparison.
16
## 2.1.1 - 2022-09-14
27

38
Changes:
49

5-
1. Feature flags local evaluation now supports date property filters as well. Note that this only supports passing in timezone-unaware datetime objects, or strings.
10+
1. Feature flags local evaluation now supports date property filters as well. Accepts both strings and datetime objects.
611

712
## 2.1.0 - 2022-08-11
813

posthog/feature_flags.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from dateutil import parser
66

7-
from posthog.utils import is_valid_regex
7+
from posthog.utils import convert_to_datetime_aware, is_valid_regex
88

99
__LONG_SCALE__ = float(0xFFFFFFFFFFFFFFF)
1010

@@ -132,17 +132,25 @@ def match_property(property, property_values) -> bool:
132132
if operator in ["is_date_before", "is_date_after"]:
133133
try:
134134
parsed_date = parser.parse(value)
135+
parsed_date = convert_to_datetime_aware(parsed_date)
135136
except Exception:
136137
raise InconclusiveMatchError("The date set on the flag is not a valid format")
137138

138-
if isinstance(override_value, datetime.date):
139+
if isinstance(override_value, datetime.datetime):
140+
override_date = convert_to_datetime_aware(override_value)
139141
if operator == "is_date_before":
140-
return override_value < parsed_date
142+
return override_date < parsed_date
141143
else:
142-
return override_value > parsed_date
144+
return override_date > parsed_date
145+
elif isinstance(override_value, datetime.date):
146+
if operator == "is_date_before":
147+
return override_value < parsed_date.date()
148+
else:
149+
return override_value > parsed_date.date()
143150
elif isinstance(override_value, str):
144151
try:
145152
override_date = parser.parse(override_value)
153+
override_date = convert_to_datetime_aware(override_date)
146154
if operator == "is_date_before":
147155
return override_date < parsed_date
148156
else:

posthog/test/test_feature_flags.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import datetime
12
import unittest
2-
from datetime import datetime
33

44
import mock
5-
from dateutil import parser
5+
from dateutil import parser, tz
66
from freezegun import freeze_time
77

88
from posthog.client import Client
@@ -1124,7 +1124,13 @@ def test_match_property_date_operators(self):
11241124
property_a = self.property(key="key", value="2022-05-01", operator="is_date_before")
11251125
self.assertTrue(match_property(property_a, {"key": "2022-03-01"}))
11261126
self.assertTrue(match_property(property_a, {"key": "2022-04-30"}))
1127-
self.assertTrue(match_property(property_a, {"key": datetime(2022, 4, 30)}))
1127+
self.assertTrue(match_property(property_a, {"key": datetime.date(2022, 4, 30)}))
1128+
self.assertTrue(match_property(property_a, {"key": datetime.datetime(2022, 4, 30, 1, 2, 3)}))
1129+
self.assertTrue(
1130+
match_property(
1131+
property_a, {"key": datetime.datetime(2022, 4, 30, 1, 2, 3, tzinfo=tz.gettz("Europe/Madrid"))}
1132+
)
1133+
)
11281134
self.assertTrue(match_property(property_a, {"key": parser.parse("2022-04-30")}))
11291135
self.assertFalse(match_property(property_a, {"key": "2022-05-30"}))
11301136

@@ -1139,7 +1145,7 @@ def test_match_property_date_operators(self):
11391145
property_b = self.property(key="key", value="2022-05-01", operator="is_date_after")
11401146
self.assertTrue(match_property(property_b, {"key": "2022-05-02"}))
11411147
self.assertTrue(match_property(property_b, {"key": "2022-05-30"}))
1142-
self.assertTrue(match_property(property_b, {"key": datetime(2022, 5, 30)}))
1148+
self.assertTrue(match_property(property_b, {"key": datetime.datetime(2022, 5, 30)}))
11431149
self.assertTrue(match_property(property_b, {"key": parser.parse("2022-05-30")}))
11441150
self.assertFalse(match_property(property_b, {"key": "2022-04-30"}))
11451151

@@ -1153,6 +1159,19 @@ def test_match_property_date_operators(self):
11531159
with self.assertRaises(InconclusiveMatchError):
11541160
match_property(property_c, {"key": 1})
11551161

1162+
# Timezone aware property
1163+
property_d = self.property(key="key", value="2022-04-05 12:34:12 +01:00", operator="is_date_before")
1164+
self.assertFalse(match_property(property_d, {"key": "2022-05-30"}))
1165+
1166+
self.assertTrue(match_property(property_d, {"key": "2022-03-30"}))
1167+
self.assertTrue(match_property(property_d, {"key": "2022-04-05 12:34:11 +01:00"}))
1168+
self.assertTrue(match_property(property_d, {"key": "2022-04-05 12:34:11 +01:00"}))
1169+
1170+
self.assertFalse(match_property(property_d, {"key": "2022-04-05 12:34:13 +01:00"}))
1171+
1172+
self.assertTrue(match_property(property_d, {"key": "2022-04-05 11:34:11 +00:00"}))
1173+
self.assertFalse(match_property(property_d, {"key": "2022-04-05 11:34:13 +00:00"}))
1174+
11561175

11571176
class TestCaptureCalls(unittest.TestCase):
11581177
@mock.patch.object(Client, "capture")

posthog/utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import numbers
33
import re
44
from collections import defaultdict
5-
from datetime import date, datetime
5+
from datetime import date, datetime, timezone
66
from decimal import Decimal
77
from uuid import UUID
88

@@ -109,3 +109,9 @@ def __setitem__(self, key, value):
109109
self.clear()
110110

111111
super().__setitem__(key, value)
112+
113+
114+
def convert_to_datetime_aware(date_obj):
115+
if date_obj.tzinfo is None:
116+
date_obj = date_obj.replace(tzinfo=timezone.utc)
117+
return date_obj

posthog/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = "2.1.1"
1+
VERSION = "2.1.2"
22

33
if __name__ == "__main__":
44
print(VERSION, end="")

0 commit comments

Comments
 (0)