chore: use zoneinfo instead of pytz

This commit is contained in:
Tarun Tak
2025-10-27 11:32:41 +00:00
committed by Feanil Patel
parent 7111e8b18c
commit f9d65aa23f
29 changed files with 127 additions and 119 deletions

View File

@@ -1,13 +1,14 @@
"""Django admin for course_modes"""
from zoneinfo import ZoneInfo
from django import forms
from django.conf import settings
from django.contrib import admin
from django.http.request import QueryDict
from django.utils.translation import gettext_lazy as _
from opaque_keys.edx.keys import CourseKey
from pytz import UTC, timezone
from common.djangoapps.course_modes.models import CourseMode, CourseModeExpirationConfig
# Technically, we shouldn't be doing this, since verify_student is defined
@@ -73,7 +74,7 @@ class CourseModeForm(forms.ModelForm):
# However, the args copy above before the super() call handles this case.
pass
default_tz = timezone(settings.TIME_ZONE)
default_tz = ZoneInfo(settings.TIME_ZONE)
if self.instance._expiration_datetime:
# django admin is using default timezone. To avoid time conversion from db to form
@@ -81,7 +82,7 @@ class CourseModeForm(forms.ModelForm):
_expiration_datetime = self.instance._expiration_datetime.replace(
tzinfo=None
)
self.initial["_expiration_datetime"] = default_tz.localize(_expiration_datetime)
self.initial["_expiration_datetime"] = _expiration_datetime.replace(tzinfo=default_tz)
# Load the verification deadline
# Since this is stored on a model in verify student, we need to load it from there.
# We need to munge the timezone a bit to get Django admin to display it without converting
@@ -90,7 +91,7 @@ class CourseModeForm(forms.ModelForm):
if self.instance.course_id and self.instance.mode_slug in CourseMode.VERIFIED_MODES:
deadline = verification_models.VerificationDeadline.deadline_for_course(self.instance.course_id)
self.initial["verification_deadline"] = (
default_tz.localize(deadline.replace(tzinfo=None))
deadline.replace(tzinfo=default_tz)
if deadline is not None else None
)
@@ -107,14 +108,14 @@ class CourseModeForm(forms.ModelForm):
# django admin saving the date with default timezone to avoid time conversion from form to db
# changes its tzinfo to UTC
if self.cleaned_data.get("_expiration_datetime"):
return self.cleaned_data.get("_expiration_datetime").replace(tzinfo=UTC)
return self.cleaned_data.get("_expiration_datetime").replace(tzinfo=ZoneInfo("UTC"))
def clean_verification_deadline(self):
"""
Ensure that the verification deadline we save uses the UTC timezone.
"""
if self.cleaned_data.get("verification_deadline"):
return self.cleaned_data.get("verification_deadline").replace(tzinfo=UTC)
return self.cleaned_data.get("verification_deadline").replace(tzinfo=ZoneInfo("UTC"))
def clean(self):
"""

View File

@@ -7,7 +7,8 @@ from datetime import datetime, timedelta
import ddt
from django.conf import settings
from django.urls import reverse
from pytz import UTC, timezone
from pytz import timezone
from zoneinfo import ZoneInfo
from common.djangoapps.course_modes.admin import CourseModeForm
from common.djangoapps.course_modes.models import CourseMode
@@ -84,7 +85,7 @@ class AdminCourseModeFormTest(ModuleStoreTestCase):
Test the course modes Django admin form validation and saving.
"""
UPGRADE_DEADLINE = datetime.now(UTC)
UPGRADE_DEADLINE = datetime.now(ZoneInfo("UTC"))
VERIFICATION_DEADLINE = UPGRADE_DEADLINE + timedelta(days=5)
def setUp(self):

View File

@@ -5,10 +5,10 @@ Unit tests for the course_mode signals
from datetime import datetime, timedelta
from unittest.mock import patch
from zoneinfo import ZoneInfo
import ddt
from django.conf import settings
from pytz import UTC
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.course_modes.signals import _listen_for_course_publish
@@ -26,7 +26,7 @@ class CourseModeSignalTest(ModuleStoreTestCase):
def setUp(self):
super().setUp()
self.end = datetime.now(tz=UTC).replace(microsecond=0) + timedelta(days=7)
self.end = datetime.now(tz=ZoneInfo("UTC")).replace(microsecond=0) + timedelta(days=7)
self.course = CourseFactory.create(end=self.end)
CourseMode.objects.all().delete()

View File

@@ -6,11 +6,11 @@ import decimal
from datetime import datetime, timedelta
from unittest.mock import patch
from urllib.parse import urljoin
from zoneinfo import ZoneInfo
import ddt
import freezegun
import httpretty
import pytz
from django.conf import settings
from django.test import override_settings
from django.urls import reverse
@@ -50,7 +50,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest
@patch.dict(settings.FEATURES, {'MODE_CREATION_FOR_TESTING': True})
def setUp(self):
super().setUp()
now = datetime.now(pytz.utc)
now = datetime.now(ZoneInfo("UTC"))
day = timedelta(days=1)
tomorrow = now + day
yesterday = now - day

View File

@@ -6,12 +6,12 @@ import logging
import uuid
from datetime import datetime, timedelta
from unittest.mock import patch
from zoneinfo import ZoneInfo
from django.conf import settings
from django.urls import reverse
from django.utils.timezone import now
from opaque_keys.edx.locator import CourseKey
from pytz import UTC
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
@@ -1023,7 +1023,7 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase):
mock_get_course_runs.return_value = self.return_values
# Setup enrollment period to be in the past
utc_now = datetime.now(UTC)
utc_now = datetime.now(ZoneInfo("UTC"))
self.course.start = utc_now - timedelta(days=15)
self.course.end = utc_now - timedelta(days=1)
self.course = self.update_course(self.course, self.user.id)

View File

@@ -5,9 +5,9 @@ Test entitlements tasks
from datetime import datetime, timedelta
from unittest import mock
from zoneinfo import ZoneInfo
import pytest
import pytz
from django.test import TestCase
from common.djangoapps.entitlements import tasks
@@ -19,7 +19,7 @@ from openedx.core.djangolib.testing.utils import skip_unless_lms
def make_entitlement(expired=False): # lint-amnesty, pylint: disable=missing-function-docstring
age = CourseEntitlementPolicy.DEFAULT_EXPIRATION_PERIOD_DAYS
past_datetime = datetime.now(tz=pytz.UTC) - timedelta(days=age)
past_datetime = datetime.now(tz=ZoneInfo("UTC")) - timedelta(days=age)
expired_at = past_datetime if expired else None
entitlement = CourseEntitlementFactory.create(created=past_datetime, expired_at=expired_at)
return entitlement

View File

@@ -5,10 +5,10 @@ import json
import random
import sys
from textwrap import dedent
from zoneinfo import ZoneInfo
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.core.management.base import BaseCommand
from pytz import UTC
from common.djangoapps.student.models import UserTestGroup
@@ -75,7 +75,7 @@ class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docst
utg = UserTestGroup()
utg.name = group
utg.description = json.dumps({"description": options['description']}, # lint-amnesty, pylint: disable=too-many-function-args
{"time": datetime.datetime.now(UTC).isoformat()})
{"time": datetime.datetime.now(ZoneInfo("UTC")).isoformat()})
group_objects[group] = utg
group_objects[group].save()

View File

@@ -5,6 +5,7 @@ import uuid # lint-amnesty, pylint: disable=wrong-import-order
from collections import defaultdict, namedtuple # lint-amnesty, pylint: disable=wrong-import-order
from datetime import date, datetime, timedelta # lint-amnesty, pylint: disable=wrong-import-order
from urllib.parse import urljoin
from zoneinfo import ZoneInfo
from config_models.models import ConfigurationModel
from django.conf import settings
@@ -29,7 +30,6 @@ from openedx_events.learning.signals import (
COURSE_UNENROLLMENT_COMPLETED,
)
from openedx_filters.learning.filters import CourseEnrollmentStarted, CourseUnenrollmentStarted
from pytz import UTC
from requests.exceptions import HTTPError, RequestException
from simple_history.models import HistoricalRecords
@@ -152,7 +152,7 @@ class CourseEnrollmentQuerySet(models.QuerySet):
"""
return self.filter(course_id__in=self.get_user_course_ids_with_certificates(username))
def in_progress(self, username, time_zone=UTC):
def in_progress(self, username, time_zone=ZoneInfo("UTC")):
"""
Returns a queryset of CourseEnrollment objects for courses that are currently in progress.
"""
@@ -170,7 +170,7 @@ class CourseEnrollmentQuerySet(models.QuerySet):
"""
return self.active().with_certificates(username)
def expired(self, username, time_zone=UTC):
def expired(self, username, time_zone=ZoneInfo("UTC")):
"""
Returns a queryset of CourseEnrollment objects for courses that have expired.
"""
@@ -1087,7 +1087,7 @@ class CourseEnrollment(models.Model):
if refund_cutoff_date is None:
log.info("Refund cutoff date is null")
return False
if datetime.now(UTC) > refund_cutoff_date:
if datetime.now(ZoneInfo("UTC")) > refund_cutoff_date:
log.info(f"Refund cutoff date: {refund_cutoff_date} has passed")
return False
@@ -1133,7 +1133,10 @@ class CourseEnrollment(models.Model):
self.course_overview.start.replace(tzinfo=None)
)
return refund_window_start_date.replace(tzinfo=UTC) + EnrollmentRefundConfiguration.current().refund_window
return (
refund_window_start_date.replace(tzinfo=ZoneInfo("UTC"))
+ EnrollmentRefundConfiguration.current().refund_window
)
def is_order_voucher_refundable(self):
""" Checks if the coupon batch expiration date has passed to determine whether order voucher is refundable. """
@@ -1142,8 +1145,11 @@ class CourseEnrollment(models.Model):
if not vouchers:
return False
voucher_end_datetime_str = vouchers[0]['end_datetime']
voucher_expiration_date = datetime.strptime(voucher_end_datetime_str, ECOMMERCE_DATE_FORMAT).replace(tzinfo=UTC)
return datetime.now(UTC) < voucher_expiration_date
voucher_expiration_date = (
datetime.strptime(voucher_end_datetime_str, ECOMMERCE_DATE_FORMAT)
.replace(tzinfo=ZoneInfo("UTC"))
)
return datetime.now(ZoneInfo("UTC")) < voucher_expiration_date
def get_order_attribute_from_ecommerce(self, attribute_name):
"""
@@ -1265,7 +1271,7 @@ class CourseEnrollment(models.Model):
if self.dynamic_upgrade_deadline is not None:
# When course modes expire they aren't found any more and None would be returned.
# Replicate that behavior here by returning None if the personalized deadline is in the past.
if self.dynamic_upgrade_deadline <= datetime.now(UTC):
if self.dynamic_upgrade_deadline <= datetime.now(ZoneInfo("UTC")):
log.debug('Schedules: Returning None since dynamic upgrade deadline has already passed.')
return None

View File

@@ -19,6 +19,7 @@ from datetime import datetime, timedelta
from functools import total_ordering
from importlib import import_module
from urllib.parse import urlencode
from zoneinfo import ZoneInfo
import crum
from config_models.models import ConfigurationModel
@@ -456,7 +457,7 @@ class UserProfile(models.Model):
location = models.CharField(blank=True, max_length=255, db_index=True)
# Optional demographic data we started capturing from Fall 2012
this_year = datetime.now(UTC).year
this_year = datetime.now(ZoneInfo("UTC")).year
VALID_YEARS = list(range(this_year, this_year - 120, -1))
year_of_birth = models.IntegerField(blank=True, null=True, db_index=True)
GENDER_CHOICES = (
@@ -572,7 +573,7 @@ class UserProfile(models.Model):
def age(self):
""" Convenience method that returns the age given a year_of_birth. """
year_of_birth = self.year_of_birth
year = datetime.now(UTC).year
year = datetime.now(ZoneInfo("UTC")).year
if year_of_birth is not None:
return self._calculate_age(year, year_of_birth)
@@ -798,7 +799,7 @@ def user_post_save_callback(sender, **kwargs):
'username': user.username,
'name': profile.name,
'age': profile.age or -1,
'yearOfBirth': profile.year_of_birth or datetime.now(UTC).year,
'yearOfBirth': profile.year_of_birth or datetime.now(ZoneInfo("UTC")).year,
'education': profile.level_of_education_display,
'address': profile.mailing_address,
'gender': profile.gender_display,
@@ -982,7 +983,7 @@ class LoginFailures(models.Model):
if not record.lockout_until:
return False
now = datetime.now(UTC)
now = datetime.now(ZoneInfo("UTC"))
until = record.lockout_until
is_locked_out = until and now < until
@@ -1003,7 +1004,7 @@ class LoginFailures(models.Model):
if record.failure_count >= max_failures_allowed:
# yes, then store when this account is locked out until
lockout_period_secs = settings.MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS
record.lockout_until = datetime.now(UTC) + timedelta(seconds=lockout_period_secs)
record.lockout_until = datetime.now(ZoneInfo("UTC")) + timedelta(seconds=lockout_period_secs)
record.save()

View File

@@ -3,8 +3,8 @@ Provides Python APIs exposed from Student models.
"""
import datetime
import logging
from zoneinfo import ZoneInfo
from pytz import UTC
from common.djangoapps.student.models import CourseAccessRole as _CourseAccessRole
from common.djangoapps.student.models import CourseEnrollment as _CourseEnrollment
@@ -158,7 +158,7 @@ def confirm_name_change(user, pending_name_change):
if 'old_names' not in meta:
meta['old_names'] = []
meta['old_names'].append(
[user_profile.name, pending_name_change.rationale, datetime.datetime.now(UTC).isoformat()]
[user_profile.name, pending_name_change.rationale, datetime.datetime.now(ZoneInfo("UTC")).isoformat()]
)
user_profile.set_meta(meta)

