diff options
author | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-01-09 09:03:38 +0100 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-01-17 11:49:15 +0100 |
commit | e6f82438d4e3750e8d299bfd79dac98eebe9f1e0 (patch) | |
tree | 4ee0cbf2c0be9822416aa3d65105f35a9784fd94 /tests/db_functions | |
parent | 8d98f99a4ab5de6f2c730399f53eba8bf6bea470 (diff) | |
download | django-e6f82438d4e3750e8d299bfd79dac98eebe9f1e0.tar.gz |
Refs #32365 -- Removed support for pytz timezones per deprecation timeline.
Diffstat (limited to 'tests/db_functions')
-rw-r--r-- | tests/db_functions/datetime/test_extract_trunc.py | 504 |
1 files changed, 212 insertions, 292 deletions
diff --git a/tests/db_functions/datetime/test_extract_trunc.py b/tests/db_functions/datetime/test_extract_trunc.py index b2327931f0..80043fe3f4 100644 --- a/tests/db_functions/datetime/test_extract_trunc.py +++ b/tests/db_functions/datetime/test_extract_trunc.py @@ -1,4 +1,3 @@ -import unittest from datetime import datetime, timedelta from datetime import timezone as datetime_timezone @@ -7,11 +6,6 @@ try: except ImportError: from backports import zoneinfo -try: - import pytz -except ImportError: - pytz = None - from django.conf import settings from django.db import DataError, OperationalError from django.db.models import ( @@ -51,29 +45,14 @@ from django.db.models.functions import ( ) from django.test import ( TestCase, - ignore_warnings, override_settings, skipIfDBFeature, skipUnlessDBFeature, ) from django.utils import timezone -from django.utils.deprecation import RemovedInDjango50Warning from ..models import Author, DTModel, Fan -HAS_PYTZ = pytz is not None -if not HAS_PYTZ: - needs_pytz = unittest.skip("Test requires pytz") -else: - - def needs_pytz(f): - return f - - -ZONE_CONSTRUCTORS = (zoneinfo.ZoneInfo,) -if HAS_PYTZ: - ZONE_CONSTRUCTORS += (pytz.timezone,) - def truncate_to(value, kind, tzinfo=None): # Convert to target timezone before truncation @@ -1690,10 +1669,6 @@ class DateFunctionTests(TestCase): @override_settings(USE_TZ=True, TIME_ZONE="UTC") class DateFunctionWithTimeZoneTests(DateFunctionTests): - def get_timezones(self, key): - for constructor in ZONE_CONSTRUCTORS: - yield constructor(key) - def test_extract_func_with_timezone(self): start_datetime = datetime(2015, 6, 15, 23, 30, 1, 321) end_datetime = datetime(2015, 6, 16, 13, 11, 27, 123) @@ -1702,62 +1677,57 @@ class DateFunctionWithTimeZoneTests(DateFunctionTests): self.create_model(start_datetime, end_datetime) delta_tzinfo_pos = datetime_timezone(timedelta(hours=5)) delta_tzinfo_neg = datetime_timezone(timedelta(hours=-5, minutes=17)) + melb = zoneinfo.ZoneInfo("Australia/Melbourne") - for melb in self.get_timezones("Australia/Melbourne"): - with self.subTest(repr(melb)): - qs = DTModel.objects.annotate( - day=Extract("start_datetime", "day"), - day_melb=Extract("start_datetime", "day", tzinfo=melb), - week=Extract("start_datetime", "week", tzinfo=melb), - isoyear=ExtractIsoYear("start_datetime", tzinfo=melb), - weekday=ExtractWeekDay("start_datetime"), - weekday_melb=ExtractWeekDay("start_datetime", tzinfo=melb), - isoweekday=ExtractIsoWeekDay("start_datetime"), - isoweekday_melb=ExtractIsoWeekDay("start_datetime", tzinfo=melb), - quarter=ExtractQuarter("start_datetime", tzinfo=melb), - hour=ExtractHour("start_datetime"), - hour_melb=ExtractHour("start_datetime", tzinfo=melb), - hour_with_delta_pos=ExtractHour( - "start_datetime", tzinfo=delta_tzinfo_pos - ), - hour_with_delta_neg=ExtractHour( - "start_datetime", tzinfo=delta_tzinfo_neg - ), - minute_with_delta_neg=ExtractMinute( - "start_datetime", tzinfo=delta_tzinfo_neg - ), - ).order_by("start_datetime") - - utc_model = qs.get() - self.assertEqual(utc_model.day, 15) - self.assertEqual(utc_model.day_melb, 16) - self.assertEqual(utc_model.week, 25) - self.assertEqual(utc_model.isoyear, 2015) - self.assertEqual(utc_model.weekday, 2) - self.assertEqual(utc_model.weekday_melb, 3) - self.assertEqual(utc_model.isoweekday, 1) - self.assertEqual(utc_model.isoweekday_melb, 2) - self.assertEqual(utc_model.quarter, 2) - self.assertEqual(utc_model.hour, 23) - self.assertEqual(utc_model.hour_melb, 9) - self.assertEqual(utc_model.hour_with_delta_pos, 4) - self.assertEqual(utc_model.hour_with_delta_neg, 18) - self.assertEqual(utc_model.minute_with_delta_neg, 47) - - with timezone.override(melb): - melb_model = qs.get() - - self.assertEqual(melb_model.day, 16) - self.assertEqual(melb_model.day_melb, 16) - self.assertEqual(melb_model.week, 25) - self.assertEqual(melb_model.isoyear, 2015) - self.assertEqual(melb_model.weekday, 3) - self.assertEqual(melb_model.isoweekday, 2) - self.assertEqual(melb_model.quarter, 2) - self.assertEqual(melb_model.weekday_melb, 3) - self.assertEqual(melb_model.isoweekday_melb, 2) - self.assertEqual(melb_model.hour, 9) - self.assertEqual(melb_model.hour_melb, 9) + qs = DTModel.objects.annotate( + day=Extract("start_datetime", "day"), + day_melb=Extract("start_datetime", "day", tzinfo=melb), + week=Extract("start_datetime", "week", tzinfo=melb), + isoyear=ExtractIsoYear("start_datetime", tzinfo=melb), + weekday=ExtractWeekDay("start_datetime"), + weekday_melb=ExtractWeekDay("start_datetime", tzinfo=melb), + isoweekday=ExtractIsoWeekDay("start_datetime"), + isoweekday_melb=ExtractIsoWeekDay("start_datetime", tzinfo=melb), + quarter=ExtractQuarter("start_datetime", tzinfo=melb), + hour=ExtractHour("start_datetime"), + hour_melb=ExtractHour("start_datetime", tzinfo=melb), + hour_with_delta_pos=ExtractHour("start_datetime", tzinfo=delta_tzinfo_pos), + hour_with_delta_neg=ExtractHour("start_datetime", tzinfo=delta_tzinfo_neg), + minute_with_delta_neg=ExtractMinute( + "start_datetime", tzinfo=delta_tzinfo_neg + ), + ).order_by("start_datetime") + + utc_model = qs.get() + self.assertEqual(utc_model.day, 15) + self.assertEqual(utc_model.day_melb, 16) + self.assertEqual(utc_model.week, 25) + self.assertEqual(utc_model.isoyear, 2015) + self.assertEqual(utc_model.weekday, 2) + self.assertEqual(utc_model.weekday_melb, 3) + self.assertEqual(utc_model.isoweekday, 1) + self.assertEqual(utc_model.isoweekday_melb, 2) + self.assertEqual(utc_model.quarter, 2) + self.assertEqual(utc_model.hour, 23) + self.assertEqual(utc_model.hour_melb, 9) + self.assertEqual(utc_model.hour_with_delta_pos, 4) + self.assertEqual(utc_model.hour_with_delta_neg, 18) + self.assertEqual(utc_model.minute_with_delta_neg, 47) + + with timezone.override(melb): + melb_model = qs.get() + + self.assertEqual(melb_model.day, 16) + self.assertEqual(melb_model.day_melb, 16) + self.assertEqual(melb_model.week, 25) + self.assertEqual(melb_model.isoyear, 2015) + self.assertEqual(melb_model.weekday, 3) + self.assertEqual(melb_model.isoweekday, 2) + self.assertEqual(melb_model.quarter, 2) + self.assertEqual(melb_model.weekday_melb, 3) + self.assertEqual(melb_model.isoweekday_melb, 2) + self.assertEqual(melb_model.hour, 9) + self.assertEqual(melb_model.hour_melb, 9) def test_extract_func_with_timezone_minus_no_offset(self): start_datetime = datetime(2015, 6, 15, 23, 30, 1, 321) @@ -1765,22 +1735,22 @@ class DateFunctionWithTimeZoneTests(DateFunctionTests): start_datetime = timezone.make_aware(start_datetime) end_datetime = timezone.make_aware(end_datetime) self.create_model(start_datetime, end_datetime) - for ust_nera in self.get_timezones("Asia/Ust-Nera"): - with self.subTest(repr(ust_nera)): - qs = DTModel.objects.annotate( - hour=ExtractHour("start_datetime"), - hour_tz=ExtractHour("start_datetime", tzinfo=ust_nera), - ).order_by("start_datetime") + ust_nera = zoneinfo.ZoneInfo("Asia/Ust-Nera") - utc_model = qs.get() - self.assertEqual(utc_model.hour, 23) - self.assertEqual(utc_model.hour_tz, 9) + qs = DTModel.objects.annotate( + hour=ExtractHour("start_datetime"), + hour_tz=ExtractHour("start_datetime", tzinfo=ust_nera), + ).order_by("start_datetime") + + utc_model = qs.get() + self.assertEqual(utc_model.hour, 23) + self.assertEqual(utc_model.hour_tz, 9) - with timezone.override(ust_nera): - ust_nera_model = qs.get() + with timezone.override(ust_nera): + ust_nera_model = qs.get() - self.assertEqual(ust_nera_model.hour, 9) - self.assertEqual(ust_nera_model.hour_tz, 9) + self.assertEqual(ust_nera_model.hour, 9) + self.assertEqual(ust_nera_model.hour_tz, 9) def test_extract_func_explicit_timezone_priority(self): start_datetime = datetime(2015, 6, 15, 23, 30, 1, 321) @@ -1788,35 +1758,32 @@ class DateFunctionWithTimeZoneTests(DateFunctionTests): start_datetime = timezone.make_aware(start_datetime) end_datetime = timezone.make_aware(end_datetime) self.create_model(start_datetime, end_datetime) - - for melb in self.get_timezones("Australia/Melbourne"): - with self.subTest(repr(melb)): - with timezone.override(melb): - model = ( - DTModel.objects.annotate( - day_melb=Extract("start_datetime", "day"), - day_utc=Extract( - "start_datetime", "day", tzinfo=datetime_timezone.utc - ), - ) - .order_by("start_datetime") - .get() - ) - self.assertEqual(model.day_melb, 16) - self.assertEqual(model.day_utc, 15) + melb = zoneinfo.ZoneInfo("Australia/Melbourne") + with timezone.override(melb): + model = ( + DTModel.objects.annotate( + day_melb=Extract("start_datetime", "day"), + day_utc=Extract( + "start_datetime", "day", tzinfo=datetime_timezone.utc + ), + ) + .order_by("start_datetime") + .get() + ) + self.assertEqual(model.day_melb, 16) + self.assertEqual(model.day_utc, 15) def test_extract_invalid_field_with_timezone(self): - for melb in self.get_timezones("Australia/Melbourne"): - with self.subTest(repr(melb)): - msg = "tzinfo can only be used with DateTimeField." - with self.assertRaisesMessage(ValueError, msg): - DTModel.objects.annotate( - day_melb=Extract("start_date", "day", tzinfo=melb), - ).get() - with self.assertRaisesMessage(ValueError, msg): - DTModel.objects.annotate( - hour_melb=Extract("start_time", "hour", tzinfo=melb), - ).get() + melb = zoneinfo.ZoneInfo("Australia/Melbourne") + msg = "tzinfo can only be used with DateTimeField." + with self.assertRaisesMessage(ValueError, msg): + DTModel.objects.annotate( + day_melb=Extract("start_date", "day", tzinfo=melb), + ).get() + with self.assertRaisesMessage(ValueError, msg): + DTModel.objects.annotate( + hour_melb=Extract("start_time", "hour", tzinfo=melb), + ).get() def test_trunc_timezone_applied_before_truncation(self): start_datetime = datetime(2016, 1, 1, 1, 30, 50, 321) @@ -1824,74 +1791,36 @@ class DateFunctionWithTimeZoneTests(DateFunctionTests): start_datetime = timezone.make_aware(start_datetime) end_datetime = timezone.make_aware(end_datetime) self.create_model(start_datetime, end_datetime) + melb = zoneinfo.ZoneInfo("Australia/Melbourne") + pacific = zoneinfo.ZoneInfo("America/Los_Angeles") - for melb, pacific in zip( - self.get_timezones("Australia/Melbourne"), - self.get_timezones("America/Los_Angeles"), - ): - with self.subTest((repr(melb), repr(pacific))): - model = ( - DTModel.objects.annotate( - melb_year=TruncYear("start_datetime", tzinfo=melb), - pacific_year=TruncYear("start_datetime", tzinfo=pacific), - melb_date=TruncDate("start_datetime", tzinfo=melb), - pacific_date=TruncDate("start_datetime", tzinfo=pacific), - melb_time=TruncTime("start_datetime", tzinfo=melb), - pacific_time=TruncTime("start_datetime", tzinfo=pacific), - ) - .order_by("start_datetime") - .get() - ) + model = ( + DTModel.objects.annotate( + melb_year=TruncYear("start_datetime", tzinfo=melb), + pacific_year=TruncYear("start_datetime", tzinfo=pacific), + melb_date=TruncDate("start_datetime", tzinfo=melb), + pacific_date=TruncDate("start_datetime", tzinfo=pacific), + melb_time=TruncTime("start_datetime", tzinfo=melb), + pacific_time=TruncTime("start_datetime", tzinfo=pacific), + ) + .order_by("start_datetime") + .get() + ) - melb_start_datetime = start_datetime.astimezone(melb) - pacific_start_datetime = start_datetime.astimezone(pacific) - self.assertEqual(model.start_datetime, start_datetime) - self.assertEqual( - model.melb_year, truncate_to(start_datetime, "year", melb) - ) - self.assertEqual( - model.pacific_year, truncate_to(start_datetime, "year", pacific) - ) - self.assertEqual(model.start_datetime.year, 2016) - self.assertEqual(model.melb_year.year, 2016) - self.assertEqual(model.pacific_year.year, 2015) - self.assertEqual(model.melb_date, melb_start_datetime.date()) - self.assertEqual(model.pacific_date, pacific_start_datetime.date()) - self.assertEqual(model.melb_time, melb_start_datetime.time()) - self.assertEqual(model.pacific_time, pacific_start_datetime.time()) - - @needs_pytz - @ignore_warnings(category=RemovedInDjango50Warning) - def test_trunc_ambiguous_and_invalid_times(self): - sao = pytz.timezone("America/Sao_Paulo") - start_datetime = datetime(2016, 10, 16, 13, tzinfo=datetime_timezone.utc) - end_datetime = datetime(2016, 2, 21, 1, tzinfo=datetime_timezone.utc) - self.create_model(start_datetime, end_datetime) - with timezone.override(sao): - with self.assertRaisesMessage( - pytz.NonExistentTimeError, "2016-10-16 00:00:00" - ): - model = DTModel.objects.annotate( - truncated_start=TruncDay("start_datetime") - ).get() - with self.assertRaisesMessage( - pytz.AmbiguousTimeError, "2016-02-20 23:00:00" - ): - model = DTModel.objects.annotate( - truncated_end=TruncHour("end_datetime") - ).get() - model = DTModel.objects.annotate( - truncated_start=TruncDay("start_datetime", is_dst=False), - truncated_end=TruncHour("end_datetime", is_dst=False), - ).get() - self.assertEqual(model.truncated_start.dst(), timedelta(0)) - self.assertEqual(model.truncated_end.dst(), timedelta(0)) - model = DTModel.objects.annotate( - truncated_start=TruncDay("start_datetime", is_dst=True), - truncated_end=TruncHour("end_datetime", is_dst=True), - ).get() - self.assertEqual(model.truncated_start.dst(), timedelta(0, 3600)) - self.assertEqual(model.truncated_end.dst(), timedelta(0, 3600)) + melb_start_datetime = start_datetime.astimezone(melb) + pacific_start_datetime = start_datetime.astimezone(pacific) + self.assertEqual(model.start_datetime, start_datetime) + self.assertEqual(model.melb_year, truncate_to(start_datetime, "year", melb)) + self.assertEqual( + model.pacific_year, truncate_to(start_datetime, "year", pacific) + ) + self.assertEqual(model.start_datetime.year, 2016) + self.assertEqual(model.melb_year.year, 2016) + self.assertEqual(model.pacific_year.year, 2015) + self.assertEqual(model.melb_date, melb_start_datetime.date()) + self.assertEqual(model.pacific_date, pacific_start_datetime.date()) + self.assertEqual(model.melb_time, melb_start_datetime.time()) + self.assertEqual(model.pacific_time, pacific_start_datetime.time()) def test_trunc_func_with_timezone(self): """ @@ -1904,118 +1833,109 @@ class DateFunctionWithTimeZoneTests(DateFunctionTests): end_datetime = timezone.make_aware(end_datetime) self.create_model(start_datetime, end_datetime) self.create_model(end_datetime, start_datetime) + melb = zoneinfo.ZoneInfo("Australia/Melbourne") - for melb in self.get_timezones("Australia/Melbourne"): - with self.subTest(repr(melb)): - - def test_datetime_kind(kind): - self.assertQuerySetEqual( - DTModel.objects.annotate( - truncated=Trunc( - "start_datetime", - kind, - output_field=DateTimeField(), - tzinfo=melb, - ) - ).order_by("start_datetime"), - [ - ( - start_datetime, - truncate_to( - start_datetime.astimezone(melb), kind, melb - ), - ), - ( - end_datetime, - truncate_to(end_datetime.astimezone(melb), kind, melb), - ), - ], - lambda m: (m.start_datetime, m.truncated), + def test_datetime_kind(kind): + self.assertQuerySetEqual( + DTModel.objects.annotate( + truncated=Trunc( + "start_datetime", + kind, + output_field=DateTimeField(), + tzinfo=melb, ) + ).order_by("start_datetime"), + [ + ( + start_datetime, + truncate_to(start_datetime.astimezone(melb), kind, melb), + ), + ( + end_datetime, + truncate_to(end_datetime.astimezone(melb), kind, melb), + ), + ], + lambda m: (m.start_datetime, m.truncated), + ) - def test_datetime_to_date_kind(kind): - self.assertQuerySetEqual( - DTModel.objects.annotate( - truncated=Trunc( - "start_datetime", - kind, - output_field=DateField(), - tzinfo=melb, - ), - ).order_by("start_datetime"), - [ - ( - start_datetime, - truncate_to( - start_datetime.astimezone(melb).date(), kind - ), - ), - ( - end_datetime, - truncate_to(end_datetime.astimezone(melb).date(), kind), - ), - ], - lambda m: (m.start_datetime, m.truncated), - ) + def test_datetime_to_date_kind(kind): + self.assertQuerySetEqual( + DTModel.objects.annotate( + truncated=Trunc( + "start_datetime", + kind, + output_field=DateField(), + tzinfo=melb, + ), + ).order_by("start_datetime"), + [ + ( + start_datetime, + truncate_to(start_datetime.astimezone(melb).date(), kind), + ), + ( + end_datetime, + truncate_to(end_datetime.astimezone(melb).date(), kind), + ), + ], + lambda m: (m.start_datetime, m.truncated), + ) - def test_datetime_to_time_kind(kind): - self.assertQuerySetEqual( - DTModel.objects.annotate( - truncated=Trunc( - "start_datetime", - kind, - output_field=TimeField(), - tzinfo=melb, - ) - ).order_by("start_datetime"), - [ - ( - start_datetime, - truncate_to( - start_datetime.astimezone(melb).time(), kind - ), - ), - ( - end_datetime, - truncate_to(end_datetime.astimezone(melb).time(), kind), - ), - ], - lambda m: (m.start_datetime, m.truncated), + def test_datetime_to_time_kind(kind): + self.assertQuerySetEqual( + DTModel.objects.annotate( + truncated=Trunc( + "start_datetime", + kind, + output_field=TimeField(), + tzinfo=melb, ) + ).order_by("start_datetime"), + [ + ( + start_datetime, + truncate_to(start_datetime.astimezone(melb).time(), kind), + ), + ( + end_datetime, + truncate_to(end_datetime.astimezone(melb).time(), kind), + ), + ], + lambda m: (m.start_datetime, m.truncated), + ) - test_datetime_to_date_kind("year") - test_datetime_to_date_kind("quarter") - test_datetime_to_date_kind("month") - test_datetime_to_date_kind("week") - test_datetime_to_date_kind("day") - test_datetime_to_time_kind("hour") - test_datetime_to_time_kind("minute") - test_datetime_to_time_kind("second") - test_datetime_kind("year") - test_datetime_kind("quarter") - test_datetime_kind("month") - test_datetime_kind("week") - test_datetime_kind("day") - test_datetime_kind("hour") - test_datetime_kind("minute") - test_datetime_kind("second") + test_datetime_to_date_kind("year") + test_datetime_to_date_kind("quarter") + test_datetime_to_date_kind("month") + test_datetime_to_date_kind("week") + test_datetime_to_date_kind("day") + test_datetime_to_time_kind("hour") + test_datetime_to_time_kind("minute") + test_datetime_to_time_kind("second") + test_datetime_kind("year") + test_datetime_kind("quarter") + test_datetime_kind("month") + test_datetime_kind("week") + test_datetime_kind("day") + test_datetime_kind("hour") + test_datetime_kind("minute") + test_datetime_kind("second") - qs = DTModel.objects.filter( - start_datetime__date=Trunc( - "start_datetime", "day", output_field=DateField() - ) - ) - self.assertEqual(qs.count(), 2) + qs = DTModel.objects.filter( + start_datetime__date=Trunc( + "start_datetime", "day", output_field=DateField() + ) + ) + self.assertEqual(qs.count(), 2) def test_trunc_invalid_field_with_timezone(self): - for melb in self.get_timezones("Australia/Melbourne"): - with self.subTest(repr(melb)): - msg = "tzinfo can only be used with DateTimeField." - with self.assertRaisesMessage(ValueError, msg): - DTModel.objects.annotate( - day_melb=Trunc("start_date", "day", tzinfo=melb), - ).get() - with self.assertRaisesMessage(ValueError, msg): - DTModel.objects.annotate( - hour_melb=Trunc("start_time", "hour", tzinfo=melb), - ).get() + melb = zoneinfo.ZoneInfo("Australia/Melbourne") + msg = "tzinfo can only be used with DateTimeField." + with self.assertRaisesMessage(ValueError, msg): + DTModel.objects.annotate( + day_melb=Trunc("start_date", "day", tzinfo=melb), + ).get() + with self.assertRaisesMessage(ValueError, msg): + DTModel.objects.annotate( + hour_melb=Trunc("start_time", "hour", tzinfo=melb), + ).get() |