summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Dufresne <jon.dufresne@gmail.com>2016-08-31 17:19:33 -0700
committerGitHub <noreply@github.com>2016-08-31 17:19:33 -0700
commitff1e7b4eb43737bf2752197036663cee58922317 (patch)
tree3ef2013de20c59e91dbe2532383ea62bb4763f20
parentd8ef5b0e6501692b8b767ebccddc936f496d77e8 (diff)
Fixed #25181 -- Added localdate() function to get date in a different time zone.
Thanks Konrad Świat for the original patch.
-rw-r--r--django/utils/timezone.py20
-rw-r--r--django/views/generic/dates.py2
-rw-r--r--docs/ref/utils.txt20
-rw-r--r--tests/utils_tests/test_timezone.py28
4 files changed, 65 insertions, 5 deletions
diff --git a/django/utils/timezone.py b/django/utils/timezone.py
index 20d59f5fed..e2c6967607 100644
--- a/django/utils/timezone.py
+++ b/django/utils/timezone.py
@@ -299,13 +299,18 @@ def template_localtime(value, use_tz=None):
# Utilities
-def localtime(value, timezone=None):
+def localtime(value=None, timezone=None):
"""
Converts an aware datetime.datetime to local time.
+ Only aware datetimes are allowed. When value is omitted, it defaults to
+ now().
+
Local time is defined by the current time zone, unless another time zone
is specified.
"""
+ if value is None:
+ value = now()
if timezone is None:
timezone = get_current_timezone()
# If `value` is naive, astimezone() will raise a ValueError,
@@ -317,6 +322,19 @@ def localtime(value, timezone=None):
return value
+def localdate(value=None, timezone=None):
+ """
+ Convert an aware datetime to local time and return the value's date.
+
+ Only aware datetimes are allowed. When value is omitted, it defaults to
+ now().
+
+ Local time is defined by the current time zone, unless another time zone is
+ specified.
+ """
+ return localtime(value, timezone).date()
+
+
def now():
"""
Returns an aware or naive datetime.datetime, depending on settings.USE_TZ.
diff --git a/django/views/generic/dates.py b/django/views/generic/dates.py
index 52b3b39062..938c538535 100644
--- a/django/views/generic/dates.py
+++ b/django/views/generic/dates.py
@@ -792,6 +792,6 @@ def timezone_today():
Return the current date in the current time zone.
"""
if settings.USE_TZ:
- return timezone.localtime(timezone.now()).date()
+ return timezone.localdate()
else:
return datetime.date.today()
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index 893ecb5792..00ac7970d7 100644
--- a/docs/ref/utils.txt
+++ b/docs/ref/utils.txt
@@ -974,14 +974,32 @@ appropriate entities.
``override`` is also usable as a function decorator.
-.. function:: localtime(value, timezone=None)
+.. function:: localtime(value=None, timezone=None)
Converts an aware :class:`~datetime.datetime` to a different time zone,
by default the :ref:`current time zone <default-current-time-zone>`.
+ When ``value`` is omitted, it defaults to :func:`now`.
+
This function doesn't work on naive datetimes; use :func:`make_aware`
instead.
+ .. versionchanged:: 1.11
+
+ In older versions, ``value`` is a required argument.
+
+.. function:: localdate(value=None, timezone=None)
+
+ .. versionadded:: 1.11
+
+ Uses :func:`localtime` to convert an aware :class:`~datetime.datetime` to a
+ :meth:`~datetime.datetime.date` in a different time zone, by default the
+ :ref:`current time zone <default-current-time-zone>`.
+
+ When ``value`` is omitted, it defaults to :func:`now`.
+
+ This function doesn't work on naive datetimes.
+
.. function:: now()
Returns a :class:`~datetime.datetime` that represents the
diff --git a/tests/utils_tests/test_timezone.py b/tests/utils_tests/test_timezone.py
index 5f21c06bae..9dc7941b4b 100644
--- a/tests/utils_tests/test_timezone.py
+++ b/tests/utils_tests/test_timezone.py
@@ -4,7 +4,7 @@ import pickle
import sys
import unittest
-from django.test import SimpleTestCase, override_settings
+from django.test import SimpleTestCase, mock, override_settings
from django.utils import timezone
try:
@@ -27,7 +27,10 @@ class TimezoneTests(SimpleTestCase):
def test_localtime(self):
now = datetime.datetime.utcnow().replace(tzinfo=timezone.utc)
local_tz = timezone.LocalTimezone()
- local_now = timezone.localtime(now, local_tz)
+ with timezone.override(local_tz):
+ local_now = timezone.localtime(now)
+ self.assertEqual(local_now.tzinfo, local_tz)
+ local_now = timezone.localtime(now, timezone=local_tz)
self.assertEqual(local_now.tzinfo, local_tz)
def test_localtime_naive(self):
@@ -54,6 +57,27 @@ class TimezoneTests(SimpleTestCase):
with override_settings(USE_TZ=False):
self.assertTrue(timezone.is_naive(timezone.now()))
+ def test_localdate(self):
+ naive = datetime.datetime(2015, 1, 1, 0, 0, 1)
+ if PY36:
+ self.assertEqual(timezone.localdate(naive), datetime.date(2015, 1, 1))
+ self.assertEqual(timezone.localdate(naive, timezone=EAT), datetime.date(2015, 1, 1))
+ else:
+ with self.assertRaisesMessage(ValueError, 'astimezone() cannot be applied to a naive datetime'):
+ timezone.localdate(naive)
+ with self.assertRaisesMessage(ValueError, 'astimezone() cannot be applied to a naive datetime'):
+ timezone.localdate(naive, timezone=EAT)
+
+ aware = datetime.datetime(2015, 1, 1, 0, 0, 1, tzinfo=ICT)
+ self.assertEqual(timezone.localdate(aware, timezone=EAT), datetime.date(2014, 12, 31))
+ with timezone.override(EAT):
+ self.assertEqual(timezone.localdate(aware), datetime.date(2014, 12, 31))
+
+ with mock.patch('django.utils.timezone.now', return_value=aware):
+ self.assertEqual(timezone.localdate(timezone=EAT), datetime.date(2014, 12, 31))
+ with timezone.override(EAT):
+ self.assertEqual(timezone.localdate(), datetime.date(2014, 12, 31))
+
def test_override(self):
default = timezone.get_default_timezone()
try: