0

I would like to convert local times to UTC tine for different countries. I'm trying to do that with this way:

tz = pytz.timezone('Europe/Berlin')
x=tz.normalize(tz.localize(datetime.now())).astimezone(pytz.utc)

It gives me right result. But when I try to do that for Europe/Lisbon, I get wrong result. Can it be a problem or am I doing something wrong? There is no difference between two time zones but it gives me 3 hours difference as below.

enter image description here

Thanks in advance.

berkayln
  • 935
  • 1
  • 8
  • 14
  • 1
    your local machine timezone is `Europe/Lisbon` right? – P S Solanki Jan 05 '22 at 14:34
  • 1
    Can you please replace the image with ``code`` formatted text? Expanding the code itself to a full [mre], with all imports and a fixed reference time, would improve the re-usability of this question as well. – MisterMiyagi Jan 05 '22 at 14:35
  • 1
    @PSSolanki no actually, I have a data from Lisbon and I would like to convert it to UTC. My timezone is Europe/İstanbul. – berkayln Jan 05 '22 at 14:39
  • where do you get that data from? and why are you using `datetime.now()` for the test while you should be using the sample datetime, right? – P S Solanki Jan 05 '22 at 14:40
  • I have searched but I couldn't find another way. astimezone function convert it to utc I guess. – berkayln Jan 05 '22 at 14:42
  • Does this answer your question? [Display the time in a different time zone](https://stackoverflow.com/questions/1398674/display-the-time-in-a-different-time-zone) – FObersteiner Jan 05 '22 at 14:48
  • wait doesn't `Europe/Lisbon` fall in GMT+0, so it's always just going to be same as UTC? (except maybe DST) – P S Solanki Jan 05 '22 at 14:50

2 Answers2

1

I am not sure why you get the wrong times. I tried this way and I get the right ones. It's just that I have frozen the current time to a variable and used it to check as a debug. Lisbon has the time as UTC - no difference P.S. I am in local time zone though, and hence you may see my time as different from yours but the difference seems to be right. Berlin is 1 hour ahead of UTC while Lisbon is same as UTC

import pytz
from datetime import datetime

tz = pytz.timezone('Europe/Berlin')
tb = tz.localize(datetime.now())
print(f"Berlin Time:   {tb}")
x=tz.normalize(tb).astimezone(pytz.utc)
print(f"Berin to UTC:   {x}")

tz2 = pytz.timezone('Europe/Lisbon')
tl = tz2.localize(datetime.now())
print(f"Lisbon Time:   {tl}")
y=tz2.normalize(tl).astimezone(pytz.utc)
print(f"Lisbon to UTC:   {tl}")

Here is the result:

Berlin Time:   2022-01-05 20:19:28.576504+01:00
Berin to UTC:   2022-01-05 19:19:28.576504+00:00
Lisbon Time:   2022-01-05 20:19:28.578506+00:00
Lisbon to UTC:   2022-01-05 20:19:28.578506+00:00

Process finished with exit code 0
Anand Gautam
  • 2,018
  • 1
  • 3
  • 8
  • Note that you do not need a call to `normalize`. astimezone should be enough. – P S Solanki Jan 05 '22 at 15:07
  • You also do not need to localize here; directly `datetime.now(pytz.timezone('Europe/Berlin'))` – FObersteiner Jan 05 '22 at 17:33
  • @MrFuppes actually using `localize` is preferred over specifying the timezone directly in the constructor. Reason is there are some timezones which will have incorrect values when it's done that way. `Asia/Kolkata` is an example. – P S Solanki Jan 06 '22 at 09:16
  • 1
    @PSSolanki actually, you *must* use `localize` (with the [outdated pytz](https://pypi.org/project/pytz-deprecation-shim/)) if the datetime object already exists - *unless* you use the `datetime.now` constructor or conversion with `astimezone` or tzinfo is UTC. Setting the tz directly in `now` just seems more readable to me. – FObersteiner Jan 06 '22 at 09:43
  • @MrFuppes it sure is readable but it gives incorrect values for some timezones. i noticed this behavior for `Asia/Kolkata` using `datetime.datetime.now` and specifying tzinfo within the constructor. This was like 2 months ago. i also remember seeing many tickets on pytz mailing lists on this topic. It had something to do with how some timezones changed their offset. For eg, `Asia/Kolkata` had a different offset than it does now and that results in an incorrect value. – P S Solanki Jan 06 '22 at 09:54
  • @PSSolanki sounds interesting ;-) Is this a pytz issue? Does it work with a timezone object from [zoneinfo](https://docs.python.org/3/library/zoneinfo.html) (passed to datetime.now)? – FObersteiner Jan 06 '22 at 10:23
  • yes, it was a pytz issue and it was very troublesome. They had to add a warning to the docs. There are a few very high voted answers on SO itself addressing those issue. I don't have the links to them unfortunately. I was looking at these a couple months ago – P S Solanki Jan 06 '22 at 10:29
0

This should work well for converting your local time to a timezone aware UTC datetime object

I'm guessing you might have issues with DST. The call to localize() requires you to specify if the timezone is serving DST or not. It defaults to False.

Other possibility is simply the fact that you're using your local times (considering you're not yourself in lisbon) and since you localize that time to lisbon timezone, of course it would result in incorrect time.

import pytz
import datetime


timezone = pytz.timezone('Europe/Lisbon')

original_time = datetime.datetime(2021, 10, 15, 13, 15)  # change this to sample datetime to test different values

local_timezone_datetime = timezone.localize(original_time, False)  # change False to True if DST is enabled on the timezone

converted_datetime = local_timezone_datetime.astimezone(pytz.utc)

print(converted_datetime)

Lemme know if you need a function to help you determine whether a timezone is serving DST.

P S Solanki
  • 1,033
  • 2
  • 11
  • 26
  • I think DST True/False only works for ambiguous times during DST transitions, you can't "enable" or "disable" DST for a tz; DST on/off is determined by the tz rules definition. – FObersteiner Jan 05 '22 at 17:36
  • @MrFuppes i'm not sure what you meant by the statement there. DST on/off is a phenomena. Mind elaborating? – P S Solanki Jan 06 '22 at 09:15
  • 1
    Sorry that comment can seem a bit out of context ;-) It refers to the usage of the DST keyword in `.localize(original_time, False)` - I mean the kwarg has no effect if the date/time is unambiguous, i.e. it is clear from the time zone rules if DST is active or not at that point in time. The keyword setting only has an effect on (UTC) date/times that could refer to multiple wall times in a given time zone. – FObersteiner Jan 06 '22 at 09:38
  • interesting. I use a function to determine if a timezone is having DST or not and pass that value around to the kwarg. – P S Solanki Jan 06 '22 at 09:55
  • you really should not have to do that. thats what time zone rules are for, and a library like pytz should use those correctly. – FObersteiner Jan 06 '22 at 10:22
  • [This](https://pastebin.com/5WtXy0Gq) is the function i use for DST check. do you think it's not needed? @MrFuppes – P S Solanki Jan 06 '22 at 10:26
  • You can check if DST is active or not, but you don't have to adjust anything (like UTC offset). That's what the library like pytz, dateutil or zoneinfo (Py3.9) do for you: they look up tz rules and do the adjustment. – FObersteiner Jan 06 '22 at 10:39
  • oh i know that. also i'm on 3.8. I don't adjust offsets myself at all. – P S Solanki Jan 06 '22 at 12:24