>>> import pytz
>>> pytz.timezone('Asia/Hong_Kong')
<DstTzInfo 'Asia/Hong_Kong' LMT+7:37:00 STD>
A seven hour and 37 minute offset? This is a little strange, does anyone experience the same issue?
In fact I'm getting different behavior between
import pytz
from datetime import datetime
hk = pytz.timezone('Asia/Hong_Kong')
dt1 = datetime(2012,1,1,tzinfo=hk)
dt2 = hk.localize(datetime(2012,1,1))
if dt1 > dt2:
print "Why?"
Time zones and offsets change over the years. The default zone name and offset delivered when pytz creates a timezone object are the earliest ones available for that zone, and sometimes they can seem kind of strange. When you use localize to attach the zone to a date, the proper zone name and offset are substituted. Simply using the datetime constructor to attach the zone to the date doesn't allow it to adjust properly.
While I'm sure historic changes in timezones are a factor, passing pytz timezone object to the DateTime constructor results in odd behavior even for timezones that have experienced no changes since their inception.
import datetime
import pytz
dt = datetime.datetime(2020, 7, 15, 0, 0, tzinfo= pytz.timezone('US/Eastern'))
produces
2020-07-15 00:00:00-04:56
Creating the datetime object then localizing it produced expected results
import datetime
import pytz
dt = datetime.datetime(2020, 7, 15, 0, 0)
dt_local = timezone('US/Eastern').localize(dt)
produces
2020-07-15 00:00:00-04:00
Coming here nearly 10 years later, I think it's worth a note that we can now exclusively utilize the Python 3.9+ standard library to handle time zones, without a "localize trap".
Use the zoneinfo module to set and replace the tzinfo however you like, ex:
from datetime import datetime
from zoneinfo import ZoneInfo
hk = ZoneInfo('Asia/Hong_Kong')
print(repr(hk))
# zoneinfo.ZoneInfo(key='Asia/Hong_Kong')
dt1 = datetime(2012,1,1,tzinfo=hk)
print(dt1)
# 2012-01-01 00:00:00+08:00
there is a deprecation shim for pytz
Alternatives, if you're not able to use zoneinfo:
for Python < 3.9, there's backports.zoneinfo
you could also use dateutil, which follows the same semantics as zoneinfo
Note for pandas users:
pandas (v1.4.1) is still using pytz internally, and seems to have some trouble with ZoneInfo timezone objects
Related
Given a pair of str objects representing an ISO 8601 time and time zone:
time_str = '09:30'
time_zone_str = 'America/New_York'
How can these 2 strings be parsed into a time (not datetime) object?
Note: It's obviously possible to split the time_str by ':' and use the time constructor but then the parsing would be a little tricky to count the number of elements in the resulting list to know the resolution (minute, second, microsecond) of the str. This is because ISO 8601 allows for different representations:
time_str_short = '09:30'
time_str_long = '09:30:00'
Thank you in advance for your consideration and response.
The answer to "can I do this?" (with a timezone) is both yes and no. Firstly let's convert the string to a time object. As one commenter mentioned, you can do this in python 3.7 with the fromisoformat method:
from datetime import time
time.fromisoformat("09:30")
If you are not using 3.7, you can do this by creating a datetime and then converting to a time object:
from datetime import datetime, time
as_time = datetime.datetime.strptime("09:00", "%H:%M").time()
Now to deal with the timezone. As the timezone is a name, we can use the very convenient pytz module to convert it to a tzinfo object:
pytz.timezone('America/New_York')
At this point you're probably tempted to just pass it to the time constructor as the tzinfo argument, but unfortunately that does not work with pytz:
Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.
~ http://pytz.sourceforge.net/
So we will have to use the localize method of the newly created tzinfo object. But unfortunately we will still not be able to successfully localize the time object with this timezone. The reason for this is that pytz needs to know the date in order to determine if this timezone is in daylight savings time or not. As we have not provided the date, achieving this is quite impossible and you will get odd results like:
>>> pytz.timezone('America/New_York').localize(as_dt).isoformat()
'1900-01-01T09:00:00-04:56'
Note the -04:56 offset, which is gibberish. There are a few options for getting to what you ultimately want.
One option is to assume the time is a time today:
as_time = datetime.datetime.strptime("09:00", "%H:%M").time()
tz = pytz.timezone('America/New_York')
local_time = tz.localize(datetime.datetime.now().replace(hour=as_time.hour, minute=as_time.minute))
The other option is to use naive timezone offsets rather than timezone names:
from datetime import timezone, timedelta
naive_tz = timezone(timedelta(hours=5))
datetime.time(9, 30).replace(tz_info=naive_tz)
But I would not recommend this method as it's quite brittle and would require some intermediate steps to derive from the TZ location name that are non-trivial.
A timezone without a date is meaningless, so no, you can't use both to produce a time object. While the standard library time object does support having a tzinfo attribute, the 'timezone' object is not really a timezone, but merely a time offset.
A timezone is more than just an offset from UTC. Timezone offsets are date-dependent, and because such details as the Daylight Savings winter / summer time distinction is partly the result of political decisions, what dates the timezone offset changes is also dependent on the year.
To be explicit, America/New_York is a timezone, not a time offset. The exact offset from UTC depends on the date; it'll be minus 4 hours in summer, 5 hours in winter!
So for a timezone such as America/New_York, you need to pick a date too. If you don't care about the date, pick a fixed date so your offset is at least consistent. If you are converting a lot of time stamps, store the timezone offset once as a timedelta(), then use that timedelta to shift time() objects to the right offset.
To parse just a timestring, pretend there is a date attached by using the datetime.strptime() method, then extract the time object:
from datetime import datetime
try:
timeobject = datetime.strptime(time_str, '%H:%M').time()
except ValueError:
# input includes seconds, perhaps
timeobject = datetime.strptime(time_str, '%H:%M:%S').time()
To update the time given a timezone, get a timezone database that supports your timezone string first; the pytz library is regularly updated.
from pytz import timezone
timezone = pytz.timezone(time_zone_str)
How you use it depends on what you are trying to do. If the input time is not in UTC, you can simply attach the timezone to a datetime() object with the datetime.combine()method, after which you can move it to the UTC timezone:
dt_in_timezone = datetime.combine(datetime.now(), timeobject, timezone)
utc_timeobject = dt_in_timezone.astimezone(pytz.UTC).time()
This assumes that 'today' is good enough to determine the correct offset.
If your time is a UTC timestamp, combine it with the UTC timezone, then use the pytz timezone; effectively the reverse:
dt_in_utc = datetime.combine(datetime.now(), timeobject, pytz.UTC)
timeobject_in_timezone = dt_in_timezone.astimezone(timezone).time()
To store just the offset for bulk application, pass in a reference date to the timezone.utcoffset() method:
utc_offset = timezone.utcoffset(datetime.now())
after which you can add this to any datetime object as needed to move from UTC to local time, or subtract it to go from local to UTC. Note that I said datetime, as time objects also don't support timedelta arithmetic; a timedelta can be larger than the number of seconds left in the day or the number of seconds since midnight, after all, so adding or subtracting could shift days as well as the time:
# new time after shifting
(datetime.combine(datetime.now(), timeobject) + utc_offset).time()
For completion sake, you can't pass in a pytz timezone to a time object; it just doesn't have any effect on the time. The timezone object returns None for the UTC offset in that case, because it can't give any meaningful answer without a date:
>>> from datetime import time
>>> from pytz import timezone
>>> tz = timezone('America/New_York')
>>> time_with_zone = time(12, 34, tzinfo=tz)
>>> time_with_zone
datetime.time(12, 34, tzinfo=<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>)
>>> time_with_zone.utcoffset()
>>> time_with_zone.utcoffset() is None
True
>>> tz.utcoffset(None) is None # what time_with_zone.utcoffset() does under the hood
None
So for all intents an purposes, time_with_zone is just another naive time object as the tzinfo object attached doesn't actually have any effect.
Moreover, because there is no date to determine the correct timezone information, pytz selects the earliest known 'New York' timezone, and that's not exactly a recent one; look closely at that tzinfo representation:
tzinfo=<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>
^^^^^^^^^^^^^^^^^^^^^^^
That's the timezone introduced in 1883 by the railroads; the 'modern' EST timezone was not introduced until the 20th century. This is why timezone objects are usually passed in a date when determining the offset:
>>> tz.utcoffset(datetime(1883, 6, 28))
datetime.timedelta(-1, 68640)
>>> tz.utcoffset(datetime(1918, 6, 28))
datetime.timedelta(-1, 72000)
Hope it works for you,
import datetime
# Hello World program in Python
print "Hello World!\n"
time_str = '09:30'
time_zone_str = 'America/New_York'
s = "I am looking for a course in Paris!"
print(s)
print(datetime.datetime.strptime(time_str, '%H:%M').time())
print(datetime.time(3, 55))
Thanks
>>> import pytz
>>> pytz.timezone('Asia/Hong_Kong')
<DstTzInfo 'Asia/Hong_Kong' LMT+7:37:00 STD>
A seven hour and 37 minute offset? This is a little strange, does anyone experience the same issue?
In fact I'm getting different behavior between
import pytz
from datetime import datetime
hk = pytz.timezone('Asia/Hong_Kong')
dt1 = datetime(2012,1,1,tzinfo=hk)
dt2 = hk.localize(datetime(2012,1,1))
if dt1 > dt2:
print "Why?"
Time zones and offsets change over the years. The default zone name and offset delivered when pytz creates a timezone object are the earliest ones available for that zone, and sometimes they can seem kind of strange. When you use localize to attach the zone to a date, the proper zone name and offset are substituted. Simply using the datetime constructor to attach the zone to the date doesn't allow it to adjust properly.
While I'm sure historic changes in timezones are a factor, passing pytz timezone object to the DateTime constructor results in odd behavior even for timezones that have experienced no changes since their inception.
import datetime
import pytz
dt = datetime.datetime(2020, 7, 15, 0, 0, tzinfo= pytz.timezone('US/Eastern'))
produces
2020-07-15 00:00:00-04:56
Creating the datetime object then localizing it produced expected results
import datetime
import pytz
dt = datetime.datetime(2020, 7, 15, 0, 0)
dt_local = timezone('US/Eastern').localize(dt)
produces
2020-07-15 00:00:00-04:00
Coming here nearly 10 years later, I think it's worth a note that we can now exclusively utilize the Python 3.9+ standard library to handle time zones, without a "localize trap".
Use the zoneinfo module to set and replace the tzinfo however you like, ex:
from datetime import datetime
from zoneinfo import ZoneInfo
hk = ZoneInfo('Asia/Hong_Kong')
print(repr(hk))
# zoneinfo.ZoneInfo(key='Asia/Hong_Kong')
dt1 = datetime(2012,1,1,tzinfo=hk)
print(dt1)
# 2012-01-01 00:00:00+08:00
there is a deprecation shim for pytz
Alternatives, if you're not able to use zoneinfo:
for Python < 3.9, there's backports.zoneinfo
you could also use dateutil, which follows the same semantics as zoneinfo
Note for pandas users:
pandas (v1.4.1) is still using pytz internally, and seems to have some trouble with ZoneInfo timezone objects
Ok let me first start by saying my timezone is CET/CEST. The exact moment it changes from CEST to CET (back from DST, which is GMT+2, to normal, which GMT+1, thus) is always the last Sunday of October at 3AM. In 2010 this was 31 October 3AM.
Now note the following:
>>> import datetime
>>> import pytz.reference
>>> local_tnz = pytz.reference.LocalTimezone()
>>> local_tnz.utcoffset(datetime.datetime(2010, 10, 31, 2, 12, 30))
datetime.timedelta(0, 3600)
This is wrong as explained above.
>>> local_tnz.utcoffset(datetime.datetime(2010, 10, 30, 2, 12, 30))
datetime.timedelta(0, 7200)
>>> local_tnz.utcoffset(datetime.datetime(2010, 10, 31, 2, 12, 30))
datetime.timedelta(0, 7200)
Now it is suddenly correct :/
I know there are several questions about this already, but the solution given is always "use localize", but my problem here is that the LocalTimezone does not provide that method.
In fact, I have several timestamps in milliseconds of which I need the utcoffset of the local timezone (not just mine, but of anyone using the program). One of these is 1288483950000 or Sun Oct 31 2010 02:12:30 GMT+0200 (CEST) in my timezone.
Currently I do the following to get the datetime object:
datetime.datetime.fromtimestamp(int(int(millis)/1E3))
and this to get the utcoffset in minutes:
-int(local_tnz.utcoffset(date).total_seconds()/60)
which, unfortunately, is wrong in many occasions :(.
Any ideas?
Note: I'm using python3.2.4, not that it should matter in this case.
EDIT:
Found the solution thanks to #JamesHolderness:
def datetimeFromMillis(millis):
return pytz.utc.localize(datetime.datetime.utcfromtimestamp(int(int(millis)/1E3)))
def getTimezoneOffset(date):
return -int(date.astimezone(local_tz).utcoffset().total_seconds()/60)
With local_tz equal to tzlocal.get_localzone() from the tzlocal module.
According to Wikipedia, the transition to and from Summer Time occurs at 01:00 UTC.
At 00:12 UTC you are still in Central European Summer Time (i.e. UTC+02:00), so the local time is 02:12.
At 01:12 UTC you are back in the standard Central European Time (i.e. UTC+01:00), so the local time is again 02:12.
When changing from Summer Time back to standard time, the local time goes from 02:59 back to 02:00 and the hour repeats itself. So when asking for the UTC offset of 02:12 (local time), the answer could truthfully be either +01:00 or +02:00 - it depends which version of 02:12 you are talking about.
On further investigation of the pytz library, I think your problem may be that you shouldn't be using the pytz.reference implementation, which may not deal with these ambiguities very well. Quoting from the comments in the source code:
Reference tzinfo implementations from the Python docs.
Used for testing against as they are only correct for the years
1987 to 2006. Do not use these for real code.
Working with ambiguous times in pytz
What you should be doing is constructing a timezone object for the appropriate timezone:
import pytz
cet = pytz.timezone('CET')
Then you can use the utcoffset method to calculate the UTC offset of a date/time in that timezone.
dt = datetime.datetime(2010, 10, 31, 2, 12, 30)
offset = cet.utcoffset(dt)
Note, that the above example will throw an AmbiguousTimeError exception, because it can't tell which of the two versions of 02:12:30 you meant. Fortunately pytz will let you specify whether you want the dst version or the standard version by setting the is_dst parameter. For example:
offset = cet.utcoffset(dt, is_dst = True)
Note that it doesn't harm to set this parameter on all calls to utcoffset, even if the time wouldn't be ambiguous. According to the documentation, it is only used during DST transition ambiguous periods to resolve that ambiguity.
How to deal with timestamps
As for dealing with timestamps, it's best you store them as UTC values for as long as possible, otherwise you potentially end up throwing away valuable information. So first convert to a UTC datetime with the datetime.utcfromtimestamp method.
dt = datetime.datetime.utcfromtimestamp(1288483950)
Then use pytz to localize the time as UTC, so the timezone is attached to the datetime object.
dt = pytz.utc.localize(dt)
Finally you can convert that UTC datetime into your local timezone, and obtain the timezone offset like this:
offset = dt.astimezone(cet).utcoffset()
Note that this set of calculations will produce the correct offsets for both 1288483950 and 1288487550, even though both timestamps are represented by 02:12:30 in the CET timezone.
Determining the local timezone
If you need to use the local timezone of your computer rather than a fixed timezone, you can't do that from pytz directly. You also can't just construct a pytz.timezone object using the timezone name from time.tzname, because the names won't always be recognised by pytz.
The solution is to use the tzlocal module - its sole purpose is to provide this missing functionality in pytz. You use it like this:
import tzlocal
local_tz = tzlocal.get_localzone()
The get_localzone() function returns a pytz.timezone object, so you should be able to use that value in all the places I've used the cet variable in the examples above.
Given a timestamp in milliseconds you can get the utc offset for the local timezone using only stdlib:
#!/usr/bin/env python
from datetime import datetime
millis = 1288483950000
ts = millis * 1e-3
# local time == (utc time + utc offset)
utc_offset = datetime.fromtimestamp(ts) - datetime.utcfromtimestamp(ts)
If we ignore time around leap seconds then there is no ambiguity or non-existent times.
It supports DST and changes of the utc offset for other reasons if OS maintains a historical timezone db e.g., it should work on Ubuntu for any past/present date but might break on Windows for past dates that used different utc offset.
Here's the same using tzlocal module that should work on *nix and Win32 systems:
#!/usr/bin/env python
from datetime import datetime
from tzlocal import get_localzone # pip install tzlocal
millis = 1288483950000
ts = millis * 1e-3
local_dt = datetime.fromtimestamp(ts, get_localzone())
utc_offset = local_dt.utcoffset()
See How to convert a python utc datetime to a local datetime using only python standard library?
To get the utc offset in minutes (Python 3.2+):
from datetime import timedelta
minutes = utc_offset / timedelta(minutes=1)
Don't use pytz.reference.LocalTimezone(), it is only for tests.
import pytz, datetime
tz = timezone('CET')
tz.utcoffset(datetime.datetime.now()).total_seconds()
7200.0
I have a naive date and time in the format '2012-05-19 19:13:00' and need to store it using Django 1.4 and its timezone-aware abilities.
Although there is no way of knowing what timezone the date is originally in, it seems to make sense to store it as if it were UTC.
However, using pytz etc, I'm not sure how to convert a date that has no timezone into a UTC datetime.
If it has no tzinfo then of course there can be no conversion to UTC. Instead you could just make the datetime object into an time-zone aware one:
import datetime
from pytz import UTC
dt = datetime.datetime.now() # just some date
tz_aware_dt = dt.replace(tzinfo=UTC)
Edit:
The migration guide for django 1.4 uses this to accomplish the above:
>>> from django.utils.dateparse import parse_datetime
>>> naive = parse_datetime("2012-02-21 10:28:45")
>>> import pytz
>>> pytz.timezone("Europe/Helsinki").localize(naive)
datetime.datetime(2012, 2, 21, 10, 28, 45, tzinfo=<DstTzInfo 'Europe/Helsinki' EET+2:00:00 STD>)
You should probably use that version, substituting "Europe/Helsinki" for "UTC".
I am trying to subtract one date value from the value of datetime.datetime.today() to calculate how long ago something was. But it complains:
TypeError: can't subtract offset-naive and offset-aware datetimes
The return value from datetime.datetime.today() doesn't seem to be "timezone aware", while my other date value is. How do I get a return value from datetime.datetime.today() that is timezone aware?
The ideal solution would be for it to automatically know the timezone.
Right now, it's giving me the time in local time, which happens to be PST, i.e. UTC - 8 hours. Worst case, is there a way I can manually enter a timezone value into the datetime object returned by datetime.datetime.today() and set it to UTC-8?
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)
Get the current time, in a specific timezone:
import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))
Remember to install pytz first.
In Python 3.2+: datetime.timezone.utc:
The standard library makes it much easier to specify UTC as the time zone:
>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2020, 11, 27, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)
You can also get a datetime that includes the local time offset using astimezone:
>>> datetime.datetime.now(datetime.timezone.utc).astimezone()
datetime.datetime(2020, 11, 27, 15, 34, 34, 74823, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600), 'CET'))
(In Python 3.6+, you can shorten the last line to: datetime.datetime.now().astimezone())
If you want a solution that uses only the standard library and that works in both Python 2 and Python 3, see jfs' answer.
In Python 3.9+: zoneinfo to use the IANA time zone database:
In Python 3.9, you can specify particular time zones using the standard library, using zoneinfo, like this:
>>> from zoneinfo import ZoneInfo
>>> datetime.datetime.now(ZoneInfo("America/Los_Angeles"))
datetime.datetime(2020, 11, 27, 6, 34, 34, 74823, tzinfo=zoneinfo.ZoneInfo(key='America/Los_Angeles'))
zoneinfo gets its database of time zones from the operating system, or from the first-party PyPI package tzdata if available.
A one-liner using only the standard library works starting with Python 3.3. You can get a local timezone aware datetime object using astimezone (as suggested by johnchen902):
from datetime import datetime, timezone
aware_local_now = datetime.now(timezone.utc).astimezone()
print(aware_local_now)
# 2020-03-03 09:51:38.570162+01:00
print(repr(aware_local_now))
# datetime.datetime(2020, 3, 3, 9, 51, 38, 570162, tzinfo=datetime.timezone(datetime.timedelta(0, 3600), 'CET'))
Here's a stdlib solution that works on both Python 2 and 3:
from datetime import datetime
now = datetime.now(utc) # Timezone-aware datetime.utcnow()
today = datetime(now.year, now.month, now.day, tzinfo=utc) # Midnight
where today is an aware datetime instance representing the beginning of the day (midnight) in UTC and utc is a tzinfo object (example from the documentation):
from datetime import tzinfo, timedelta
ZERO = timedelta(0)
class UTC(tzinfo):
def utcoffset(self, dt):
return ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return ZERO
utc = UTC()
Related: performance comparison of several ways to get midnight (start of a day) for a given UTC time.
Note: it is more complex, to get midnight for a time zone with a non-fixed UTC offset.
Another method to construct time zone aware datetime object representing current time:
import datetime
import pytz
pytz.utc.localize( datetime.datetime.utcnow() )
You can install pytz from PyPI by running:
$ pipenv install pytz
Use dateutil as described in Python datetime.datetime.now() that is timezone aware:
from dateutil.tz import tzlocal
# Get the current date/time with the timezone.
now = datetime.datetime.now(tzlocal())
If you are using Django, you can set dates non-tz aware (only UTC).
Comment the following line in settings.py:
USE_TZ = True
Here is one way to generate it with the stdlib:
import time
from datetime import datetime
FORMAT='%Y-%m-%dT%H:%M:%S%z'
date=datetime.strptime(time.strftime(FORMAT, time.localtime()),FORMAT)
date will store the local date and the offset from UTC, not the date at UTC timezone, so you can use this solution if you need to identify which timezone the date is generated at. In this example and in my local timezone:
date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))
date.tzname()
'UTC+02:00'
The key is adding the %z directive to the representation FORMAT, to indicate the UTC offset of the generated time struct. Other representation formats can be consulted in the datetime module docs
If you need the date at the UTC timezone, you can replace time.localtime() with time.gmtime()
date=datetime.strptime(time.strftime(FORMAT, time.gmtime()),FORMAT)
date
datetime.datetime(2017, 8, 1, 10, 23, 51, tzinfo=datetime.timezone.utc)
date.tzname()
'UTC'
Edit
This works only on python3. The z directive is not available on python 2 _strptime.py code
It should be emphasized that since Python 3.6, you only need the standard lib to get a timezone aware datetime object that represents local time (the setting of your OS). Using astimezone()
import datetime
datetime.datetime(2010, 12, 25, 10, 59).astimezone()
# e.g.
# datetime.datetime(2010, 12, 25, 10, 59, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600), 'Mitteleuropäische Zeit'))
datetime.datetime(2010, 12, 25, 12, 59).astimezone().isoformat()
# e.g.
# '2010-12-25T12:59:00+01:00'
# I'm on CET/CEST
(see #johnchen902's comment).
Note there's a small caveat though, don't expect any "DST-awareness" from a timedelta timezone.
pytz is a Python library that allows accurate and cross platform timezone calculations using Python 2.3 or higher.
With the stdlib, this is not possible.
See a similar question on SO.
Here is a solution using a readable timezone and that works with today():
from pytz import timezone
datetime.now(timezone('Europe/Berlin'))
datetime.now(timezone('Europe/Berlin')).today()
You can list all timezones as follows:
import pytz
pytz.all_timezones
pytz.common_timezones # or
Getting a timezone-aware date in utc timezone is enough for date subtraction to work.
But if you want a timezone-aware date in your current time zone, tzlocal is the way to go:
from tzlocal import get_localzone # pip install tzlocal
from datetime import datetime
datetime.now(get_localzone())
PS dateutil has a similar function (dateutil.tz.tzlocal). But inspite of sharing the name it has a completely different code base, which as noted by J.F. Sebastian can give wrong results.
Another alternative, in my mind a better one, is using Pendulum instead of pytz. Consider the following simple code:
>>> import pendulum
>>> dt = pendulum.now().to_iso8601_string()
>>> print (dt)
2018-03-27T13:59:49+03:00
>>>
To install Pendulum and see their documentation, go here. It have tons of options (like simple ISO8601, RFC3339 and many others format support), better performance and tend to yield simpler code.
Especially for non-UTC timezones:
The only timezone that has its own method is timezone.utc, but you can fudge a timezone with any UTC offset if you need to by using timedelta & timezone, and forcing it using .replace.
In [1]: from datetime import datetime, timezone, timedelta
In [2]: def force_timezone(dt, utc_offset=0):
...: return dt.replace(tzinfo=timezone(timedelta(hours=utc_offset)))
...:
In [3]: dt = datetime(2011,8,15,8,15,12,0)
In [4]: str(dt)
Out[4]: '2011-08-15 08:15:12'
In [5]: str(force_timezone(dt, -8))
Out[5]: '2011-08-15 08:15:12-08:00'
Using timezone(timedelta(hours=n)) as the time zone is the real silver bullet here, and it has lots of other useful applications.
Tyler from 'howchoo' made a really great article that helped me get a better idea of the Datetime Objects, link below
Working with Datetime
essentially, I just added the following to the end of both my datetime objects
.replace(tzinfo=pytz.utc)
Example:
import pytz
import datetime from datetime
date = datetime.now().replace(tzinfo=pytz.utc)
If you get current time and date in python then import date and time,pytz package in python after you will get current date and time like as..
from datetime import datetime
import pytz
import time
str(datetime.strftime(datetime.now(pytz.utc),"%Y-%m-%d %H:%M:%S%t"))
Use the timezone as shown below for a timezone-aware date time. The default is UTC:
from django.utils import timezone
today = timezone.now()
try pnp_datetime, all the time been used and returned is with timezone, and will not cause any offset-naive and offset-aware issues.
>>> from pnp_datetime.pnp_datetime import Pnp_Datetime
>>>
>>> Pnp_Datetime.utcnow()
datetime.datetime(2020, 6, 5, 12, 26, 18, 958779, tzinfo=<UTC>)