123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707 |
- .. _time-zones:
- ==========
- Time zones
- ==========
- .. _time-zones-overview:
- Overview
- ========
- When support for time zones is enabled, Django stores date and time
- information in UTC in the database, uses time-zone-aware datetime objects
- internally, and translates them to the end user's time zone in templates and
- forms.
- This is handy if your users live in more than one time zone and you want to
- display date and time information according to each user's wall clock.
- Even if your Web site is available in only one time zone, it's still good
- practice to store data in UTC in your database. One main reason is Daylight
- Saving Time (DST). Many countries have a system of DST, where clocks are moved
- forward in spring and backward in autumn. If you're working in local time,
- you're likely to encounter errors twice a year, when the transitions happen.
- (The pytz_ documentation discusses `these issues`_ in greater detail.) This
- probably doesn't matter for your blog, but it's a problem if you over-bill or
- under-bill your customers by one hour, twice a year, every year. The solution
- to this problem is to use UTC in the code and use local time only when
- interacting with end users.
- Time zone support is disabled by default. To enable it, set :setting:`USE_TZ =
- True <USE_TZ>` in your settings file. Installing pytz_ is highly recommended,
- but may not be mandatory depending on your particular database backend,
- operating system and time zone. If you encounter an exception querying dates
- or times, please try installing it before filing a bug. It's as simple as:
- .. code-block:: bash
- $ pip install pytz
- .. note::
- The default :file:`settings.py` file created by :djadmin:`django-admin
- startproject <startproject>` includes :setting:`USE_TZ = True <USE_TZ>`
- for convenience.
- .. note::
- There is also an independent but related :setting:`USE_L10N` setting that
- controls whether Django should activate format localization. See
- :doc:`/topics/i18n/formatting` for more details.
- If you're wrestling with a particular problem, start with the :ref:`time zone
- FAQ <time-zones-faq>`.
- Concepts
- ========
- .. _naive_vs_aware_datetimes:
- Naive and aware datetime objects
- --------------------------------
- Python's :class:`datetime.datetime` objects have a ``tzinfo`` attribute that
- can be used to store time zone information, represented as an instance of a
- subclass of :class:`datetime.tzinfo`. When this attribute is set and describes
- an offset, a datetime object is **aware**. Otherwise, it's **naive**.
- You can use :func:`~django.utils.timezone.is_aware` and
- :func:`~django.utils.timezone.is_naive` to determine whether datetimes are
- aware or naive.
- When time zone support is disabled, Django uses naive datetime objects in local
- time. This is simple and sufficient for many use cases. In this mode, to obtain
- the current time, you would write::
- import datetime
- now = datetime.datetime.now()
- When time zone support is enabled (:setting:`USE_TZ=True <USE_TZ>`), Django uses
- time-zone-aware datetime objects. If your code creates datetime objects, they
- should be aware too. In this mode, the example above becomes::
- from django.utils import timezone
- now = timezone.now()
- .. warning::
- Dealing with aware datetime objects isn't always intuitive. For instance,
- the ``tzinfo`` argument of the standard datetime constructor doesn't work
- reliably for time zones with DST. Using UTC is generally safe; if you're
- using other time zones, you should review the `pytz`_ documentation
- carefully.
- .. note::
- Python's :class:`datetime.time` objects also feature a ``tzinfo``
- attribute, and PostgreSQL has a matching ``time with time zone`` type.
- However, as PostgreSQL's docs put it, this type "exhibits properties which
- lead to questionable usefulness".
- Django only supports naive time objects and will raise an exception if you
- attempt to save an aware time object, as a timezone for a time with no
- associated date does not make sense.
- .. _naive-datetime-objects:
- Interpretation of naive datetime objects
- ----------------------------------------
- When :setting:`USE_TZ` is ``True``, Django still accepts naive datetime
- objects, in order to preserve backwards-compatibility. When the database layer
- receives one, it attempts to make it aware by interpreting it in the
- :ref:`default time zone <default-current-time-zone>` and raises a warning.
- Unfortunately, during DST transitions, some datetimes don't exist or are
- ambiguous. In such situations, pytz_ raises an exception. Other
- :class:`~datetime.tzinfo` implementations, such as the local time zone used as
- a fallback when pytz_ isn't installed, may raise an exception or return
- inaccurate results. That's why you should always create aware datetime objects
- when time zone support is enabled.
- In practice, this is rarely an issue. Django gives you aware datetime objects
- in the models and forms, and most often, new datetime objects are created from
- existing ones through :class:`~datetime.timedelta` arithmetic. The only
- datetime that's often created in application code is the current time, and
- :func:`timezone.now() <django.utils.timezone.now>` automatically does the
- right thing.
- .. _default-current-time-zone:
- Default time zone and current time zone
- ---------------------------------------
- The **default time zone** is the time zone defined by the :setting:`TIME_ZONE`
- setting.
- The **current time zone** is the time zone that's used for rendering.
- You should set the current time zone to the end user's actual time zone with
- :func:`~django.utils.timezone.activate`. Otherwise, the default time zone is
- used.
- .. note::
- As explained in the documentation of :setting:`TIME_ZONE`, Django sets
- environment variables so that its process runs in the default time zone.
- This happens regardless of the value of :setting:`USE_TZ` and of the
- current time zone.
- When :setting:`USE_TZ` is ``True``, this is useful to preserve
- backwards-compatibility with applications that still rely on local time.
- However, :ref:`as explained above <naive-datetime-objects>`, this isn't
- entirely reliable, and you should always work with aware datetimes in UTC
- in your own code. For instance, use
- :meth:`~datetime.datetime.utcfromtimestamp` instead of
- :meth:`~datetime.datetime.fromtimestamp` -- and don't forget to set
- ``tzinfo`` to :data:`~django.utils.timezone.utc`.
- Selecting the current time zone
- -------------------------------
- The current time zone is the equivalent of the current :term:`locale <locale
- name>` for translations. However, there's no equivalent of the
- ``Accept-Language`` HTTP header that Django could use to determine the user's
- time zone automatically. Instead, Django provides :ref:`time zone selection
- functions <time-zone-selection-functions>`. Use them to build the time zone
- selection logic that makes sense for you.
- Most Web sites that care about time zones just ask users in which time zone they
- live and store this information in the user's profile. For anonymous users,
- they use the time zone of their primary audience or UTC. pytz_ provides
- helpers_, like a list of time zones per country, that you can use to pre-select
- the most likely choices.
- Here's an example that stores the current timezone in the session. (It skips
- error handling entirely for the sake of simplicity.)
- Add the following middleware to :setting:`MIDDLEWARE_CLASSES`::
- import pytz
- from django.utils import timezone
- class TimezoneMiddleware(object):
- def process_request(self, request):
- tzname = request.session.get('django_timezone')
- if tzname:
- timezone.activate(pytz.timezone(tzname))
- else:
- timezone.deactivate()
- Create a view that can set the current timezone::
- from django.shortcuts import redirect, render
- def set_timezone(request):
- if request.method == 'POST':
- request.session['django_timezone'] = request.POST['timezone']
- return redirect('/')
- else:
- return render(request, 'template.html', {'timezones': pytz.common_timezones})
- Include a form in ``template.html`` that will ``POST`` to this view:
- .. code-block:: html+django
- {% load tz %}
- {% get_current_timezone as TIME_ZONE %}
- <form action="{% url 'set_timezone' %}" method="POST">
- {% csrf_token %}
- <label for="timezone">Time zone:</label>
- <select name="timezone">
- {% for tz in timezones %}
- <option value="{{ tz }}"{% if tz == TIME_ZONE %} selected="selected"{% endif %}>{{ tz }}</option>
- {% endfor %}
- </select>
- <input type="submit" value="Set" />
- </form>
- .. _time-zones-in-forms:
- Time zone aware input in forms
- ==============================
- When you enable time zone support, Django interprets datetimes entered in
- forms in the :ref:`current time zone <default-current-time-zone>` and returns
- aware datetime objects in ``cleaned_data``.
- If the current time zone raises an exception for datetimes that don't exist or
- are ambiguous because they fall in a DST transition (the timezones provided by
- pytz_ do this), such datetimes will be reported as invalid values.
- .. _time-zones-in-templates:
- Time zone aware output in templates
- ===================================
- When you enable time zone support, Django converts aware datetime objects to
- the :ref:`current time zone <default-current-time-zone>` when they're rendered
- in templates. This behaves very much like :doc:`format localization
- </topics/i18n/formatting>`.
- .. warning::
- Django doesn't convert naive datetime objects, because they could be
- ambiguous, and because your code should never produce naive datetimes when
- time zone support is enabled. However, you can force conversion with the
- template filters described below.
- Conversion to local time isn't always appropriate -- you may be generating
- output for computers rather than for humans. The following filters and tags,
- provided by the ``tz`` template tag library, allow you to control the time zone
- conversions.
- Template tags
- -------------
- .. templatetag:: localtime
- localtime
- ~~~~~~~~~
- Enables or disables conversion of aware datetime objects to the current time
- zone in the contained block.
- This tag has exactly the same effects as the :setting:`USE_TZ` setting as far
- as the template engine is concerned. It allows a more fine grained control of
- conversion.
- To activate or deactivate conversion for a template block, use::
- {% load tz %}
- {% localtime on %}
- {{ value }}
- {% endlocaltime %}
- {% localtime off %}
- {{ value }}
- {% endlocaltime %}
- .. note::
- The value of :setting:`USE_TZ` isn't respected inside of a
- ``{% localtime %}`` block.
- .. templatetag:: timezone
- timezone
- ~~~~~~~~
- Sets or unsets the current time zone in the contained block. When the current
- time zone is unset, the default time zone applies.
- ::
- {% load tz %}
- {% timezone "Europe/Paris" %}
- Paris time: {{ value }}
- {% endtimezone %}
- {% timezone None %}
- Server time: {{ value }}
- {% endtimezone %}
- .. templatetag:: get_current_timezone
- get_current_timezone
- ~~~~~~~~~~~~~~~~~~~~
- You can get the name of the current time zone using the
- ``get_current_timezone`` tag::
- {% get_current_timezone as TIME_ZONE %}
- If you enable the ``django.template.context_processors.tz`` context processor,
- each :class:`~django.template.RequestContext` will contain a ``TIME_ZONE``
- variable with the value of ``get_current_timezone()``.
- Template filters
- ----------------
- These filters accept both aware and naive datetimes. For conversion purposes,
- they assume that naive datetimes are in the default time zone. They always
- return aware datetimes.
- .. templatefilter:: localtime
- localtime
- ~~~~~~~~~
- Forces conversion of a single value to the current time zone.
- For example::
- {% load tz %}
- {{ value|localtime }}
- .. templatefilter:: utc
- utc
- ~~~
- Forces conversion of a single value to UTC.
- For example::
- {% load tz %}
- {{ value|utc }}
- .. templatefilter:: timezone
- timezone
- ~~~~~~~~
- Forces conversion of a single value to an arbitrary timezone.
- The argument must be an instance of a :class:`~datetime.tzinfo` subclass or a
- time zone name. If it is a time zone name, pytz_ is required.
- For example::
- {% load tz %}
- {{ value|timezone:"Europe/Paris" }}
- .. _time-zones-migration-guide:
- Migration guide
- ===============
- Here's how to migrate a project that was started before Django supported time
- zones.
- Database
- --------
- PostgreSQL
- ~~~~~~~~~~
- The PostgreSQL backend stores datetimes as ``timestamp with time zone``. In
- practice, this means it converts datetimes from the connection's time zone to
- UTC on storage, and from UTC to the connection's time zone on retrieval.
- As a consequence, if you're using PostgreSQL, you can switch between ``USE_TZ
- = False`` and ``USE_TZ = True`` freely. The database connection's time zone
- will be set to :setting:`TIME_ZONE` or ``UTC`` respectively, so that Django
- obtains correct datetimes in all cases. You don't need to perform any data
- conversions.
- Other databases
- ~~~~~~~~~~~~~~~
- Other backends store datetimes without time zone information. If you switch
- from ``USE_TZ = False`` to ``USE_TZ = True``, you must convert your data from
- local time to UTC -- which isn't deterministic if your local time has DST.
- Code
- ----
- The first step is to add :setting:`USE_TZ = True <USE_TZ>` to your settings
- file and install pytz_ (if possible). At this point, things should mostly
- work. If you create naive datetime objects in your code, Django makes them
- aware when necessary.
- However, these conversions may fail around DST transitions, which means you
- aren't getting the full benefits of time zone support yet. Also, you're likely
- to run into a few problems because it's impossible to compare a naive datetime
- with an aware datetime. Since Django now gives you aware datetimes, you'll get
- exceptions wherever you compare a datetime that comes from a model or a form
- with a naive datetime that you've created in your code.
- So the second step is to refactor your code wherever you instantiate datetime
- objects to make them aware. This can be done incrementally.
- :mod:`django.utils.timezone` defines some handy helpers for compatibility
- code: :func:`~django.utils.timezone.now`,
- :func:`~django.utils.timezone.is_aware`,
- :func:`~django.utils.timezone.is_naive`,
- :func:`~django.utils.timezone.make_aware`, and
- :func:`~django.utils.timezone.make_naive`.
- Finally, in order to help you locate code that needs upgrading, Django raises
- a warning when you attempt to save a naive datetime to the database::
- RuntimeWarning: DateTimeField ModelName.field_name received a naive
- datetime (2012-01-01 00:00:00) while time zone support is active.
- During development, you can turn such warnings into exceptions and get a
- traceback by adding the following to your settings file::
- import warnings
- warnings.filterwarnings(
- 'error', r"DateTimeField .* received a naive datetime",
- RuntimeWarning, r'django\.db\.models\.fields')
- Fixtures
- --------
- When serializing an aware datetime, the UTC offset is included, like this::
- "2011-09-01T13:20:30+03:00"
- For a naive datetime, it obviously isn't::
- "2011-09-01T13:20:30"
- For models with :class:`~django.db.models.DateTimeField`\ s, this difference
- makes it impossible to write a fixture that works both with and without time
- zone support.
- Fixtures generated with ``USE_TZ = False``, or before Django 1.4, use the
- "naive" format. If your project contains such fixtures, after you enable time
- zone support, you'll see :exc:`RuntimeWarning`\ s when you load them. To get
- rid of the warnings, you must convert your fixtures to the "aware" format.
- You can regenerate fixtures with :djadmin:`loaddata` then :djadmin:`dumpdata`.
- Or, if they're small enough, you can simply edit them to add the UTC offset
- that matches your :setting:`TIME_ZONE` to each serialized datetime.
- .. _time-zones-faq:
- FAQ
- ===
- Setup
- -----
- 1. **I don't need multiple time zones. Should I enable time zone support?**
- Yes. When time zone support is enabled, Django uses a more accurate model
- of local time. This shields you from subtle and unreproducible bugs around
- Daylight Saving Time (DST) transitions.
- In this regard, time zones are comparable to ``unicode`` in Python. At first
- it's hard. You get encoding and decoding errors. Then you learn the rules.
- And some problems disappear -- you never get mangled output again when your
- application receives non-ASCII input.
- When you enable time zone support, you'll encounter some errors because
- you're using naive datetimes where Django expects aware datetimes. Such
- errors show up when running tests and they're easy to fix. You'll quickly
- learn how to avoid invalid operations.
- On the other hand, bugs caused by the lack of time zone support are much
- harder to prevent, diagnose and fix. Anything that involves scheduled tasks
- or datetime arithmetic is a candidate for subtle bugs that will bite you
- only once or twice a year.
- For these reasons, time zone support is enabled by default in new projects,
- and you should keep it unless you have a very good reason not to.
- 2. **I've enabled time zone support. Am I safe?**
- Maybe. You're better protected from DST-related bugs, but you can still
- shoot yourself in the foot by carelessly turning naive datetimes into aware
- datetimes, and vice-versa.
- If your application connects to other systems -- for instance, if it queries
- a Web service -- make sure datetimes are properly specified. To transmit
- datetimes safely, their representation should include the UTC offset, or
- their values should be in UTC (or both!).
- Finally, our calendar system contains interesting traps for computers::
- >>> import datetime
- >>> def one_year_before(value): # DON'T DO THAT!
- ... return value.replace(year=value.year - 1)
- >>> one_year_before(datetime.datetime(2012, 3, 1, 10, 0))
- datetime.datetime(2011, 3, 1, 10, 0)
- >>> one_year_before(datetime.datetime(2012, 2, 29, 10, 0))
- Traceback (most recent call last):
- ...
- ValueError: day is out of range for month
- (To implement this function, you must decide whether 2012-02-29 minus
- one year is 2011-02-28 or 2011-03-01, which depends on your business
- requirements.)
- 3. **Should I install pytz?**
- Yes. Django has a policy of not requiring external dependencies, and for
- this reason pytz_ is optional. However, it's much safer to install it.
- As soon as you activate time zone support, Django needs a definition of the
- default time zone. When pytz is available, Django loads this definition
- from the `tz database`_. This is the most accurate solution. Otherwise, it
- relies on the difference between local time and UTC, as reported by the
- operating system, to compute conversions. This is less reliable, especially
- around DST transitions.
- Furthermore, if you want to support users in more than one time zone, pytz
- is the reference for time zone definitions.
- Troubleshooting
- ---------------
- 1. **My application crashes with** ``TypeError: can't compare offset-naive``
- ``and offset-aware datetimes`` **-- what's wrong?**
- Let's reproduce this error by comparing a naive and an aware datetime::
- >>> import datetime
- >>> from django.utils import timezone
- >>> naive = datetime.datetime.utcnow()
- >>> aware = timezone.now()
- >>> naive == aware
- Traceback (most recent call last):
- ...
- TypeError: can't compare offset-naive and offset-aware datetimes
- If you encounter this error, most likely your code is comparing these two
- things:
- - a datetime provided by Django -- for instance, a value read from a form or
- a model field. Since you enabled time zone support, it's aware.
- - a datetime generated by your code, which is naive (or you wouldn't be
- reading this).
- Generally, the correct solution is to change your code to use an aware
- datetime instead.
- If you're writing a pluggable application that's expected to work
- independently of the value of :setting:`USE_TZ`, you may find
- :func:`django.utils.timezone.now` useful. This function returns the current
- date and time as a naive datetime when ``USE_TZ = False`` and as an aware
- datetime when ``USE_TZ = True``. You can add or subtract
- :class:`datetime.timedelta` as needed.
- 2. **I see lots of** ``RuntimeWarning: DateTimeField received a naive
- datetime`` ``(YYYY-MM-DD HH:MM:SS)`` ``while time zone support is active``
- **-- is that bad?**
- When time zone support is enabled, the database layer expects to receive
- only aware datetimes from your code. This warning occurs when it receives a
- naive datetime. This indicates that you haven't finished porting your code
- for time zone support. Please refer to the :ref:`migration guide
- <time-zones-migration-guide>` for tips on this process.
- In the meantime, for backwards compatibility, the datetime is considered to
- be in the default time zone, which is generally what you expect.
- 3. ``now.date()`` **is yesterday! (or tomorrow)**
- If you've always used naive datetimes, you probably believe that you can
- convert a datetime to a date by calling its :meth:`~datetime.datetime.date`
- method. You also consider that a :class:`~datetime.date` is a lot like a
- :class:`~datetime.datetime`, except that it's less accurate.
- None of this is true in a time zone aware environment::
- >>> import datetime
- >>> import pytz
- >>> paris_tz = pytz.timezone("Europe/Paris")
- >>> new_york_tz = pytz.timezone("America/New_York")
- >>> paris = paris_tz.localize(datetime.datetime(2012, 3, 3, 1, 30))
- # This is the correct way to convert between time zones with pytz.
- >>> new_york = new_york_tz.normalize(paris.astimezone(new_york_tz))
- >>> paris == new_york, paris.date() == new_york.date()
- (True, False)
- >>> paris - new_york, paris.date() - new_york.date()
- (datetime.timedelta(0), datetime.timedelta(1))
- >>> paris
- datetime.datetime(2012, 3, 3, 1, 30, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
- >>> new_york
- datetime.datetime(2012, 3, 2, 19, 30, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
- As this example shows, the same datetime has a different date, depending on
- the time zone in which it is represented. But the real problem is more
- fundamental.
- A datetime represents a **point in time**. It's absolute: it doesn't depend
- on anything. On the contrary, a date is a **calendaring concept**. It's a
- period of time whose bounds depend on the time zone in which the date is
- considered. As you can see, these two concepts are fundamentally different,
- and converting a datetime to a date isn't a deterministic operation.
- What does this mean in practice?
- Generally, you should avoid converting a :class:`~datetime.datetime` to
- :class:`~datetime.date`. For instance, you can use the :tfilter:`date`
- template filter to only show the date part of a datetime. This filter will
- convert the datetime into the current time zone before formatting it,
- ensuring the results appear correctly.
- If you really need to do the conversion yourself, you must ensure the
- datetime is converted to the appropriate time zone first. Usually, this
- will be the current timezone::
- >>> from django.utils import timezone
- >>> timezone.activate(pytz.timezone("Asia/Singapore"))
- # For this example, we just set the time zone to Singapore, but here's how
- # you would obtain the current time zone in the general case.
- >>> current_tz = timezone.get_current_timezone()
- # Again, this is the correct way to convert between time zones with pytz.
- >>> local = current_tz.normalize(paris.astimezone(current_tz))
- >>> local
- datetime.datetime(2012, 3, 3, 8, 30, tzinfo=<DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>)
- >>> local.date()
- datetime.date(2012, 3, 3)
- 4. **I get an error** "``Are time zone definitions for your database and pytz
- installed?``" **pytz is installed, so I guess the problem is my database?**
- If you are using MySQL, see the :ref:`mysql-time-zone-definitions` section
- of the MySQL notes for instructions on loading time zone definitions.
- Usage
- -----
- 1. **I have a string** ``"2012-02-21 10:28:45"`` **and I know it's in the**
- ``"Europe/Helsinki"`` **time zone. How do I turn that into an aware
- datetime?**
- This is exactly what pytz_ is for.
- >>> from django.utils.dateparse import parse_datetime
- >>> naive = parse_datetime("2012-02-21 10:28:45")
- >>> import pytz
- >>> pytz.timezone("Europe/Helsinki").localize(naive, is_dst=None)
- datetime.datetime(2012, 2, 21, 10, 28, 45, tzinfo=<DstTzInfo 'Europe/Helsinki' EET+2:00:00 STD>)
- Note that ``localize`` is a pytz extension to the :class:`~datetime.tzinfo`
- API. Also, you may want to catch ``pytz.InvalidTimeError``. The
- documentation of pytz contains `more examples`_. You should review it
- before attempting to manipulate aware datetimes.
- 2. **How can I obtain the local time in the current time zone?**
- Well, the first question is, do you really need to?
- You should only use local time when you're interacting with humans, and the
- template layer provides :ref:`filters and tags <time-zones-in-templates>`
- to convert datetimes to the time zone of your choice.
- Furthermore, Python knows how to compare aware datetimes, taking into
- account UTC offsets when necessary. It's much easier (and possibly faster)
- to write all your model and view code in UTC. So, in most circumstances,
- the datetime in UTC returned by :func:`django.utils.timezone.now` will be
- sufficient.
- For the sake of completeness, though, if you really want the local time
- in the current time zone, here's how you can obtain it::
- >>> from django.utils import timezone
- >>> timezone.localtime(timezone.now())
- datetime.datetime(2012, 3, 3, 20, 10, 53, 873365, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
- In this example, pytz_ is installed and the current time zone is
- ``"Europe/Paris"``.
- 3. **How can I see all available time zones?**
- pytz_ provides helpers_, including a list of current time zones and a list
- of all available time zones -- some of which are only of historical
- interest.
- .. _pytz: http://pytz.sourceforge.net/
- .. _more examples: http://pytz.sourceforge.net/#example-usage
- .. _these issues: http://pytz.sourceforge.net/#problems-with-localtime
- .. _helpers: http://pytz.sourceforge.net/#helpers
- .. _tz database: http://en.wikipedia.org/wiki/Tz_database
|