View File

@@ -3,6 +3,7 @@
from datetime import datetime
from uuid import uuid4
from zoneinfo import ZoneInfo
import factory
from django.contrib.auth.models import AnonymousUser, Group, Permission
@@ -10,7 +11,6 @@ from django.contrib.contenttypes.models import ContentType
from django.test.client import RequestFactory
from factory.django import DjangoModelFactory
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
from common.djangoapps.student.models import (
AccountRecovery,
@@ -91,8 +91,8 @@ class UserFactory(DjangoModelFactory): # lint-amnesty, pylint: disable=missing-
is_staff = False
is_active = True
is_superuser = False
last_login = datetime(2012, 1, 1, tzinfo=UTC)
date_joined = datetime(2011, 1, 1, tzinfo=UTC)
last_login = datetime(2012, 1, 1, tzinfo=ZoneInfo("UTC"))
date_joined = datetime(2011, 1, 1, tzinfo=ZoneInfo("UTC"))
@factory.post_generation
def profile(obj, create, extracted, **kwargs): # pylint: disable=unused-argument, missing-function-docstring

View File

@@ -6,6 +6,7 @@ Tests student admin.py
import datetime
import json
from unittest.mock import Mock
from zoneinfo import ZoneInfo
import ddt
import pytest
@@ -17,7 +18,6 @@ from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils.timezone import now
from edx_toggles.toggles.testutils import override_waffle_switch
from pytz import UTC
from common.djangoapps.student.admin import ( # lint-amnesty, pylint: disable=line-too-long
COURSE_ENROLLMENT_ADMIN_SWITCH,
@@ -335,7 +335,7 @@ class LoginFailuresAdminTest(TestCase):
super().setUp()
self.client.login(username=self.user.username, password=self.TEST_PASSWORD)
self.user2 = UserFactory.create(username='Zażółć gęślą jaźń')
self.user_lockout_until = datetime.datetime.now(UTC)
self.user_lockout_until = datetime.datetime.now(ZoneInfo("UTC"))
LoginFailures.objects.create(user=self.user, failure_count=10, lockout_until=self.user_lockout_until)
LoginFailures.objects.create(user=self.user2, failure_count=2)

View File

@@ -2,12 +2,12 @@
import datetime
from unittest.mock import patch
from zoneinfo import ZoneInfo
import ddt
from django.conf import settings
from django.test.utils import override_settings
from django.urls import reverse
from pytz import UTC
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
@@ -22,8 +22,8 @@ from openedx.core.djangoapps.site_configuration.tests.test_util import with_site
# pylint: disable=no-member
PAST_DATE = datetime.datetime.now(UTC) - datetime.timedelta(days=2)
FUTURE_DATE = datetime.datetime.now(UTC) + datetime.timedelta(days=2)
PAST_DATE = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=2)
FUTURE_DATE = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=2)
class CertificateDisplayTestBase(SharedModuleStoreTestCase):
@@ -92,7 +92,7 @@ class CertificateDashboardMessageDisplayTest(CertificateDisplayTestBase):
def _check_message(self, visible_date): # lint-amnesty, pylint: disable=missing-function-docstring
response = self.client.get(reverse('dashboard'))
is_past = visible_date < datetime.datetime.now(UTC)
is_past = visible_date < datetime.datetime.now(ZoneInfo("UTC"))
if is_past:
test_message = 'Your grade and certificate will be ready after'

View File

@@ -4,9 +4,9 @@ Tests for credit courses on the student dashboard.
import datetime
from unittest.mock import patch
from zoneinfo import ZoneInfo
import ddt
import pytz
from django.conf import settings
from django.test.utils import override_settings
from django.urls import reverse
@@ -101,7 +101,7 @@ class CreditCourseDashboardTest(ModuleStoreTestCase):
# Move the eligibility deadline so it's within 30 days
eligibility = CreditEligibility.objects.get(username=self.USERNAME)
eligibility.deadline = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=29)
eligibility.deadline = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=29)
eligibility.save()
# The user should still have the option to purchase credit,

View File

