Skip to content

Commit 82ea659

Browse files
Use correct UTC time when creating Meetecho conferences. Fixes ietf-tools#3565. Commit ready for merge.
- Legacy-Id: 19969
1 parent f0d4068 commit 82ea659

4 files changed

Lines changed: 54 additions & 41 deletions

File tree

ietf/meeting/helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1099,7 +1099,7 @@ def create_interim_session_conferences(sessions):
10991099
confs = meetecho_manager.create(
11001100
group=session.group,
11011101
description=str(session),
1102-
start_time=ts.time,
1102+
start_time=ts.utc_start_time(),
11031103
duration=ts.duration,
11041104
)
11051105
except Exception as err:

ietf/meeting/tests_helpers.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,8 @@ def test_sessions_post_cancel_delete_exception(self, mock):
456456
def test_create_interim_session_conferences(self, mock):
457457
mock_conf_mgr = mock.return_value # "instance" seen by the internals
458458
sessions = [
459-
SessionFactory(meeting__type_id='interim', remote_instructions='junk'),
460-
SessionFactory(meeting__type_id='interim', remote_instructions=''),
459+
SessionFactory(meeting__type_id='interim', meeting__time_zone='america/halifax', remote_instructions='junk'),
460+
SessionFactory(meeting__type_id='interim', meeting__time_zone='asia/kuala_lumpur', remote_instructions=''),
461461
]
462462
timeslots = [
463463
session.official_timeslotassignment().timeslot for session in sessions
@@ -482,18 +482,18 @@ def test_create_interim_session_conferences(self, mock):
482482
mock_conf_mgr.create.return_value = [
483483
Conference(
484484
manager=mock_conf_mgr, id=1, public_id='some-uuid', description='desc',
485-
start_time=timeslots[0].time, duration=timeslots[0].duration, url='fake-meetecho-url',
485+
start_time=timeslots[0].utc_start_time(), duration=timeslots[0].duration, url='fake-meetecho-url',
486486
deletion_token='please-delete-me',
487487
),
488488
]
489489
create_interim_session_conferences([sessions[0]])
490490
self.assertTrue(mock_conf_mgr.create.called)
491-
self.assertCountEqual(
491+
self.assertEqual(
492492
mock_conf_mgr.create.call_args[1],
493493
{
494494
'group': sessions[0].group,
495495
'description': str(sessions[0]),
496-
'start_time': timeslots[0].time,
496+
'start_time': timeslots[0].utc_start_time(),
497497
'duration': timeslots[0].duration,
498498
}
499499
)
@@ -507,30 +507,30 @@ def test_create_interim_session_conferences(self, mock):
507507
mock_conf_mgr.create.side_effect = [
508508
[Conference(
509509
manager=mock_conf_mgr, id=1, public_id='some-uuid', description='desc',
510-
start_time=timeslots[0].time, duration=timeslots[0].duration, url='different-fake-meetecho-url',
510+
start_time=timeslots[0].utc_start_time(), duration=timeslots[0].duration, url='different-fake-meetecho-url',
511511
deletion_token='please-delete-me',
512512
)],
513513
[Conference(
514514
manager=mock_conf_mgr, id=2, public_id='another-uuid', description='desc',
515-
start_time=timeslots[1].time, duration=timeslots[1].duration, url='another-fake-meetecho-url',
515+
start_time=timeslots[1].utc_start_time(), duration=timeslots[1].duration, url='another-fake-meetecho-url',
516516
deletion_token='please-delete-me-too',
517517
)],
518518
]
519519
create_interim_session_conferences([sessions[0], sessions[1]])
520520
self.assertTrue(mock_conf_mgr.create.called)
521-
self.assertCountEqual(
521+
self.assertEqual(
522522
mock_conf_mgr.create.call_args_list,
523523
[
524524
({
525525
'group': sessions[0].group,
526526
'description': str(sessions[0]),
527-
'start_time': timeslots[0].time,
527+
'start_time': timeslots[0].utc_start_time(),
528528
'duration': timeslots[0].duration,
529529
},),
530530
({
531531
'group': sessions[1].group,
532532
'description': str(sessions[1]),
533-
'start_time': timeslots[1].time,
533+
'start_time': timeslots[1].utc_start_time(),
534534
'duration': timeslots[1].duration,
535535
},),
536536
]

ietf/utils/meetecho.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515

1616
from datetime import datetime, timedelta
1717
from json import JSONDecodeError
18+
from pytz import utc
1819
from typing import Dict, Sequence, Union
1920
from urllib.parse import urljoin
2021

2122

2223
class MeetechoAPI:
24+
timezone = utc
25+
2326
def __init__(self, api_base: str, client_id: str, client_secret: str, request_timeout=3.01):
2427
self.client_id = client_id
2528
self.client_secret = client_secret
@@ -57,10 +60,10 @@ def _request(self, method, url, api_token=None, json=None):
5760
return None
5861

5962
def _deserialize_time(self, s: str) -> datetime:
60-
return datetime.strptime(s, '%Y-%m-%d %H:%M:%S')
63+
return self.timezone.localize(datetime.strptime(s, '%Y-%m-%d %H:%M:%S'))
6164

6265
def _serialize_time(self, dt: datetime) -> str:
63-
return dt.strftime('%Y-%m-%d %H:%M:%S')
66+
return dt.astimezone(self.timezone).strftime('%Y-%m-%d %H:%M:%S')
6467

6568
def _deserialize_duration(self, minutes: int) -> timedelta:
6669
return timedelta(minutes=minutes)

ietf/utils/tests_meetecho.py

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import requests
55
import requests_mock
66

7+
from pytz import timezone, utc
78
from unittest.mock import patch
89
from urllib.parse import urljoin
910

@@ -91,7 +92,7 @@ def test_schedule_meeting(self):
9192
api = MeetechoAPI(API_BASE, CLIENT_ID, CLIENT_SECRET)
9293
api_response = api.schedule_meeting(
9394
wg_token='my-token',
94-
start_time=datetime.datetime(2021, 9, 14, 10, 0, 0),
95+
start_time=utc.localize(datetime.datetime(2021, 9, 14, 10, 0, 0)),
9596
duration=datetime.timedelta(minutes=130),
9697
description='interim-2021-wgname-01',
9798
extrainfo='message for staff',
@@ -117,23 +118,32 @@ def test_schedule_meeting(self):
117118
},
118119
'Incorrect request content'
119120
)
120-
self.assertEqual(
121-
api_response,
122-
{
123-
'rooms': {
124-
'3d55bce0-535e-4ba8-bb8e-734911cf3c32': {
125-
'room': {
126-
'id': 18,
127-
'start_time': datetime.datetime(2021, 9, 14, 10, 0, 0),
128-
'duration': datetime.timedelta(minutes=130),
129-
'description': 'interim-2021-wgname-01',
121+
# same time in different time zones
122+
for start_time in [
123+
utc.localize(datetime.datetime(2021, 9, 14, 10, 0, 0)),
124+
timezone('america/halifax').localize(datetime.datetime(2021, 9, 14, 7, 0, 0)),
125+
timezone('europe/kiev').localize(datetime.datetime(2021, 9, 14, 13, 0, 0)),
126+
timezone('pacific/easter').localize(datetime.datetime(2021, 9, 14, 5, 0, 0)),
127+
timezone('africa/porto-novo').localize(datetime.datetime(2021, 9, 14, 11, 0, 0)),
128+
]:
129+
self.assertEqual(
130+
api_response,
131+
{
132+
'rooms': {
133+
'3d55bce0-535e-4ba8-bb8e-734911cf3c32': {
134+
'room': {
135+
'id': 18,
136+
'start_time': start_time,
137+
'duration': datetime.timedelta(minutes=130),
138+
'description': 'interim-2021-wgname-01',
139+
},
140+
'url': 'https://meetings.conf.meetecho.com/interim/?short=3d55bce0-535e-4ba8-bb8e-734911cf3c32',
141+
'deletion_token': 'session-deletion-token',
130142
},
131-
'url': 'https://meetings.conf.meetecho.com/interim/?short=3d55bce0-535e-4ba8-bb8e-734911cf3c32',
132-
'deletion_token': 'session-deletion-token',
133-
},
134-
}
135-
},
136-
)
143+
}
144+
},
145+
f'Incorrect time conversion for {start_time.tzinfo.zone}',
146+
)
137147

138148
def test_fetch_meetings(self):
139149
self.maxDiff = 2048
@@ -181,7 +191,7 @@ def test_fetch_meetings(self):
181191
'3d55bce0-535e-4ba8-bb8e-734911cf3c32': {
182192
'room': {
183193
'id': 18,
184-
'start_time': datetime.datetime(2021, 9, 14, 10, 0, 0),
194+
'start_time': utc.localize(datetime.datetime(2021, 9, 14, 10, 0, 0)),
185195
'duration': datetime.timedelta(minutes=130),
186196
'description': 'interim-2021-wgname-01',
187197
},
@@ -191,7 +201,7 @@ def test_fetch_meetings(self):
191201
'e68e96d4-d38f-475b-9073-ecab46ca96a5': {
192202
'room': {
193203
'id': 23,
194-
'start_time': datetime.datetime(2021, 9, 15, 14, 30, 0),
204+
'start_time': utc.localize(datetime.datetime(2021, 9, 15, 14, 30, 0)),
195205
'duration': datetime.timedelta(minutes=30),
196206
'description': 'interim-2021-wgname-02',
197207
},
@@ -239,7 +249,7 @@ def test_request_helper_exception(self):
239249

240250
def test_time_serialization(self):
241251
"""Time de/serialization should be consistent"""
242-
time = datetime.datetime.now().replace(microsecond=0) # cut off to 0 microseconds
252+
time = datetime.datetime.now(utc).replace(microsecond=0) # cut off to 0 microseconds
243253
api = MeetechoAPI(API_BASE, CLIENT_ID, CLIENT_SECRET)
244254
self.assertEqual(api._deserialize_time(api._serialize_time(time)), time)
245255

@@ -253,7 +263,7 @@ def test_conference_from_api_dict(self):
253263
'session-1-uuid': {
254264
'room': {
255265
'id': 1,
256-
'start_time': datetime.datetime(2022,2,4,1,2,3),
266+
'start_time': utc.localize(datetime.datetime(2022,2,4,1,2,3)),
257267
'duration': datetime.timedelta(minutes=45),
258268
'description': 'some-description',
259269
},
@@ -263,7 +273,7 @@ def test_conference_from_api_dict(self):
263273
'session-2-uuid': {
264274
'room': {
265275
'id': 2,
266-
'start_time': datetime.datetime(2022,2,5,4,5,6),
276+
'start_time': utc.localize(datetime.datetime(2022,2,5,4,5,6)),
267277
'duration': datetime.timedelta(minutes=90),
268278
'description': 'another-description',
269279
},
@@ -280,7 +290,7 @@ def test_conference_from_api_dict(self):
280290
id=1,
281291
public_id='session-1-uuid',
282292
description='some-description',
283-
start_time=datetime.datetime(2022,2,4,1,2,3),
293+
start_time=utc.localize(datetime.datetime(2022, 2, 4, 1, 2, 3)),
284294
duration=datetime.timedelta(minutes=45),
285295
url='https://example.com/some/url',
286296
deletion_token='delete-me',
@@ -290,7 +300,7 @@ def test_conference_from_api_dict(self):
290300
id=2,
291301
public_id='session-2-uuid',
292302
description='another-description',
293-
start_time=datetime.datetime(2022,2,5,4,5,6),
303+
start_time=utc.localize(datetime.datetime(2022, 2, 5, 4, 5, 6)),
294304
duration=datetime.timedelta(minutes=90),
295305
url='https://example.com/another/url',
296306
deletion_token='delete-me-too',
@@ -306,7 +316,7 @@ def test_fetch(self, mock_fetch, _):
306316
'session-1-uuid': {
307317
'room': {
308318
'id': 1,
309-
'start_time': datetime.datetime(2022,2,4,1,2,3),
319+
'start_time': utc.localize(datetime.datetime(2022,2,4,1,2,3)),
310320
'duration': datetime.timedelta(minutes=45),
311321
'description': 'some-description',
312322
},
@@ -325,7 +335,7 @@ def test_fetch(self, mock_fetch, _):
325335
id=1,
326336
public_id='session-1-uuid',
327337
description='some-description',
328-
start_time=datetime.datetime(2022,2,4,1,2,3),
338+
start_time=utc.localize(datetime.datetime(2022,2,4,1,2,3)),
329339
duration=datetime.timedelta(minutes=45),
330340
url='https://example.com/some/url',
331341
deletion_token='delete-me',
@@ -341,7 +351,7 @@ def test_create(self, mock_schedule, _):
341351
'session-1-uuid': {
342352
'room': {
343353
'id': 1,
344-
'start_time': datetime.datetime(2022,2,4,1,2,3),
354+
'start_time': utc.localize(datetime.datetime(2022,2,4,1,2,3)),
345355
'duration': datetime.timedelta(minutes=45),
346356
'description': 'some-description',
347357
},
@@ -359,7 +369,7 @@ def test_create(self, mock_schedule, _):
359369
id=1,
360370
public_id='session-1-uuid',
361371
description='some-description',
362-
start_time=datetime.datetime(2022,2,4,1,2,3),
372+
start_time=utc.localize(datetime.datetime(2022,2,4,1,2,3)),
363373
duration=datetime.timedelta(minutes=45),
364374
url='https://example.com/some/url',
365375
deletion_token='delete-me',

0 commit comments

Comments
 (0)