Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion ietf/meeting/tests_js.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from ietf.utils.test_utils import assert_ical_response_is_valid
from ietf.utils.jstest import ( IetfSeleniumTestCase, ifSeleniumEnabled, selenium_enabled,
presence_of_element_child_by_css_selector )
from ietf.utils.timezone import timezone_not_near_midnight

if selenium_enabled():
from selenium.webdriver.common.action_chains import ActionChains
Expand Down Expand Up @@ -392,7 +393,12 @@ def test_past_flags(self):
def test_past_swap_days_buttons(self):
"""Swap days buttons should be hidden for past items"""
wait = WebDriverWait(self.driver, 2)
meeting = MeetingFactory(type_id='ietf', date=datetime.datetime.today() - datetime.timedelta(days=3), days=7)
meeting = MeetingFactory(
type_id='ietf',
date=datetime.datetime.today() - datetime.timedelta(days=3),
days=7,
time_zone=timezone_not_near_midnight(),
)
room = RoomFactory(meeting=meeting)

# get current time in meeting time zone
Expand Down
41 changes: 41 additions & 0 deletions ietf/utils/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
# -*- coding: utf-8 -*-


import datetime
import io
import json
import os.path
import pytz
import shutil
import types

from mock import patch
from pyquery import PyQuery
from typing import Dict, List # pyflakes:ignore

Expand Down Expand Up @@ -39,6 +42,7 @@
from ietf.utils.test_runner import get_template_paths, set_coverage_checking
from ietf.utils.test_utils import TestCase, unicontent
from ietf.utils.text import parse_unicode
from ietf.utils.timezone import timezone_not_near_midnight
from ietf.utils.xmldraft import XMLDraft

class SendingMail(TestCase):
Expand Down Expand Up @@ -476,3 +480,40 @@ def test_manifest(self):
manifest = json.loads(unicontent(r))
self.assertTrue('name' in manifest)
self.assertTrue('theme_color' in manifest)


class TimezoneTests(TestCase):
"""Tests of the timezone utilities"""
@patch(
'ietf.utils.timezone.timezone.now',
return_value=pytz.timezone('America/Chicago').localize(datetime.datetime(2022, 7, 1, 23, 15, 0)), # 23:15:00
)
def test_timezone_not_near_midnight(self, mock):
# give it several choices that should be rejected and one that should be accepted
with patch(
'ietf.utils.timezone.pytz.common_timezones',
[
'America/Chicago', # time is 23:15, should be rejected
'America/Lima', # time is 23:15, should be rejected
'America/New_York', # time is 00:15, should be rejected
'Europe/Riga', # time is 07:15, acceptable
],
):
# check a few times (will pass by chance < 0.1% of the time)
self.assertEqual(timezone_not_near_midnight(), 'Europe/Riga')
self.assertEqual(timezone_not_near_midnight(), 'Europe/Riga')
self.assertEqual(timezone_not_near_midnight(), 'Europe/Riga')
self.assertEqual(timezone_not_near_midnight(), 'Europe/Riga')
self.assertEqual(timezone_not_near_midnight(), 'Europe/Riga')

# now give it no valid choice
with patch(
'ietf.utils.timezone.pytz.common_timezones',
[
'America/Chicago', # time is 23:15, should be rejected
'America/Lima', # time is 23:15, should be rejected
'America/New_York', # time is 00:15, should be rejected
],
):
with self.assertRaises(RuntimeError):
timezone_not_near_midnight()
23 changes: 23 additions & 0 deletions ietf/utils/timezone.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import pytz
import email.utils
import datetime
import random

from django.conf import settings
from django.utils import timezone


def local_timezone_to_utc(d):
"""Takes a naive datetime in the local timezone and returns a
Expand Down Expand Up @@ -37,3 +40,23 @@ def email_time_to_local_timezone(date_string):
def date2datetime(date, tz=pytz.utc):
return datetime.datetime(*(date.timetuple()[:6]), tzinfo=tz)


def timezone_not_near_midnight():
"""Get the name of a random timezone where it's not close to midnight

Avoids midnight +/- 1 hour. Raises RuntimeError if it is unable to find
a time zone satisfying this constraint.
"""
timezone_options = pytz.common_timezones
tzname = random.choice(timezone_options)
right_now = timezone.now().astimezone(pytz.timezone(tzname))
# Avoid the remote possibility of an infinite loop (might come up
# if there is a problem with the time zone library)
tries_left = 20
while right_now.hour < 1 or right_now.hour >= 23:
tzname = random.choice(timezone_options)
right_now = right_now.astimezone(pytz.timezone(tzname))
tries_left -= 1
if tries_left <= 0:
raise RuntimeError('Unable to find a time zone not near midnight')
return tzname