@@ -3,9 +3,9 @@ import datetime
import hashlib
from unittest import mock
from unittest.mock import MagicMock
from zoneinfo import ZoneInfo
import ddt
import pytz
from crum import set_current_request
from django.contrib.auth.models import AnonymousUser, User # lint-amnesty, pylint: disable=imported-auth-user
from django.core.cache import cache
@@ -15,7 +15,6 @@ from django.test import TestCase, override_settings
from edx_toggles.toggles.testutils import override_waffle_flag
from freezegun import freeze_time
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
@@ -150,7 +149,7 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
course_id=course.id,
mode_slug=CourseMode.VERIFIED,
# This must be in the future to ensure it is returned by downstream code.
expiration_datetime=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
expiration_datetime=datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=1)
)
enrollment = CourseEnrollmentFactory(course_id=course.id, mode=CourseMode.AUDIT)
Schedule.objects.all().delete()
@@ -164,7 +163,7 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
course_id=course.id,
mode_slug=CourseMode.VERIFIED,
# This must be in the future to ensure it is returned by downstream code.
expiration_datetime=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=30),
expiration_datetime=datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=30),
)
course_overview = CourseOverview.load_from_module_store(course.id)
CourseEnrollmentFactory(
@@ -172,7 +171,7 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
mode=CourseMode.AUDIT,
course=course_overview,
)
Schedule.objects.update(upgrade_deadline=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=5))
Schedule.objects.update(upgrade_deadline=datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=5))
enrollment = CourseEnrollment.objects.first()
# The schedule's upgrade deadline should be used if a schedule exists
@@ -189,7 +188,7 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
@skip_unless_lms
def test_upgrade_deadline_instructor_paced(self):
course = CourseFactory(self_paced=False)
course_upgrade_deadline = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
course_upgrade_deadline = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=1)
CourseModeFactory(
course_id=course.id,
mode_slug=CourseMode.VERIFIED,
@@ -226,7 +225,7 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
course_id=course.id,
mode_slug=CourseMode.VERIFIED,
# This must be in the future to ensure it is returned by downstream code.
expiration_datetime=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=30),
expiration_datetime=datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=30),
)
# Create a CourseOverview with an outdated version
@@ -280,7 +279,7 @@ class UserCelebrationTests(SharedModuleStoreTestCase):
def test_first_check_streak_celebration(self):
STREAK_LENGTH_TO_CELEBRATE = UserCelebration.perform_streak_updates(self.user, self.course_key)
today = datetime.datetime.now(UTC).date()
today = datetime.datetime.now(ZoneInfo("UTC")).date()
assert self.user.celebration.streak_length == 1
assert self.user.celebration.last_day_of_streak == today
assert STREAK_LENGTH_TO_CELEBRATE is None
@@ -300,7 +299,7 @@ class UserCelebrationTests(SharedModuleStoreTestCase):
| 2/9/21 | 6 | 2/9/21 | None | Day 6 of Streak |
+---------+---------------------+--------------------+-------------------------+------------------+------------------+
"""
now = datetime.datetime.now(UTC)
now = datetime.datetime.now(ZoneInfo("UTC"))
for i in range(1, (self.STREAK_LENGTH_TO_CELEBRATE * 2) + 1):
with freeze_time(now + datetime.timedelta(days=i)):
STREAK_LENGTH_TO_CELEBRATE = UserCelebration.perform_streak_updates(self.user, self.course_key)
@@ -321,7 +320,7 @@ class UserCelebrationTests(SharedModuleStoreTestCase):
| 2/9/21 | 6 | 2/9/21 | None | longest_streak_ever is 6 |
+---------+---------------------+--------------------+-------------------------+------------------+---------------------+
"""
now = datetime.datetime.now(UTC)
now = datetime.datetime.now(ZoneInfo("UTC"))
for i in range(1, (self.STREAK_LENGTH_TO_CELEBRATE * 2) + 1):
with freeze_time(now + datetime.timedelta(days=i)):
UserCelebration.perform_streak_updates(self.user, self.course_key)
@@ -342,7 +341,7 @@ class UserCelebrationTests(SharedModuleStoreTestCase):
| 2/6/21 | 3 | 2/6/21 | None | Already celebrated this streak. |
+---------+---------------------+--------------------+-------------------------+------------------+----------------------------+
"""
now = datetime.datetime.now(UTC)
now = datetime.datetime.now(ZoneInfo("UTC"))
for i in range(1, self.STREAK_LENGTH_TO_CELEBRATE + 1):
with freeze_time(now + datetime.timedelta(days=i)):
streak_length_to_celebrate = UserCelebration.perform_streak_updates(self.user, self.course_key)
@@ -382,7 +381,7 @@ class UserCelebrationTests(SharedModuleStoreTestCase):
| 2/10/21 | 3 | 2/10/21 | 3 | Completed 3 Day Streak so we should celebrate |
+---------+---------------------+--------------------+-------------------------+------------------+-----------------------------------------------+
"""
now = datetime.datetime.now(UTC)
now = datetime.datetime.now(ZoneInfo("UTC"))
for i in range(1, self.STREAK_LENGTH_TO_CELEBRATE + self.STREAK_BREAK_LENGTH + self.STREAK_LENGTH_TO_CELEBRATE + 1):
with freeze_time(now + datetime.timedelta(days=i)):
if self.STREAK_LENGTH_TO_CELEBRATE < i <= self.STREAK_LENGTH_TO_CELEBRATE + self.STREAK_BREAK_LENGTH:
@@ -413,7 +412,7 @@ class UserCelebrationTests(SharedModuleStoreTestCase):
| 2/12/21 | 1 | 2/12/21 | None | Day 2 of streak was missed, so streak resets |
+---------+---------------------+--------------------+-------------------------+------------------+-----------------------------------------------+
"""
now = datetime.datetime.now(UTC)
now = datetime.datetime.now(ZoneInfo("UTC"))
for i in range(1, self.STREAK_LENGTH_TO_CELEBRATE * 3 + 1, 2):
with freeze_time(now + datetime.timedelta(days=i)):
streak_length_to_celebrate = UserCelebration.perform_streak_updates(self.user, self.course_key)
@@ -440,7 +439,7 @@ class UserCelebrationTests(SharedModuleStoreTestCase):
+---------+---------------------+--------------------+-------------------------+------------------+
"""
UserCelebration.STREAK_BREAK_LENGTH = 2
now = datetime.datetime.now(UTC)
now = datetime.datetime.now(ZoneInfo("UTC"))
for i in range(1, self.STREAK_LENGTH_TO_CELEBRATE * 3 + 1, 2):
with freeze_time(now + datetime.timedelta(days=i)):
streak_length_to_celebrate = UserCelebration.perform_streak_updates(self.user, self.course_key)
@@ -831,7 +830,7 @@ class TestUserPostSaveCallback(SharedModuleStoreTestCase):
return CourseEnrollment.get_enrollment(student, self.course.id)
# Set enrollment end date to a past date so that enrollment is ended
enrollment_end = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=2)
enrollment_end = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=2)
course_overview = CourseOverviewFactory.create(id=self.course.id, enrollment_end=enrollment_end)
course_overview.save()

