1. ==========
    
  2. Time zones
    
  3. ==========
    
  4. 
    
  5. .. _time-zones-overview:
    
  6. 
    
  7. Overview
    
  8. ========
    
  9. 
    
  10. When support for time zones is enabled, Django stores datetime information in
    
  11. UTC in the database, uses time-zone-aware datetime objects internally, and
    
  12. translates them to the end user's time zone in templates and forms.
    
  13. 
    
  14. This is handy if your users live in more than one time zone and you want to
    
  15. display datetime information according to each user's wall clock.
    
  16. 
    
  17. Even if your website is available in only one time zone, it's still good
    
  18. practice to store data in UTC in your database. The main reason is daylight
    
  19. saving time (DST). Many countries have a system of DST, where clocks are moved
    
  20. forward in spring and backward in autumn. If you're working in local time,
    
  21. you're likely to encounter errors twice a year, when the transitions happen.
    
  22. This probably doesn't matter for your blog, but it's a problem if you over bill
    
  23. or under bill your customers by one hour, twice a year, every year. The
    
  24. solution to this problem is to use UTC in the code and use local time only when
    
  25. interacting with end users.
    
  26. 
    
  27. Time zone support is disabled by default. To enable it, set :setting:`USE_TZ =
    
  28. True <USE_TZ>` in your settings file.
    
  29. 
    
  30. .. note::
    
  31. 
    
  32.     In Django 5.0, time zone support will be enabled by default.
    
  33. 
    
  34. Time zone support uses :mod:`zoneinfo`, which is part of the Python standard
    
  35. library from Python 3.9.  The ``backports.zoneinfo`` package is automatically
    
  36. installed alongside Django if you are using Python 3.8.
    
  37. 
    
  38. .. versionchanged:: 4.0
    
  39. 
    
  40.     :mod:`zoneinfo` was made the default timezone implementation. You may
    
  41.     continue to use `pytz`_ during the 4.x release cycle via the
    
  42.     :setting:`USE_DEPRECATED_PYTZ` setting.
    
  43. 
    
  44. .. note::
    
  45. 
    
  46.     The default :file:`settings.py` file created by :djadmin:`django-admin
    
  47.     startproject <startproject>` includes :setting:`USE_TZ = True <USE_TZ>`
    
  48.     for convenience.
    
  49. 
    
  50. If you're wrestling with a particular problem, start with the :ref:`time zone
    
  51. FAQ <time-zones-faq>`.
    
  52. 
    
  53. Concepts
    
  54. ========
    
  55. 
    
  56. .. _naive_vs_aware_datetimes:
    
  57. 
    
  58. Naive and aware datetime objects
    
  59. --------------------------------
    
  60. 
    
  61. Python's :class:`datetime.datetime` objects have a ``tzinfo`` attribute that
    
  62. can be used to store time zone information, represented as an instance of a
    
  63. subclass of :class:`datetime.tzinfo`. When this attribute is set and describes
    
  64. an offset, a datetime object is **aware**. Otherwise, it's **naive**.
    
  65. 
    
  66. You can use :func:`~django.utils.timezone.is_aware` and
    
  67. :func:`~django.utils.timezone.is_naive` to determine whether datetimes are
    
  68. aware or naive.
    
  69. 
    
  70. When time zone support is disabled, Django uses naive datetime objects in local
    
  71. time. This is sufficient for many use cases. In this mode, to obtain the
    
  72. current time, you would write::
    
  73. 
    
  74.     import datetime
    
  75. 
    
  76.     now = datetime.datetime.now()
    
  77. 
    
  78. When time zone support is enabled (:setting:`USE_TZ=True <USE_TZ>`), Django uses
    
  79. time-zone-aware datetime objects. If your code creates datetime objects, they
    
  80. should be aware too. In this mode, the example above becomes::
    
  81. 
    
  82.     from django.utils import timezone
    
  83. 
    
  84.     now = timezone.now()
    
  85. 
    
  86. .. warning::
    
  87. 
    
  88.     Dealing with aware datetime objects isn't always intuitive. For instance,
    
  89.     the ``tzinfo`` argument of the standard datetime constructor doesn't work
    
  90.     reliably for time zones with DST. Using UTC is generally safe; if you're
    
  91.     using other time zones, you should review the :mod:`zoneinfo`
    
  92.     documentation carefully.
    
  93. 
    
  94. .. note::
    
  95. 
    
  96.     Python's :class:`datetime.time` objects also feature a ``tzinfo``
    
  97.     attribute, and PostgreSQL has a matching ``time with time zone`` type.
    
  98.     However, as PostgreSQL's docs put it, this type "exhibits properties which
    
  99.     lead to questionable usefulness".
    
  100. 
    
  101.     Django only supports naive time objects and will raise an exception if you
    
  102.     attempt to save an aware time object, as a timezone for a time with no
    
  103.     associated date does not make sense.
    
  104. 
    
  105. .. _naive-datetime-objects:
    
  106. 
    
  107. Interpretation of naive datetime objects
    
  108. ----------------------------------------
    
  109. 
    
  110. When :setting:`USE_TZ` is ``True``, Django still accepts naive datetime
    
  111. objects, in order to preserve backwards-compatibility. When the database layer
    
  112. receives one, it attempts to make it aware by interpreting it in the
    
  113. :ref:`default time zone <default-current-time-zone>` and raises a warning.
    
  114. 
    
  115. Unfortunately, during DST transitions, some datetimes don't exist or are
    
  116. ambiguous. That's why you should always create aware datetime objects when time
    
  117. zone support is enabled. (See the :mod:`Using ZoneInfo section of the zoneinfo
    
  118. docs <zoneinfo>` for examples using the ``fold`` attribute to specify the
    
  119. offset that should apply to a datetime during a DST transition.)
    
  120. 
    
  121. In practice, this is rarely an issue. Django gives you aware datetime objects
    
  122. in the models and forms, and most often, new datetime objects are created from
    
  123. existing ones through :class:`~datetime.timedelta` arithmetic. The only
    
  124. datetime that's often created in application code is the current time, and
    
  125. :func:`timezone.now() <django.utils.timezone.now>` automatically does the
    
  126. right thing.
    
  127. 
    
  128. .. _default-current-time-zone:
    
  129. 
    
  130. Default time zone and current time zone
    
  131. ---------------------------------------
    
  132. 
    
  133. The **default time zone** is the time zone defined by the :setting:`TIME_ZONE`
    
  134. setting.
    
  135. 
    
  136. The **current time zone** is the time zone that's used for rendering.
    
  137. 
    
  138. You should set the current time zone to the end user's actual time zone with
    
  139. :func:`~django.utils.timezone.activate`. Otherwise, the default time zone is
    
  140. used.
    
  141. 
    
  142. .. note::
    
  143. 
    
  144.     As explained in the documentation of :setting:`TIME_ZONE`, Django sets
    
  145.     environment variables so that its process runs in the default time zone.
    
  146.     This happens regardless of the value of :setting:`USE_TZ` and of the
    
  147.     current time zone.
    
  148. 
    
  149.     When :setting:`USE_TZ` is ``True``, this is useful to preserve
    
  150.     backwards-compatibility with applications that still rely on local time.
    
  151.     However, :ref:`as explained above <naive-datetime-objects>`, this isn't
    
  152.     entirely reliable, and you should always work with aware datetimes in UTC
    
  153.     in your own code. For instance, use :meth:`~datetime.datetime.fromtimestamp`
    
  154.     and set the ``tz`` parameter to :attr:`~datetime.timezone.utc`.
    
  155. 
    
  156. Selecting the current time zone
    
  157. -------------------------------
    
  158. 
    
  159. The current time zone is the equivalent of the current :term:`locale <locale
    
  160. name>` for translations. However, there's no equivalent of the
    
  161. ``Accept-Language`` HTTP header that Django could use to determine the user's
    
  162. time zone automatically. Instead, Django provides :ref:`time zone selection
    
  163. functions <time-zone-selection-functions>`. Use them to build the time zone
    
  164. selection logic that makes sense for you.
    
  165. 
    
  166. Most websites that care about time zones ask users in which time zone they live
    
  167. and store this information in the user's profile. For anonymous users, they use
    
  168. the time zone of their primary audience or UTC.
    
  169. :func:`zoneinfo.available_timezones` provides a set of available timezones that
    
  170. you can use to build a map from likely locations to time zones.
    
  171. 
    
  172. Here's an example that stores the current timezone in the session. (It skips
    
  173. error handling entirely for the sake of simplicity.)
    
  174. 
    
  175. Add the following middleware to :setting:`MIDDLEWARE`::
    
  176. 
    
  177.     import zoneinfo
    
  178. 
    
  179.     from django.utils import timezone
    
  180. 
    
  181.     class TimezoneMiddleware:
    
  182.         def __init__(self, get_response):
    
  183.             self.get_response = get_response
    
  184. 
    
  185.         def __call__(self, request):
    
  186.             tzname = request.session.get('django_timezone')
    
  187.             if tzname:
    
  188.                 timezone.activate(zoneinfo.ZoneInfo(tzname))
    
  189.             else:
    
  190.                 timezone.deactivate()
    
  191.             return self.get_response(request)
    
  192. 
    
  193. Create a view that can set the current timezone::
    
  194. 
    
  195.     from django.shortcuts import redirect, render
    
  196. 
    
  197.     # Prepare a map of common locations to timezone choices you wish to offer.
    
  198.     common_timezones = {
    
  199.         'London': 'Europe/London',
    
  200.         'Paris': 'Europe/Paris',
    
  201.         'New York': 'America/New_York',
    
  202.     }
    
  203. 
    
  204.     def set_timezone(request):
    
  205.         if request.method == 'POST':
    
  206.             request.session['django_timezone'] = request.POST['timezone']
    
  207.             return redirect('/')
    
  208.         else:
    
  209.             return render(request, 'template.html', {'timezones': common_timezones})
    
  210. 
    
  211. Include a form in ``template.html`` that will ``POST`` to this view:
    
  212. 
    
  213. .. code-block:: html+django
    
  214. 
    
  215.     {% load tz %}
    
  216.     {% get_current_timezone as TIME_ZONE %}
    
  217.     <form action="{% url 'set_timezone' %}" method="POST">
    
  218.         {% csrf_token %}
    
  219.         <label for="timezone">Time zone:</label>
    
  220.         <select name="timezone">
    
  221.             {% for city, tz in timezones %}
    
  222.             <option value="{{ tz }}"{% if tz == TIME_ZONE %} selected{% endif %}>{{ city }}</option>
    
  223.             {% endfor %}
    
  224.         </select>
    
  225.         <input type="submit" value="Set">
    
  226.     </form>
    
  227. 
    
  228. .. _time-zones-in-forms:
    
  229. 
    
  230. Time zone aware input in forms
    
  231. ==============================
    
  232. 
    
  233. When you enable time zone support, Django interprets datetimes entered in
    
  234. forms in the :ref:`current time zone <default-current-time-zone>` and returns
    
  235. aware datetime objects in ``cleaned_data``.
    
  236. 
    
  237. Converted datetimes that don't exist or are ambiguous because they fall in a
    
  238. DST transition will be reported as invalid values.
    
  239. 
    
  240. .. _time-zones-in-templates:
    
  241. 
    
  242. Time zone aware output in templates
    
  243. ===================================
    
  244. 
    
  245. When you enable time zone support, Django converts aware datetime objects to
    
  246. the :ref:`current time zone <default-current-time-zone>` when they're rendered
    
  247. in templates. This behaves very much like :doc:`format localization
    
  248. </topics/i18n/formatting>`.
    
  249. 
    
  250. .. warning::
    
  251. 
    
  252.     Django doesn't convert naive datetime objects, because they could be
    
  253.     ambiguous, and because your code should never produce naive datetimes when
    
  254.     time zone support is enabled. However, you can force conversion with the
    
  255.     template filters described below.
    
  256. 
    
  257. Conversion to local time isn't always appropriate -- you may be generating
    
  258. output for computers rather than for humans. The following filters and tags,
    
  259. provided by the ``tz`` template tag library, allow you to control the time zone
    
  260. conversions.
    
  261. 
    
  262. .. highlight:: html+django
    
  263. 
    
  264. Template tags
    
  265. -------------
    
  266. 
    
  267. .. templatetag:: localtime
    
  268. 
    
  269. ``localtime``
    
  270. ~~~~~~~~~~~~~
    
  271. 
    
  272. Enables or disables conversion of aware datetime objects to the current time
    
  273. zone in the contained block.
    
  274. 
    
  275. This tag has exactly the same effects as the :setting:`USE_TZ` setting as far
    
  276. as the template engine is concerned. It allows a more fine grained control of
    
  277. conversion.
    
  278. 
    
  279. To activate or deactivate conversion for a template block, use::
    
  280. 
    
  281.     {% load tz %}
    
  282. 
    
  283.     {% localtime on %}
    
  284.         {{ value }}
    
  285.     {% endlocaltime %}
    
  286. 
    
  287.     {% localtime off %}
    
  288.         {{ value }}
    
  289.     {% endlocaltime %}
    
  290. 
    
  291. .. note::
    
  292. 
    
  293.     The value of :setting:`USE_TZ` isn't respected inside of a
    
  294.     ``{% localtime %}`` block.
    
  295. 
    
  296. .. templatetag:: timezone
    
  297. 
    
  298. ``timezone``
    
  299. ~~~~~~~~~~~~
    
  300. 
    
  301. Sets or unsets the current time zone in the contained block. When the current
    
  302. time zone is unset, the default time zone applies.
    
  303. 
    
  304. ::
    
  305. 
    
  306.     {% load tz %}
    
  307. 
    
  308.     {% timezone "Europe/Paris" %}
    
  309.         Paris time: {{ value }}
    
  310.     {% endtimezone %}
    
  311. 
    
  312.     {% timezone None %}
    
  313.         Server time: {{ value }}
    
  314.     {% endtimezone %}
    
  315. 
    
  316. .. templatetag:: get_current_timezone
    
  317. 
    
  318. ``get_current_timezone``
    
  319. ~~~~~~~~~~~~~~~~~~~~~~~~
    
  320. 
    
  321. You can get the name of the current time zone using the
    
  322. ``get_current_timezone`` tag::
    
  323. 
    
  324.     {% get_current_timezone as TIME_ZONE %}
    
  325. 
    
  326. Alternatively, you can activate the
    
  327. :func:`~django.template.context_processors.tz` context processor and
    
  328. use the ``TIME_ZONE`` context variable.
    
  329. 
    
  330. Template filters
    
  331. ----------------
    
  332. 
    
  333. These filters accept both aware and naive datetimes. For conversion purposes,
    
  334. they assume that naive datetimes are in the default time zone. They always
    
  335. return aware datetimes.
    
  336. 
    
  337. .. templatefilter:: localtime
    
  338. 
    
  339. ``localtime``
    
  340. ~~~~~~~~~~~~~
    
  341. 
    
  342. Forces conversion of a single value to the current time zone.
    
  343. 
    
  344. For example::
    
  345. 
    
  346.     {% load tz %}
    
  347. 
    
  348.     {{ value|localtime }}
    
  349. 
    
  350. .. templatefilter:: utc
    
  351. 
    
  352. ``utc``
    
  353. ~~~~~~~
    
  354. 
    
  355. Forces conversion of a single value to UTC.
    
  356. 
    
  357. For example::
    
  358. 
    
  359.     {% load tz %}
    
  360. 
    
  361.     {{ value|utc }}
    
  362. 
    
  363. .. templatefilter:: timezone
    
  364. 
    
  365. ``timezone``
    
  366. ~~~~~~~~~~~~
    
  367. 
    
  368. Forces conversion of a single value to an arbitrary timezone.
    
  369. 
    
  370. The argument must be an instance of a :class:`~datetime.tzinfo` subclass or a
    
  371. time zone name.
    
  372. 
    
  373. For example::
    
  374. 
    
  375.     {% load tz %}
    
  376. 
    
  377.     {{ value|timezone:"Europe/Paris" }}
    
  378. 
    
  379. .. highlight:: python
    
  380. 
    
  381. .. _time-zones-migration-guide:
    
  382. 
    
  383. Migration guide
    
  384. ===============
    
  385. 
    
  386. Here's how to migrate a project that was started before Django supported time
    
  387. zones.
    
  388. 
    
  389. Database
    
  390. --------
    
  391. 
    
  392. PostgreSQL
    
  393. ~~~~~~~~~~
    
  394. 
    
  395. The PostgreSQL backend stores datetimes as ``timestamp with time zone``. In
    
  396. practice, this means it converts datetimes from the connection's time zone to
    
  397. UTC on storage, and from UTC to the connection's time zone on retrieval.
    
  398. 
    
  399. As a consequence, if you're using PostgreSQL, you can switch between ``USE_TZ
    
  400. = False`` and ``USE_TZ = True`` freely. The database connection's time zone
    
  401. will be set to :setting:`TIME_ZONE` or ``UTC`` respectively, so that Django
    
  402. obtains correct datetimes in all cases. You don't need to perform any data
    
  403. conversions.
    
  404. 
    
  405. Other databases
    
  406. ~~~~~~~~~~~~~~~
    
  407. 
    
  408. Other backends store datetimes without time zone information. If you switch
    
  409. from ``USE_TZ = False`` to ``USE_TZ = True``, you must convert your data from
    
  410. local time to UTC -- which isn't deterministic if your local time has DST.
    
  411. 
    
  412. Code
    
  413. ----
    
  414. 
    
  415. The first step is to add :setting:`USE_TZ = True <USE_TZ>` to your settings
    
  416. file. At this point, things should mostly work. If you create naive datetime
    
  417. objects in your code, Django makes them aware when necessary.
    
  418. 
    
  419. However, these conversions may fail around DST transitions, which means you
    
  420. aren't getting the full benefits of time zone support yet. Also, you're likely
    
  421. to run into a few problems because it's impossible to compare a naive datetime
    
  422. with an aware datetime. Since Django now gives you aware datetimes, you'll get
    
  423. exceptions wherever you compare a datetime that comes from a model or a form
    
  424. with a naive datetime that you've created in your code.
    
  425. 
    
  426. So the second step is to refactor your code wherever you instantiate datetime
    
  427. objects to make them aware. This can be done incrementally.
    
  428. :mod:`django.utils.timezone` defines some handy helpers for compatibility
    
  429. code: :func:`~django.utils.timezone.now`,
    
  430. :func:`~django.utils.timezone.is_aware`,
    
  431. :func:`~django.utils.timezone.is_naive`,
    
  432. :func:`~django.utils.timezone.make_aware`, and
    
  433. :func:`~django.utils.timezone.make_naive`.
    
  434. 
    
  435. Finally, in order to help you locate code that needs upgrading, Django raises
    
  436. a warning when you attempt to save a naive datetime to the database::
    
  437. 
    
  438.     RuntimeWarning: DateTimeField ModelName.field_name received a naive
    
  439.     datetime (2012-01-01 00:00:00) while time zone support is active.
    
  440. 
    
  441. During development, you can turn such warnings into exceptions and get a
    
  442. traceback by adding the following to your settings file::
    
  443. 
    
  444.     import warnings
    
  445.     warnings.filterwarnings(
    
  446.         'error', r"DateTimeField .* received a naive datetime",
    
  447.         RuntimeWarning, r'django\.db\.models\.fields',
    
  448.     )
    
  449. 
    
  450. Fixtures
    
  451. --------
    
  452. 
    
  453. When serializing an aware datetime, the UTC offset is included, like this::
    
  454. 
    
  455.     "2011-09-01T13:20:30+03:00"
    
  456. 
    
  457. While for a naive datetime, it isn't::
    
  458. 
    
  459.     "2011-09-01T13:20:30"
    
  460. 
    
  461. For models with :class:`~django.db.models.DateTimeField`\ s, this difference
    
  462. makes it impossible to write a fixture that works both with and without time
    
  463. zone support.
    
  464. 
    
  465. Fixtures generated with ``USE_TZ = False``, or before Django 1.4, use the
    
  466. "naive" format. If your project contains such fixtures, after you enable time
    
  467. zone support, you'll see :exc:`RuntimeWarning`\ s when you load them. To get
    
  468. rid of the warnings, you must convert your fixtures to the "aware" format.
    
  469. 
    
  470. You can regenerate fixtures with :djadmin:`loaddata` then :djadmin:`dumpdata`.
    
  471. Or, if they're small enough, you can edit them to add the UTC offset that
    
  472. matches your :setting:`TIME_ZONE` to each serialized datetime.
    
  473. 
    
  474. .. _time-zones-faq:
    
  475. 
    
  476. FAQ
    
  477. ===
    
  478. 
    
  479. Setup
    
  480. -----
    
  481. 
    
  482. #. **I don't need multiple time zones. Should I enable time zone support?**
    
  483. 
    
  484.    Yes. When time zone support is enabled, Django uses a more accurate model
    
  485.    of local time. This shields you from subtle and unreproducible bugs around
    
  486.    daylight saving time (DST) transitions.
    
  487. 
    
  488.    When you enable time zone support, you'll encounter some errors because
    
  489.    you're using naive datetimes where Django expects aware datetimes. Such
    
  490.    errors show up when running tests. You'll quickly learn how to avoid invalid
    
  491.    operations.
    
  492. 
    
  493.    On the other hand, bugs caused by the lack of time zone support are much
    
  494.    harder to prevent, diagnose and fix. Anything that involves scheduled tasks
    
  495.    or datetime arithmetic is a candidate for subtle bugs that will bite you
    
  496.    only once or twice a year.
    
  497. 
    
  498.    For these reasons, time zone support is enabled by default in new projects,
    
  499.    and you should keep it unless you have a very good reason not to.
    
  500. 
    
  501. #. **I've enabled time zone support. Am I safe?**
    
  502. 
    
  503.    Maybe. You're better protected from DST-related bugs, but you can still
    
  504.    shoot yourself in the foot by carelessly turning naive datetimes into aware
    
  505.    datetimes, and vice-versa.
    
  506. 
    
  507.    If your application connects to other systems -- for instance, if it queries
    
  508.    a web service -- make sure datetimes are properly specified. To transmit
    
  509.    datetimes safely, their representation should include the UTC offset, or
    
  510.    their values should be in UTC (or both!).
    
  511. 
    
  512.    Finally, our calendar system contains interesting edge cases. For example,
    
  513.    you can't always subtract one year directly from a given date::
    
  514. 
    
  515.        >>> import datetime
    
  516.        >>> def one_year_before(value):  # Wrong example.
    
  517.        ...     return value.replace(year=value.year - 1)
    
  518.        >>> one_year_before(datetime.datetime(2012, 3, 1, 10, 0))
    
  519.        datetime.datetime(2011, 3, 1, 10, 0)
    
  520.        >>> one_year_before(datetime.datetime(2012, 2, 29, 10, 0))
    
  521.        Traceback (most recent call last):
    
  522.        ...
    
  523.        ValueError: day is out of range for month
    
  524. 
    
  525.    To implement such a function correctly, you must decide whether 2012-02-29
    
  526.    minus one year is 2011-02-28 or 2011-03-01, which depends on your business
    
  527.    requirements.
    
  528. 
    
  529. #. **How do I interact with a database that stores datetimes in local time?**
    
  530. 
    
  531.    Set the :setting:`TIME_ZONE <DATABASE-TIME_ZONE>` option to the appropriate
    
  532.    time zone for this database in the :setting:`DATABASES` setting.
    
  533. 
    
  534.    This is useful for connecting to a database that doesn't support time zones
    
  535.    and that isn't managed by Django when :setting:`USE_TZ` is ``True``.
    
  536. 
    
  537. Troubleshooting
    
  538. ---------------
    
  539. 
    
  540. #. **My application crashes with** ``TypeError: can't compare offset-naive``
    
  541.    ``and offset-aware datetimes`` **-- what's wrong?**
    
  542. 
    
  543.    Let's reproduce this error by comparing a naive and an aware datetime::
    
  544. 
    
  545.        >>> from django.utils import timezone
    
  546.        >>> aware = timezone.now()
    
  547.        >>> naive = timezone.make_naive(aware)
    
  548.        >>> naive == aware
    
  549.        Traceback (most recent call last):
    
  550.        ...
    
  551.        TypeError: can't compare offset-naive and offset-aware datetimes
    
  552. 
    
  553.    If you encounter this error, most likely your code is comparing these two
    
  554.    things:
    
  555. 
    
  556.    - a datetime provided by Django -- for instance, a value read from a form or
    
  557.      a model field. Since you enabled time zone support, it's aware.
    
  558.    - a datetime generated by your code, which is naive (or you wouldn't be
    
  559.      reading this).
    
  560. 
    
  561.    Generally, the correct solution is to change your code to use an aware
    
  562.    datetime instead.
    
  563. 
    
  564.    If you're writing a pluggable application that's expected to work
    
  565.    independently of the value of :setting:`USE_TZ`, you may find
    
  566.    :func:`django.utils.timezone.now` useful. This function returns the current
    
  567.    date and time as a naive datetime when ``USE_TZ = False`` and as an aware
    
  568.    datetime when ``USE_TZ = True``. You can add or subtract
    
  569.    :class:`datetime.timedelta` as needed.
    
  570. 
    
  571. #. **I see lots of** ``RuntimeWarning: DateTimeField received a naive
    
  572.    datetime`` ``(YYYY-MM-DD HH:MM:SS)`` ``while time zone support is active``
    
  573.    **-- is that bad?**
    
  574. 
    
  575.    When time zone support is enabled, the database layer expects to receive
    
  576.    only aware datetimes from your code. This warning occurs when it receives a
    
  577.    naive datetime. This indicates that you haven't finished porting your code
    
  578.    for time zone support. Please refer to the :ref:`migration guide
    
  579.    <time-zones-migration-guide>` for tips on this process.
    
  580. 
    
  581.    In the meantime, for backwards compatibility, the datetime is considered to
    
  582.    be in the default time zone, which is generally what you expect.
    
  583. 
    
  584. #. ``now.date()`` **is yesterday! (or tomorrow)**
    
  585. 
    
  586.    If you've always used naive datetimes, you probably believe that you can
    
  587.    convert a datetime to a date by calling its :meth:`~datetime.datetime.date`
    
  588.    method. You also consider that a :class:`~datetime.date` is a lot like a
    
  589.    :class:`~datetime.datetime`, except that it's less accurate.
    
  590. 
    
  591.    None of this is true in a time zone aware environment::
    
  592. 
    
  593.        >>> import datetime
    
  594.        >>> import zoneinfo
    
  595.        >>> paris_tz = zoneinfo.ZoneInfo("Europe/Paris")
    
  596.        >>> new_york_tz = zoneinfo.ZoneInfo("America/New_York")
    
  597.        >>> paris = datetime.datetime(2012, 3, 3, 1, 30, tzinfo=paris_tz)
    
  598.        # This is the correct way to convert between time zones.
    
  599.        >>> new_york = paris.astimezone(new_york_tz)
    
  600.        >>> paris == new_york, paris.date() == new_york.date()
    
  601.        (True, False)
    
  602.        >>> paris - new_york, paris.date() - new_york.date()
    
  603.        (datetime.timedelta(0), datetime.timedelta(1))
    
  604.        >>> paris
    
  605.        datetime.datetime(2012, 3, 3, 1, 30, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))
    
  606.        >>> new_york
    
  607.        datetime.datetime(2012, 3, 2, 19, 30, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
    
  608. 
    
  609.    As this example shows, the same datetime has a different date, depending on
    
  610.    the time zone in which it is represented. But the real problem is more
    
  611.    fundamental.
    
  612. 
    
  613.    A datetime represents a **point in time**. It's absolute: it doesn't depend
    
  614.    on anything. On the contrary, a date is a **calendaring concept**. It's a
    
  615.    period of time whose bounds depend on the time zone in which the date is
    
  616.    considered. As you can see, these two concepts are fundamentally different,
    
  617.    and converting a datetime to a date isn't a deterministic operation.
    
  618. 
    
  619.    What does this mean in practice?
    
  620. 
    
  621.    Generally, you should avoid converting a :class:`~datetime.datetime` to
    
  622.    :class:`~datetime.date`. For instance, you can use the :tfilter:`date`
    
  623.    template filter to only show the date part of a datetime. This filter will
    
  624.    convert the datetime into the current time zone before formatting it,
    
  625.    ensuring the results appear correctly.
    
  626. 
    
  627.    If you really need to do the conversion yourself, you must ensure the
    
  628.    datetime is converted to the appropriate time zone first. Usually, this
    
  629.    will be the current timezone::
    
  630. 
    
  631.        >>> from django.utils import timezone
    
  632.        >>> timezone.activate(zoneinfo.ZoneInfo("Asia/Singapore"))
    
  633.        # For this example, we set the time zone to Singapore, but here's how
    
  634.        # you would obtain the current time zone in the general case.
    
  635.        >>> current_tz = timezone.get_current_timezone()
    
  636.        >>> local = paris.astimezone(current_tz)
    
  637.        >>> local
    
  638.        datetime.datetime(2012, 3, 3, 8, 30, tzinfo=zoneinfo.ZoneInfo(key='Asia/Singapore'))
    
  639.        >>> local.date()
    
  640.        datetime.date(2012, 3, 3)
    
  641. 
    
  642. #. **I get an error** "``Are time zone definitions for your database
    
  643.    installed?``"
    
  644. 
    
  645.    If you are using MySQL, see the :ref:`mysql-time-zone-definitions` section
    
  646.    of the MySQL notes for instructions on loading time zone definitions.
    
  647. 
    
  648. Usage
    
  649. -----
    
  650. 
    
  651. #. **I have a string** ``"2012-02-21 10:28:45"`` **and I know it's in the**
    
  652.    ``"Europe/Helsinki"`` **time zone. How do I turn that into an aware
    
  653.    datetime?**
    
  654. 
    
  655.    Here you need to create the required ``ZoneInfo`` instance and attach it to
    
  656.    the naïve datetime::
    
  657. 
    
  658.        >>> import zoneinfo
    
  659.        >>> from django.utils.dateparse import parse_datetime
    
  660.        >>> naive = parse_datetime("2012-02-21 10:28:45")
    
  661.        >>> naive.replace(tzinfo=zoneinfo.ZoneInfo("Europe/Helsinki"))
    
  662.        datetime.datetime(2012, 2, 21, 10, 28, 45, tzinfo=zoneinfo.ZoneInfo(key='Europe/Helsinki'))
    
  663. 
    
  664. #. **How can I obtain the local time in the current time zone?**
    
  665. 
    
  666.    Well, the first question is, do you really need to?
    
  667. 
    
  668.    You should only use local time when you're interacting with humans, and the
    
  669.    template layer provides :ref:`filters and tags <time-zones-in-templates>`
    
  670.    to convert datetimes to the time zone of your choice.
    
  671. 
    
  672.    Furthermore, Python knows how to compare aware datetimes, taking into
    
  673.    account UTC offsets when necessary. It's much easier (and possibly faster)
    
  674.    to write all your model and view code in UTC. So, in most circumstances,
    
  675.    the datetime in UTC returned by :func:`django.utils.timezone.now` will be
    
  676.    sufficient.
    
  677. 
    
  678.    For the sake of completeness, though, if you really want the local time
    
  679.    in the current time zone, here's how you can obtain it::
    
  680. 
    
  681.        >>> from django.utils import timezone
    
  682.        >>> timezone.localtime(timezone.now())
    
  683.        datetime.datetime(2012, 3, 3, 20, 10, 53, 873365, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))
    
  684. 
    
  685.    In this example, the current time zone is ``"Europe/Paris"``.
    
  686. 
    
  687. #. **How can I see all available time zones?**
    
  688. 
    
  689.    :func:`zoneinfo.available_timezones` provides the set of all valid keys for
    
  690.    IANA time zones available to your system. See the docs for usage
    
  691.    considerations.
    
  692. 
    
  693. .. _pytz: http://pytz.sourceforge.net/