Skip to content

Commit 5b244a2

Browse files
fix(fcm): Convert event_time to UTC (#403)
* fix(fcm): Convert event_time to UTC - Check if the datetime object is naive or timezone aware - If a naive datetime object is provided then set the timezone to local timezone - Convert the event_time to UTC Zulu format * Remove the third party library * Add new test case for naive event_timestamp * Consider naive datetimes are in UTC * Add a comment explaning the logic * Update docs
1 parent 08ed809 commit 5b244a2

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

firebase_admin/_messaging_encoder.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,11 @@ def encode_android_notification(cls, notification):
324324

325325
event_time = result.get('event_time')
326326
if event_time:
327-
result['event_time'] = str(event_time.isoformat()) + 'Z'
327+
# if the datetime instance is not naive (tzinfo is present), convert to UTC
328+
# otherwise (tzinfo is None) assume the datetime instance is already in UTC
329+
if event_time.tzinfo is not None:
330+
event_time = event_time.astimezone(datetime.timezone.utc)
331+
result['event_time'] = event_time.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
328332

329333
priority = result.get('notification_priority')
330334
if priority:

firebase_admin/_messaging_utils.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ class AndroidNotification:
9898
the user clicks it (optional).
9999
event_timestamp: For notifications that inform users about events with an absolute time
100100
reference, sets the time that the event in the notification occurred as a
101-
``datetime.datetime`` instance. Notifications in the panel are sorted by this time
101+
``datetime.datetime`` instance. If the ``datetime.datetime`` instance is naive, it
102+
defaults to be in the UTC timezone. Notifications in the panel are sorted by this time
102103
(optional).
103104
local_only: Sets whether or not this notification is relevant only to the current device.
104105
Some notifications can be bridged to other devices for remote display, such as a Wear OS

tests/test_messaging.py

+27-2
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,10 @@ def test_android_notification(self):
547547
click_action='ca', title_loc_key='tlk', body_loc_key='blk',
548548
title_loc_args=['t1', 't2'], body_loc_args=['b1', 'b2'], channel_id='c',
549549
ticker='ticker', sticky=True,
550-
event_timestamp=datetime.datetime(2019, 10, 20, 15, 12, 23, 123),
550+
event_timestamp=datetime.datetime(
551+
2019, 10, 20, 15, 12, 23, 123,
552+
tzinfo=datetime.timezone(datetime.timedelta(hours=-5))
553+
),
551554
local_only=False,
552555
priority='high', vibrate_timings_millis=[100, 50, 250],
553556
default_vibrate_timings=False, default_sound=True,
@@ -577,7 +580,7 @@ def test_android_notification(self):
577580
'channel_id': 'c',
578581
'ticker': 'ticker',
579582
'sticky': True,
580-
'event_time': '2019-10-20T15:12:23.000123Z',
583+
'event_time': '2019-10-20T20:12:23.000123Z',
581584
'local_only': False,
582585
'notification_priority': 'PRIORITY_HIGH',
583586
'vibrate_timings': ['0.100000000s', '0.050000000s', '0.250000000s'],
@@ -601,6 +604,28 @@ def test_android_notification(self):
601604
}
602605
check_encoding(msg, expected)
603606

607+
def test_android_notification_naive_event_timestamp(self):
608+
event_time = datetime.datetime.now()
609+
msg = messaging.Message(
610+
topic='topic',
611+
android=messaging.AndroidConfig(
612+
notification=messaging.AndroidNotification(
613+
title='t',
614+
event_timestamp=event_time,
615+
)
616+
)
617+
)
618+
expected = {
619+
'topic': 'topic',
620+
'android': {
621+
'notification': {
622+
'title': 't',
623+
'event_time': event_time.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
624+
},
625+
},
626+
}
627+
check_encoding(msg, expected)
628+
604629

605630
class TestLightSettingsEncoder:
606631

0 commit comments

Comments
 (0)