View File

@@ -3,12 +3,12 @@ Tests for the recently enrolled messaging within the Dashboard.
"""
import datetime
from zoneinfo import ZoneInfo
import ddt
from django.urls import reverse
from django.utils.timezone import now
from opaque_keys.edx import locator
from pytz import UTC
from common.test.utils import XssTestMixin
from common.djangoapps.student.models import CourseEnrollment, DashboardConfiguration
@@ -40,7 +40,7 @@ class TestRecentEnrollments(ModuleStoreTestCase, XssTestMixin):
# Old Course
old_course_location = locator.CourseLocator('Org0', 'Course0', 'Run0')
__, enrollment = self._create_course_and_enrollment(old_course_location)
enrollment.created = datetime.datetime(1900, 12, 31, 0, 0, 0, 0, tzinfo=UTC)
enrollment.created = datetime.datetime(1900, 12, 31, 0, 0, 0, 0, tzinfo=ZoneInfo("UTC"))
enrollment.save()
# New Course

View File

@@ -6,10 +6,10 @@ import json
import logging
from datetime import datetime, timedelta
from unittest.mock import patch
from zoneinfo import ZoneInfo
import ddt
import httpretty
import pytz
# Explicitly import the cache from ConfigurationModel so we can reset it after each test
from config_models.models import cache
from django.test.client import Client
@@ -56,7 +56,7 @@ class RefundableTest(SharedModuleStoreTestCase):
course_id=self.course.id,
mode_slug='verified',
mode_display_name='Verified',
expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=1)
expiration_datetime=datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
)
self.enrollment = CourseEnrollment.enroll(self.user, self.course.id, mode='verified')
@@ -67,14 +67,14 @@ class RefundableTest(SharedModuleStoreTestCase):
@patch('common.djangoapps.student.models.course_enrollment.CourseEnrollment.refund_cutoff_date')
def test_refundable(self, cutoff_date):
""" Assert base case is refundable"""
cutoff_date.return_value = datetime.now(pytz.UTC) + timedelta(days=1)
cutoff_date.return_value = datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
assert self.enrollment.refundable()
@patch('common.djangoapps.student.models.course_enrollment.CourseEnrollment.refund_cutoff_date')
def test_refundable_expired_verification(self, cutoff_date):
""" Assert that enrollment is refundable if course mode has expired."""
cutoff_date.return_value = datetime.now(pytz.UTC) + timedelta(days=1)
self.verified_mode.expiration_datetime = datetime.now(pytz.UTC) - timedelta(days=1)
cutoff_date.return_value = datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
self.verified_mode.expiration_datetime = datetime.now(ZoneInfo("UTC")) - timedelta(days=1)
self.verified_mode.save()
assert self.enrollment.refundable()
@@ -82,7 +82,7 @@ class RefundableTest(SharedModuleStoreTestCase):
def test_refundable_when_certificate_exists(self, cutoff_date):
""" Assert that enrollment is not refundable once a certificat has been generated."""
cutoff_date.return_value = datetime.now(pytz.UTC) + timedelta(days=1)
cutoff_date.return_value = datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
assert self.enrollment.refundable()
@@ -110,13 +110,13 @@ class RefundableTest(SharedModuleStoreTestCase):
@patch('common.djangoapps.student.models.course_enrollment.CourseEnrollment.refund_cutoff_date')
def test_refundable_with_cutoff_date(self, cutoff_date):
""" Assert enrollment is refundable before cutoff and not refundable after."""
cutoff_date.return_value = datetime.now(pytz.UTC) + timedelta(days=1)
cutoff_date.return_value = datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
assert self.enrollment.refundable()
cutoff_date.return_value = datetime.now(pytz.UTC) - timedelta(minutes=5)
cutoff_date.return_value = datetime.now(ZoneInfo("UTC")) - timedelta(minutes=5)
assert not self.enrollment.refundable()
cutoff_date.return_value = datetime.now(pytz.UTC) + timedelta(minutes=5)
cutoff_date.return_value = datetime.now(ZoneInfo("UTC")) + timedelta(minutes=5)
assert self.enrollment.refundable()
@ddt.data(
@@ -132,7 +132,7 @@ class RefundableTest(SharedModuleStoreTestCase):
"""
Assert that the later date is used with the configurable refund period in calculating the returned cutoff date.
"""
now = datetime.now(pytz.UTC).replace(microsecond=0)
now = datetime.now(ZoneInfo("UTC")).replace(microsecond=0)
order_date = now + order_date_delta
course_start = now + course_start_delta
expected_date = now + expected_date_delta
@@ -170,9 +170,9 @@ class RefundableTest(SharedModuleStoreTestCase):
assert expected_date_placed_attr in CourseEnrollmentAttribute.get_enrollment_attributes(self.enrollment)
@ddt.data(
(datetime.now(pytz.UTC) + timedelta(days=1), True),
(datetime.now(pytz.UTC) - timedelta(days=1), False),
(datetime.now(pytz.UTC) - timedelta(minutes=5), False),
(datetime.now(ZoneInfo("UTC")) + timedelta(days=1), True),
(datetime.now(ZoneInfo("UTC")) - timedelta(days=1), False),
(datetime.now(ZoneInfo("UTC")) - timedelta(minutes=5), False),
)
@ddt.unpack
@httpretty.activate
@@ -260,7 +260,7 @@ class RefundableTest(SharedModuleStoreTestCase):
Assert that the refund_cutoff_date returns order placement date if order:date_placed
attribute exist without calling ecommerce.
"""
now = datetime.now(pytz.UTC).replace(microsecond=0)
now = datetime.now(ZoneInfo("UTC")).replace(microsecond=0)
order_date = now + timedelta(days=2)
course_start = now + timedelta(days=1)
@@ -280,7 +280,7 @@ class RefundableTest(SharedModuleStoreTestCase):
@override_settings(ECOMMERCE_API_URL=TEST_API_URL)
def test_multiple_refunds_dashbaord_page_error(self):
""" Order with mutiple refunds will not throw 500 error when dashboard page will access."""
now = datetime.now(pytz.UTC).replace(microsecond=0)
now = datetime.now(ZoneInfo("UTC")).replace(microsecond=0)
order_date = now + timedelta(days=1)
expected_content = f'{{"date_placed": "{order_date.strftime(ECOMMERCE_DATE_FORMAT)}"}}'

