From 4aa06890805f8bc619d240ca5b4e2cd81be308c1 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Fri, 6 Jan 2023 09:37:41 +0100 Subject: [PATCH] Refs #32738 -- Removed django.utils.datetime_safe module per deprecation timeline. --- django/utils/datetime_safe.py | 118 ------------------------ docs/releases/5.0.txt | 2 + tests/utils_tests/test_datetime_safe.py | 77 ---------------- 3 files changed, 2 insertions(+), 195 deletions(-) delete mode 100644 django/utils/datetime_safe.py delete mode 100644 tests/utils_tests/test_datetime_safe.py diff --git a/django/utils/datetime_safe.py b/django/utils/datetime_safe.py deleted file mode 100644 index 2792b48a26..0000000000 --- a/django/utils/datetime_safe.py +++ /dev/null @@ -1,118 +0,0 @@ -# These classes override date and datetime to ensure that strftime('%Y') -# returns four digits (with leading zeros) on years < 1000. -# https://bugs.python.org/issue13305 -# -# Based on code submitted to comp.lang.python by Andrew Dalke -# -# >>> datetime_safe.date(10, 8, 2).strftime("%Y/%m/%d was a %A") -# '0010/08/02 was a Monday' - -import time -import warnings -from datetime import date as real_date -from datetime import datetime as real_datetime - -from django.utils.deprecation import RemovedInDjango50Warning -from django.utils.regex_helper import _lazy_re_compile - -warnings.warn( - "The django.utils.datetime_safe module is deprecated.", - category=RemovedInDjango50Warning, - stacklevel=2, -) - - -class date(real_date): - def strftime(self, fmt): - return strftime(self, fmt) - - -class datetime(real_datetime): - def strftime(self, fmt): - return strftime(self, fmt) - - @classmethod - def combine(cls, date, time): - return cls( - date.year, - date.month, - date.day, - time.hour, - time.minute, - time.second, - time.microsecond, - time.tzinfo, - ) - - def date(self): - return date(self.year, self.month, self.day) - - -def new_date(d): - "Generate a safe date from a datetime.date object." - return date(d.year, d.month, d.day) - - -def new_datetime(d): - """ - Generate a safe datetime from a datetime.date or datetime.datetime object. - """ - kw = [d.year, d.month, d.day] - if isinstance(d, real_datetime): - kw.extend([d.hour, d.minute, d.second, d.microsecond, d.tzinfo]) - return datetime(*kw) - - -# This library does not support strftime's "%s" or "%y" format strings. -# Allowed if there's an even number of "%"s because they are escaped. -_illegal_formatting = _lazy_re_compile(r"((^|[^%])(%%)*%[sy])") - - -def _findall(text, substr): - # Also finds overlaps - sites = [] - i = 0 - while True: - i = text.find(substr, i) - if i == -1: - break - sites.append(i) - i += 1 - return sites - - -def strftime(dt, fmt): - if dt.year >= 1000: - return super(type(dt), dt).strftime(fmt) - illegal_formatting = _illegal_formatting.search(fmt) - if illegal_formatting: - raise TypeError( - "strftime of dates before 1000 does not handle " + illegal_formatting[0] - ) - - year = dt.year - # For every non-leap year century, advance by - # 6 years to get into the 28-year repeat cycle - delta = 2000 - year - off = 6 * (delta // 100 + delta // 400) - year += off - - # Move to around the year 2000 - year += ((2000 - year) // 28) * 28 - timetuple = dt.timetuple() - s1 = time.strftime(fmt, (year,) + timetuple[1:]) - sites1 = _findall(s1, str(year)) - - s2 = time.strftime(fmt, (year + 28,) + timetuple[1:]) - sites2 = _findall(s2, str(year + 28)) - - sites = [] - for site in sites1: - if site in sites2: - sites.append(site) - - s = s1 - syear = "%04d" % dt.year - for site in sites: - s = s[:site] + syear + s[site + 4 :] - return s diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt index 82c06e3be1..631a11ca3b 100644 --- a/docs/releases/5.0.txt +++ b/docs/releases/5.0.txt @@ -259,6 +259,8 @@ to remove usage of these features. * The undocumented ``django.utils.baseconv`` module is removed. +* The undocumented ``django.utils.datetime_safe`` module is removed. + See :ref:`deprecated-features-4.1` for details on these changes, including how to remove usage of these features. diff --git a/tests/utils_tests/test_datetime_safe.py b/tests/utils_tests/test_datetime_safe.py deleted file mode 100644 index cb987319f4..0000000000 --- a/tests/utils_tests/test_datetime_safe.py +++ /dev/null @@ -1,77 +0,0 @@ -from datetime import date as original_date -from datetime import datetime as original_datetime - -from django.test import SimpleTestCase, ignore_warnings -from django.utils.deprecation import RemovedInDjango50Warning - -with ignore_warnings(category=RemovedInDjango50Warning): - from django.utils.datetime_safe import date, datetime - - -class DatetimeTests(SimpleTestCase): - def setUp(self): - self.percent_y_safe = (1900, 1, 1) # >= 1900 required on Windows. - self.just_safe = (1000, 1, 1) - self.just_unsafe = (999, 12, 31, 23, 59, 59) - self.really_old = (20, 1, 1) - self.more_recent = (2006, 1, 1) - - def test_compare_datetimes(self): - self.assertEqual( - original_datetime(*self.more_recent), datetime(*self.more_recent) - ) - self.assertEqual( - original_datetime(*self.really_old), datetime(*self.really_old) - ) - self.assertEqual(original_date(*self.more_recent), date(*self.more_recent)) - self.assertEqual(original_date(*self.really_old), date(*self.really_old)) - - self.assertEqual( - original_date(*self.just_safe).strftime("%Y-%m-%d"), - date(*self.just_safe).strftime("%Y-%m-%d"), - ) - self.assertEqual( - original_datetime(*self.just_safe).strftime("%Y-%m-%d"), - datetime(*self.just_safe).strftime("%Y-%m-%d"), - ) - - def test_safe_strftime(self): - self.assertEqual( - date(*self.just_unsafe[:3]).strftime("%Y-%m-%d (weekday %w)"), - "0999-12-31 (weekday 2)", - ) - self.assertEqual( - date(*self.just_safe).strftime("%Y-%m-%d (weekday %w)"), - "1000-01-01 (weekday 3)", - ) - - self.assertEqual( - datetime(*self.just_unsafe).strftime("%Y-%m-%d %H:%M:%S (weekday %w)"), - "0999-12-31 23:59:59 (weekday 2)", - ) - self.assertEqual( - datetime(*self.just_safe).strftime("%Y-%m-%d %H:%M:%S (weekday %w)"), - "1000-01-01 00:00:00 (weekday 3)", - ) - - # %y will error before this date - self.assertEqual(date(*self.percent_y_safe).strftime("%y"), "00") - self.assertEqual(datetime(*self.percent_y_safe).strftime("%y"), "00") - with self.assertRaisesMessage( - TypeError, "strftime of dates before 1000 does not handle %y" - ): - datetime(*self.just_unsafe).strftime("%y") - - self.assertEqual( - date(1850, 8, 2).strftime("%Y/%m/%d was a %A"), "1850/08/02 was a Friday" - ) - - def test_zero_padding(self): - """ - Regression for #12524 - - Pre-1000AD dates are padded with zeros if necessary - """ - self.assertEqual( - date(1, 1, 1).strftime("%Y/%m/%d was a %A"), "0001/01/01 was a Monday" - )