Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python datetime and tzinfo objects (changing minutes instead of hours)

I'm trying to apply a tzinfo to a datetime object.

In [1]: from datetime import datetime
In [2]: import pytz

In [3]: london = pytz.timezone("Europe/London")
In [4]: london
Out[5]: <DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>

In [6]: localized_date_object = datetime(2016, 1, 1, 11, 30, 0, 5000, london)
In [7]: localized_date_object
Out[8]: datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>)

In [9]: utc_date_object = localized_date_object.astimezone(pytz.utc)
In [10]: utc_date_object
Out[11]: datetime.datetime(2016, 1, 1, 11, 31, 0, 5000, tzinfo=<UTC>)

In [16]: paris = pytz.timezone("Europe/Paris")
In [17]: localized_date_object = datetime(2016, 1, 1, 11, 30, 0, 5000, paris)
In [18]: utc_date_object = localized_date_object.astimezone(pytz.utc)
In [19]: utc_date_object
Out[19]: datetime.datetime(2016, 1, 1, 11, 21, 0, 5000, tzinfo=<UTC>)

As you can see, it's applying delta to minutes instead of hours.
Can someone explain me what I'm doing wrong here.

like image 742
Sifnos Avatar asked Nov 22 '16 11:11

Sifnos


People also ask

How do you make datetime objects timezone aware?

Timezone aware object using datetime now(). time() function of datetime module. Then we will replace the value of the timezone in the tzinfo class of the object using the replace() function. After that convert the date value into ISO 8601 format using the isoformat() method.

What is the purpose of the Tzinfo attribute in a datetime object?

This is used to find the time zone name of the datetime object passed. It returns a Python String object.

How do I format a datetime object in Python?

Use datetime. strftime(format) to convert a datetime object into a string as per the corresponding format . The format codes are standard directives for mentioning in which format you want to represent datetime. For example, the %d-%m-%Y %H:%M:%S codes convert date to dd-mm-yyyy hh:mm:ss format.


2 Answers

The pytz docs say:

This library only supports two ways of building a localized time. The first is to use the localize() method provided by the pytz library. This is used to localize a naive datetime (datetime with no timezone information):

The second way of building a localized time is by converting an existing localized time using the standard astimezone() method:

Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.

In the code sample provided you are trying to use the tzinfo argument rather than localize()

>>> london = pytz.timezone("Europe/London")

>>> datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, london) # This is incorrect
datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>)

>>> london.localize(datetime.datetime(2016, 1, 1, 11, 30, 0, 5000)) # This is correct
datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' GMT0:00:00 STD>)
like image 121
cdmp Avatar answered Oct 03 '22 00:10

cdmp


I think that you should use CET for Paris time and UTC for London time. I am using a bit different approach but it works for me:

from datetime import datetime
from pytz import timezone

ldo = datetime(2016, 1, 1, 11, 30, 0, 5000)
ldo = ldo.replace(tzinfo=timezone('Europe/London'))

udo = ldo.astimezone(timezone('UTC'))
print ldo
print udo

ldo = datetime(2016, 1, 1, 11, 30, 0, 5000)
ldo = ldo.replace(tzinfo=timezone('CET'))

udo = ldo.astimezone(timezone('UTC'))
print ldo
print udo

UPDATE:

When you store time values there should be also stored related timezone information. IMO best practice is to store everything in UTC and convert for viewing to "user" timezone. BTW converting from UTC to Europe/Paris works flawlessly, try this:

winter = datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=timezone("UTC"))
paris =  winter.astimezone(timezone("Europe/Paris"))
print paris
# 2016-01-01 12:30:00.005000+01:00

summer = datetime(2016, 6, 1, 11, 30, 0, 5000, tzinfo=timezone("UTC"))
paris = summer.astimezone(timezone("Europe/Paris"))
print paris
# 2016-06-01 13:30:00.005000+02:00
like image 45
Jiri Avatar answered Oct 02 '22 23:10

Jiri