View File

@@ -8,9 +8,9 @@ import json
import unittest
from datetime import datetime, timedelta # lint-amnesty, pylint: disable=unused-import
from unittest.mock import patch
from zoneinfo import ZoneInfo
import ddt
import pytz
from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing
from django.conf import settings
from django.test.utils import override_settings
@@ -948,7 +948,7 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin,
course_id=course.id,
mode_slug='verified',
mode_display_name='Verified',
expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=1),
expiration_datetime=datetime.now(ZoneInfo("UTC")) + timedelta(days=1),
sku=sku
)

View File

@@ -6,9 +6,9 @@ import logging
from datetime import datetime, timedelta
from unittest.mock import Mock, patch
from urllib.parse import quote
from zoneinfo import ZoneInfo
import ddt
import pytz
from config_models.models import cache
from django.conf import settings
from django.contrib.auth.models import AnonymousUser, User # lint-amnesty, pylint: disable=imported-auth-user
@@ -81,7 +81,7 @@ class CourseEndingTest(ModuleStoreTestCase):
course = CourseOverviewFactory.create(
end_of_course_survey_url=survey_url,
certificates_display_behavior=CertificatesDisplayBehaviors.END,
end=datetime.now(pytz.UTC) - timedelta(days=2)
end=datetime.now(ZoneInfo("UTC")) - timedelta(days=2)
)
cert = GeneratedCertificateFactory.create(
user=user,
@@ -287,7 +287,7 @@ class CourseEndingTest(ModuleStoreTestCase):
course = CourseOverviewFactory.create(
end_of_course_survey_url=survey_url,
certificates_display_behavior=CertificatesDisplayBehaviors.END,
end=datetime.now(pytz.UTC) - timedelta(days=2),
end=datetime.now(ZoneInfo("UTC")) - timedelta(days=2),
)
enrollment = CourseEnrollmentFactory(user=user, course_id=course.id, mode=CourseMode.VERIFIED)
@@ -314,7 +314,7 @@ class CourseEndingTest(ModuleStoreTestCase):
course = CourseOverviewFactory.create(
end_of_course_survey_url=survey_url,
certificates_display_behavior=CertificatesDisplayBehaviors.END,
end=datetime.now(pytz.UTC) - timedelta(days=2),
end=datetime.now(ZoneInfo("UTC")) - timedelta(days=2),
)
cert_status = {'status': 'generating', 'mode': 'honor', 'uuid': None}
enrollment = CourseEnrollmentFactory(user=user, course_id=course.id, mode=CourseMode.VERIFIED)
@@ -412,14 +412,14 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
course_id=self.course.id,
mode_slug='verified',
mode_display_name='Verified',
expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=1)
expiration_datetime=datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
)
enrollment = CourseEnrollment.enroll(self.user, self.course.id)
course_mode_info = complete_course_mode_info(self.course.id, enrollment)
assert course_mode_info['show_upsell']
assert course_mode_info['days_for_upsell'] == 1
verified_mode.expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=-1)
verified_mode.expiration_datetime = datetime.now(ZoneInfo("UTC")) + timedelta(days=-1)
verified_mode.save()
course_mode_info = complete_course_mode_info(self.course.id, enrollment)
assert not course_mode_info['show_upsell']
@@ -434,13 +434,13 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
course_id=self.course.id,
mode_slug='verified',
mode_display_name='verified',
expiration_datetime=datetime.now(pytz.UTC) - timedelta(days=1)
expiration_datetime=datetime.now(ZoneInfo("UTC")) - timedelta(days=1)
)
CourseEnrollment.enroll(self.user, self.course.id, mode='honor')
self.course.start = datetime.now(pytz.UTC) - timedelta(days=2)
self.course.end = datetime.now(pytz.UTC) - timedelta(days=1)
self.course.start = datetime.now(ZoneInfo("UTC")) - timedelta(days=2)
self.course.end = datetime.now(ZoneInfo("UTC")) - timedelta(days=1)
self.course.display_name = "Omega"
self.course = self.update_course(self.course, self.user.id)
@@ -482,12 +482,12 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
course_id=self.course.id,
mode_slug='verified',
mode_display_name='verified',
expiration_datetime=datetime.now(pytz.UTC) - timedelta(days=1)
expiration_datetime=datetime.now(ZoneInfo("UTC")) - timedelta(days=1)
)
CourseEnrollment.enroll(self.user, self.course.id, mode='honor')
self.course.certificate_available_date = datetime.now(pytz.UTC) - timedelta(days=1)
self.course.start = datetime.now(pytz.UTC) - timedelta(days=2)
self.course.end = datetime.now(pytz.UTC) - timedelta(days=1)
self.course.certificate_available_date = datetime.now(ZoneInfo("UTC")) - timedelta(days=1)
self.course.start = datetime.now(ZoneInfo("UTC")) - timedelta(days=2)
self.course.end = datetime.now(ZoneInfo("UTC")) - timedelta(days=1)
self.course.display_name = 'Omega'
self.course.course_organization = 'Omega Org'
self.course = self.update_course(self.course, self.user.id)
@@ -593,7 +593,7 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
course_id=self.course.id,
mode_slug='verified',
mode_display_name='Verified',
expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=1)
expiration_datetime=datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
)
enrollment = CourseEnrollment.enroll(self.user, self.course.id, mode=enrollment_mode)
return complete_course_mode_info(self.course.id, enrollment)

