How to Get a Value of Datetime.Today() in Python That Is "Timezone Aware"

How do I get a value of datetime.today() in Python that is timezone aware?

In the standard library, there is no cross-platform way to create aware timezones without creating your own timezone class. (Edit: Python 3.9 introduces zoneinfo in the standard library which does provide this functionality.)

On Windows, there's win32timezone.utcnow(), but that's part of pywin32. I would rather suggest to use the pytz library, which has a constantly updated database of most timezones.

Working with local timezones can be very tricky (see "Further reading" links below), so you may rather want to use UTC throughout your application, especially for arithmetic operations like calculating the difference between two time points.

You can get the current date/time like so:

import pytz
from datetime import datetime
datetime.utcnow().replace(tzinfo=pytz.utc)

Mind that datetime.today() and datetime.now() return the local time, not the UTC time, so applying .replace(tzinfo=pytz.utc) to them would not be correct.

Another nice way to do it is:

datetime.now(pytz.utc)

which is a bit shorter and does the same.


Further reading/watching why to prefer UTC in many cases:

  • pytz documentation
  • What Every Developer Should Know About Time – development hints for many real-life use cases
  • The Problem with Time & Timezones - Computerphile – funny, eye-opening explanation about the complexity of working with timezones (video)

How to make a timezone aware datetime object

In general, to make a naive datetime timezone-aware, use the localize method:

import datetime
import pytz

unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0)
aware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0, pytz.UTC)

now_aware = pytz.utc.localize(unaware)
assert aware == now_aware

For the UTC timezone, it is not really necessary to use localize since there is no daylight savings time calculation to handle:

now_aware = unaware.replace(tzinfo=pytz.UTC)

works. (.replace returns a new datetime; it does not modify unaware.)

Python datetime.now() with timezone

If you are using Python 3.2 or newer, you need to create a datetime.timezone() object; it takes an offset as a datetime.timedelta():

from datetime import datetime, timezone, timedelta

timezone_offset = -8.0 # Pacific Standard Time (UTC−08:00)
tzinfo = timezone(timedelta(hours=timezone_offset))
datetime.now(tzinfo)

For earlier Python versions, it'll be easiest to use an external library to define a timezone object for you.

The dateutil library includes objects to take a numerical offset to create a timezone object:

from dateutil.tz import tzoffset

timezone_offset = -8.0 # Pacific Standard Time (UTC−08:00)
tzinfo = tzoffset(None, timezone_offset * 3600) # offset in seconds
datetime.now(tzinfo)

Why does datetime.datetime.utcnow() not contain timezone information?

That means it is timezone naive, so you can't use it with datetime.astimezone

you can give it a timezone like this

import pytz  # 3rd party: $ pip install pytz

u = datetime.utcnow()
u = u.replace(tzinfo=pytz.utc) #NOTE: it works only with a fixed utc offset

now you can change timezones

print(u.astimezone(pytz.timezone("America/New_York")))

To get the current time in a given timezone, you could pass tzinfo to datetime.now() directly:

#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz

print(datetime.now(pytz.timezone("America/New_York")))

It works for any timezone including those that observe daylight saving time (DST) i.e., it works for timezones that may have different utc offsets at different times (non-fixed utc offset). Don't use tz.localize(datetime.now()) -- it may fail during end-of-DST transition when the local time is ambiguous.

Python Datetime : use strftime() with a timezone-aware date

In addition to what @Slam has already answered:

If you want to output the UTC time without any offset, you can do

from datetime import timezone, datetime, timedelta
d = datetime(2009, 4, 19, 21, 12, tzinfo=timezone(timedelta(hours=-2)))
d.astimezone(timezone.utc).strftime('%Y-%m-%d %H:%M:%S.%f')

See datetime.astimezone in the Python docs.

Python. How to create a local datetime with datetime.today()

I'm guessing that the datetime from your frontend is in UTC. Doing a replace doesn't actually convert the datetime. It uses the data/hour/etc. and just uses a new timezone.

When you call datetime.today(), you create a naive datetime without any timezone info. When you do a replace on that, it's not actually doing a conversion either, it's just assuming the date you gave it is already in the timezone you provided, the same as the replace you did on the server time.

To actually convert datetimes to another timezone, you need to use astimezone. If the datetime from the server is also naive and doesn't specify a timezone, astimezone will error. To fix that. add a timezone of UTC first.

time_from_frontend = time_from_frontend.replace(tzinfo=pytz.timezone('UTC'))
converted_server_time = time_from_frontend.astimezone(my_timezone)

Python: Figure out local timezone

Try dateutil, which has a tzlocal type that does what you need.

How do I print a datetime in the local timezone?

Think your should look around: datetime.astimezone()

http://docs.python.org/library/datetime.html#datetime.datetime.astimezone

Also see pytz module - it's quite easy to use -- as example:

eastern = timezone('US/Eastern')

http://pytz.sourceforge.net/

Example:

from datetime import datetime
import pytz
from tzlocal import get_localzone # $ pip install tzlocal

utc_dt = datetime(2009, 7, 10, 18, 44, 59, 193982, tzinfo=pytz.utc)
print(utc_dt.astimezone(get_localzone())) # print local time
# -> 2009-07-10 14:44:59.193982-04:00


Related Topics



Leave a reply



Submit