5

EDITED: I want to convert a UTC time in my country UTC (spain). I am using the module pytz to do the conversion but the result I am getting is UTC-1 rather than the UTC+1. This is my code:

import datetime
import pytz

madrid = pytz.timezone("Europe/Madrid")
UTC_time = datetime.datetime.strptime("2019-03-01 14:45","%Y-%m-%d %H:%M")
madrid_dt = madrid.localize(UTC_time, is_dst=None)
MadridTime = madrid_dt.astimezone(pytz.utc).strftime ("%Y-%m-%d %H:%M")

And this is the output:

UTC_Time: 2019-03-01 14:45:00
MadridTime: 2019-03-01 13:45

I need that MadridTime returns 15:45 instead 13:45. What am I doing wrong?

EDITED2: With your help I saw that I was confusing the use of localize and astimeszone. Now I am facing two new issues. This is the new code:

import datetime
import pytz

dt = datetime.datetime.strptime('2019-03-01 14:45','%Y-%m-%d %H:%M')

madrid_tz = pytz.timezone('Europe/Madrid')
madrid = dt.astimezone(madrid_tz)

print(madrid)
# 2019-03-01 14:45:00+01:00

print(madrid.strftime ("%Y-%m-%d %H:%M"))
# 2019-03-01 14:45

Issue 1: Running this code in Windows 10, Python3, the output I expected was 2019-03-01 15:45:00 rather than 2019-03-01 14:45:00+01:00. I tried to format it with strftime ("%Y-%m-%d %H:%M")but that didn't make the trick.

Issue 2: Running this code in Raspberrypi (which is where I will run the code when is finished), Python3, I get a ValueError in this line madrid = dt.astimezone(madrid_tz). The error is ValueError: astimezone() cannot be applied to a naive datetime

Any ideas?

Dani LA
  • 107
  • 1
  • 7

2 Answers2

4

Let's make it a little clearer what's what here:

madrid = pytz.timezone('Europe/Madrid')

The timezone Europe/Madrid, which is UTC+1/+2.

naive_ts = datetime.strptime('2019-03-01 14:45', '%Y-%m-%d %H:%M')

A naïve timestamp without any particular timezone.

madrid_ts = madrid.localize(naive_ts)

The same timestamp, now with the timezone Europe/Madrid attached, i.e. 14:45 in Madrid (UTC+1).

utc_ts = madrid_ts.astimezone(pytz.utc)

The same time as 14:45 in Madrid (UTC+1) in UTC, so, 14:45 - 1 hour → 13:45. All as expected. If it's 14:45 in Madrid, it's 13:45 in UTC, because Madrid is one hour ahead of UTC.

datetime.now()

Whatever that is… it has nothing to do with any of the two timestamps above, and depends on the default timezone of your machine and the current time there when you execute this code.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • Hi @deceze, I think the error is in my code, I just edited my question to clarify what I need. – Dani LA Mar 01 '19 at 17:29
  • 1
    Then understand the difference between a *naïve* datetime (without timezone, ambiguous information) and an *aware* one (one with timezone information). Your `localize` attaches a timezone to a naïve datetime, which you then convert to a different timezone. If you want to convert from UTC to Madrid, you need to do it the other way around. – deceze Mar 01 '19 at 18:54
1

I think you are misunderstanding localize and astimezone, because you are creating your 2019-03-01 14:45 datetime object in the Europe/Madrid time zone with localize and then converting it to UTC with astimezone which is giving you the unexpected result.

Instead, it seems that you mean to be creating a datetime object for 2019-03-01 14:45 and then you want to display that datetime in Europe/Madrid time and UTC time. You can use either astimezone or localize to get the desired result.

astimezone example:

import datetime
import pytz

dt = datetime.datetime.strptime('2019-03-01 14:45','%Y-%m-%d %H:%M')

madrid_tz = pytz.timezone('Europe/Madrid')
madrid = dt.astimezone(madrid_tz)
print(madrid)
# 2019-03-01 15:45:00+01:00

utc = dt.astimezone(pytz.utc)
print(utc)
# 2019-03-01 14:45:00+00:00

localize example (note that the datetime objects are created in the time that corresponds to each time zone, so that both will represent the same point in time):

import datetime
import pytz

madrid_tz = pytz.timezone('Europe/Madrid')
madrid = madrid_tz.localize(datetime.datetime(2019, 3, 1, 15, 45))
print(madrid)
# 2019-03-01 15:45:00+01:00

utc = pytz.utc.localize(datetime.datetime(2019, 3, 1, 14, 45))
print(utc)
# 2019-03-01 14:45:00+00:00
benvc
  • 14,448
  • 4
  • 33
  • 54
  • Thanks for your aclaration!. But how can I get just 15:45 instead of 14:15 + 01:00?? – Dani LA Mar 01 '19 at 20:28
  • @DaniLA - you can use `strftime` to format the output however you like. – benvc Mar 01 '19 at 20:29
  • How? If I do `madrid = dt.astimezone(madrid_tz) print(madrid)` I get `2019-03-01 14:45:00+01:00` and if I do `print(madrid.strftime ("%Y-%m-%d %H:%M")` I get 2019-03-01 14:45 – Dani LA Mar 01 '19 at 20:33
  • @DaniLA - how are you initializing `dt`? If you were doing it the same way as shown in the answer, you would not get 2019-03-01 14:45:00+01:00 from `print(madrid)` – benvc Mar 01 '19 at 20:55
  • I just copy pasted your "astimezone example" but my outputs are different than yours. Mine are 2019-03-01 14:45:00+01:00 and 2019-03-01 13:45:00+00:00 . I must say that I am testing this in python3 in windows. If I execute your example of astimezone in my raspberrypi, also in python3, I get an error like `ValueError: astimezone() cannot be applied to a naive datetime` when executing `madrid = dt.astimezone(madrid_tz)` . I am so confused... – Dani LA Mar 02 '19 at 09:09
  • @DaniLA - maybe add an edit to the bottom of your question that includes the code you are attempting now along with the output you are getting, so we can see the context of your errors. – benvc Mar 02 '19 at 23:25