View File

@@ -6,6 +6,7 @@ Dashboard view and supporting methods
import datetime
import logging
from collections import defaultdict
from zoneinfo import ZoneInfo
from django.conf import settings
from django.contrib import messages
@@ -20,7 +21,6 @@ from edx_django_utils.plugins import get_plugins_view_context
from edx_toggles.toggles import WaffleFlag
from opaque_keys.edx.keys import CourseKey
from openedx_filters.learning.filters import DashboardRenderStarted
from pytz import UTC
from edx_django_utils.plugins import pluggable_override
from lms.djangoapps.bulk_email.api import is_bulk_email_feature_enabled
@@ -108,7 +108,7 @@ def _get_recently_enrolled_courses(course_enrollments):
list[CourseEnrollment]: A list of recent course enrollments.
"""
seconds = DashboardConfiguration.current().recent_enrollment_time_delta
time_delta = (datetime.datetime.now(UTC) - datetime.timedelta(seconds=seconds))
time_delta = (datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(seconds=seconds))
return [
enrollment for enrollment in course_enrollments
# If the enrollment has no created date, we are explicitly excluding the course
@@ -270,7 +270,7 @@ def complete_course_mode_info(course_id, enrollment, modes=None):
mode_info['verified_bulk_sku'] = modes['verified'].bulk_sku
# if there is an expiration date, find out how long from now it is
if modes['verified'].expiration_datetime:
today = datetime.datetime.now(UTC).date()
today = datetime.datetime.now(ZoneInfo("UTC")).date()
mode_info['days_for_upsell'] = (modes['verified'].expiration_datetime.date() - today).days
mode_info['expiration_datetime'] = modes['verified'].expiration_datetime.date()

View File

@@ -9,6 +9,7 @@ import urllib.parse
import uuid
from collections import namedtuple
import re
from zoneinfo import ZoneInfo
from django.conf import settings
from django.contrib import messages
@@ -35,7 +36,6 @@ from eventtracking import tracker
# Note that this lives in LMS, so this dependency should be refactored.
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import IsAuthenticated
@@ -539,7 +539,7 @@ def disable_account_ajax(request):
context['message'] = _("Unexpected account status")
return JsonResponse(context, status=400)
user_account.changed_by = request.user
user_account.standing_last_changed_at = datetime.datetime.now(UTC)
user_account.standing_last_changed_at = datetime.datetime.now(ZoneInfo("UTC"))
user_account.save()
return JsonResponse(context)
@@ -921,7 +921,7 @@ def confirm_email_change(request, key):
meta = u_prof.get_meta()
if 'old_emails' not in meta:
meta['old_emails'] = []
meta['old_emails'].append([user.email, datetime.datetime.now(UTC).isoformat()])
meta['old_emails'].append([user.email, datetime.datetime.now(ZoneInfo("UTC")).isoformat()])
u_prof.set_meta(meta)
u_prof.save()
# Send it to the old email...

View File

@@ -3,8 +3,8 @@ import copy
from datetime import datetime # lint-amnesty, pylint: disable=wrong-import-order
from unittest import mock
from uuid import uuid4 # lint-amnesty, pylint: disable=wrong-import-order
from zoneinfo import ZoneInfo
import pytz
from django.contrib.sites.models import Site
from django.urls import reverse
from django.utils.http import urlencode
@@ -33,7 +33,7 @@ SINGLE_PROVIDER_DATA = {
'entity_id': 'http://entity-id-1',
'sso_url': 'http://test.url',
'public_key': 'a-key0Aid98',
'fetched_at': datetime.now(pytz.UTC).replace(microsecond=0)
'fetched_at': datetime.now(ZoneInfo("UTC")).replace(microsecond=0)
}
SINGLE_PROVIDER_DATA_2 = copy.copy(SINGLE_PROVIDER_DATA)

View File

@@ -3,10 +3,10 @@
import datetime
from unittest import mock
from zoneinfo import ZoneInfo
import ddt
import pytest
import pytz
from django import test
from django.contrib.auth import models, REDIRECT_FIELD_NAME
from django.core import mail
@@ -562,7 +562,7 @@ class SetIDVerificationStatusTestCase(TestCase):
)
with mock.patch('common.djangoapps.third_party_auth.pipeline.earliest_allowed_verification_date') as earliest_date: # lint-amnesty, pylint: disable=line-too-long
earliest_date.return_value = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
earliest_date.return_value = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=1)
# Begin the pipeline.
pipeline.set_id_verification_status(
auth_entry=pipeline.AUTH_ENTRY_LOGIN,

View File

@@ -5,9 +5,9 @@ Utility functions for third_party_auth
import datetime
import logging
from uuid import UUID
from zoneinfo import ZoneInfo
import dateutil.parser
import pytz
import requests
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.utils.timezone import now
@@ -93,7 +93,7 @@ def parse_metadata_xml(xml, entity_id):
expires_at = dateutil.parser.parse(xml.attrib["validUntil"])
if "cacheDuration" in xml.attrib:
cache_expires = OneLogin_Saml2_Utils.parse_duration(xml.attrib["cacheDuration"])
cache_expires = datetime.datetime.fromtimestamp(cache_expires, tz=pytz.utc)
cache_expires = datetime.datetime.fromtimestamp(cache_expires, tz=ZoneInfo("UTC"))
if expires_at is None or cache_expires < expires_at:
expires_at = cache_expires

View File

@@ -2,15 +2,15 @@
from datetime import datetime
from zoneinfo import ZoneInfo
from django.test import TestCase
from django.test.utils import override_settings
from eventtracking import tracker
from eventtracking.django import DjangoTracker
from freezegun import freeze_time
from pytz import UTC
FROZEN_TIME = datetime(2013, 10, 3, 8, 24, 55, tzinfo=UTC)
FROZEN_TIME = datetime(2013, 10, 3, 8, 24, 55, tzinfo=ZoneInfo("UTC"))
IN_MEMORY_BACKEND_CONFIG = {
'mem': {
'ENGINE': 'common.djangoapps.track.tests.InMemoryBackend'

View File

@@ -2,9 +2,9 @@
import json
from datetime import datetime
from zoneinfo import ZoneInfo
from django.test import TestCase
from pytz import UTC
from common.djangoapps.track.utils import DateTimeJSONEncoder
@@ -12,7 +12,7 @@ from common.djangoapps.track.utils import DateTimeJSONEncoder
class TestDateTimeJSONEncoder(TestCase): # lint-amnesty, pylint: disable=missing-class-docstring
def test_datetime_encoding(self):
a_naive_datetime = datetime(2012, 5, 1, 7, 27, 10, 20000)
a_tz_datetime = datetime(2012, 5, 1, 7, 27, 10, 20000, tzinfo=UTC)
a_tz_datetime = datetime(2012, 5, 1, 7, 27, 10, 20000, tzinfo=ZoneInfo("UTC"))
a_date = a_naive_datetime.date()
an_iso_datetime = '2012-05-01T07:27:10.020000+00:00'
an_iso_date = '2012-05-01'

View File

@@ -5,6 +5,7 @@ Utility methods related to file handling.
import os
from datetime import datetime
from zoneinfo import ZoneInfo
from django.conf import settings
from django.core.exceptions import PermissionDenied
@@ -12,7 +13,6 @@ from django.core.files.storage import DefaultStorage
from django.utils.text import get_valid_filename
from django.utils.translation import gettext as _
from django.utils.translation import ngettext
from pytz import UTC
from storages.backends.s3boto3 import S3Boto3Storage
@@ -145,7 +145,7 @@ def course_and_time_based_filename_generator(course_id, base_name):
return "{course_prefix}_{base_name}_{timestamp_str}".format(
course_prefix=course_filename_prefix_generator(course_id),
base_name=get_valid_filename(base_name),
timestamp_str=datetime.now(UTC).strftime("%Y-%m-%d-%H%M%S")
timestamp_str=datetime.now(ZoneInfo("UTC")).strftime("%Y-%m-%d-%H%M%S")
)

View File

@@ -5,12 +5,12 @@ Tests for util.date_utils
import unittest
from datetime import datetime, timedelta, tzinfo
from unittest.mock import patch
from zoneinfo import ZoneInfo
import crum
import ddt
import pytest
from markupsafe import Markup
from pytz import utc
from django.test.client import RequestFactory
@@ -21,7 +21,7 @@ from common.djangoapps.util.date_utils import (
def test_get_default_time_display():
assert get_default_time_display(None) == ""
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=utc)
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=ZoneInfo("UTC"))
assert get_default_time_display(test_time) == "Mar 12, 1992 at 15:03 UTC"
@@ -32,12 +32,12 @@ def test_get_dflt_time_disp_notz():
def test_get_time_disp_ret_empty():
assert get_time_display(None) == ""
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=utc)
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=ZoneInfo("UTC"))
assert get_time_display(test_time, "") == ""
def test_get_time_display():
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=utc)
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=ZoneInfo("UTC"))
assert get_time_display(test_time, 'dummy text') == "dummy text"
assert get_time_display(test_time, '%b %d %Y') == "Mar 12 1992"
assert get_time_display(test_time, '%b %d %Y %Z') == "Mar 12 1992 UTC"
@@ -45,15 +45,15 @@ def test_get_time_display():
def test_get_time_pass_through():
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=utc)
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=ZoneInfo("UTC"))
assert get_time_display(test_time) == "Mar 12, 1992 at 15:03 UTC"
assert get_time_display(test_time, None) == "Mar 12, 1992 at 15:03 UTC"
assert get_time_display(test_time, "%") == "Mar 12, 1992 at 15:03 UTC"
def test_get_time_display_coerce():
test_time_standard = datetime(1992, 1, 12, 15, 3, 30, tzinfo=utc)
test_time_daylight = datetime(1992, 7, 12, 15, 3, 30, tzinfo=utc)
test_time_standard = datetime(1992, 1, 12, 15, 3, 30, tzinfo=ZoneInfo("UTC"))
test_time_daylight = datetime(1992, 7, 12, 15, 3, 30, tzinfo=ZoneInfo("UTC"))
assert get_time_display(test_time_standard, None, coerce_tz="US/Pacific") == "Jan 12, 1992 at 07:03 PST"
assert get_time_display(test_time_standard, None, coerce_tz="NONEXISTENTTZ") == "Jan 12, 1992 at 15:03 UTC"
assert get_time_display(test_time_standard, '%b %d %H:%M', coerce_tz="US/Pacific") == "Jan 12 07:03"

View File

@@ -7,6 +7,7 @@ import os
from datetime import datetime
from io import StringIO
from unittest.mock import Mock, patch
from zoneinfo import ZoneInfo
import pytest
import ddt
@@ -17,7 +18,6 @@ from django.test import TestCase
from django.test.utils import override_settings
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import CourseLocator
from pytz import UTC
from ccx_keys.locator import CCXLocator
@@ -99,7 +99,7 @@ class FilenameGeneratorTestCase(TestCase):
"""
Tests for course_and_time_based_filename_generator
"""
NOW = datetime.strptime('1974-06-22T01:02:03', '%Y-%m-%dT%H:%M:%S').replace(tzinfo=UTC)
NOW = datetime.strptime('1974-06-22T01:02:03', '%Y-%m-%dT%H:%M:%S').replace(tzinfo=ZoneInfo("UTC"))
def setUp(self):
super().setUp()