Search code examples
pythontimezonetimezone-offsetpytz

pytz giving wrong timezone offset for 'Africa/Khartoum'


I have the following code

import datetime
import pytz

tz_offset = datetime.datetime.now(pytz.timezone('Africa/Khartoum' or 'GMT')).strftime('%z')
print(tz_offset)

The expected output is "+0200" but it gives "+0300".

Since pytz gets its info from IANA, I contacted them and they said it is correctly set in their database. Here is their email reply:

On 6/19/20 10:40 AM, Ubay Abdelgadir wrote:

Khartoum's time zone is +2 since 1/Nov/2017. I think it is wrong in the IANA database:

Zone Africa/Khartoum 2:10:08 - LMT 1931
    2:00 Sudan CA%sT 2000 Jan 15 12:00
    3:00 - EAT 2017 Nov  1
    2:00 - CAT

That data entry says that Africa/Khartoum has been +02 since 2017 Nov 1, so it appears to agree .with your statement that Khartoum's time zone is +2 since 1/Nov/2017.

Edit

I solved this by updating pytz version, it was 2016.7 which is outdated for my case (change happened in 2017)


Solution

  • I cannot reproduce the example for datetime.datetime.now. pytz also shows the correct UTC offset change in 2017 for the timezone 'Africa/Khartoum'. However, you need to use the localize method (see e.g. here).

    import datetime
    import pytz
    
    tz = pytz.timezone('Africa/Khartoum')
    
    # correct UTC offset for "now":
    tz_offset = tz.localize(datetime.datetime.now()).strftime('%z')
    print(tz_offset)
    # +0200
    
    # also correct UTC offset around 1st Nov 2017:
    tz_offset = tz.localize(datetime.datetime(2017,10,31)).strftime('%z')
    print(tz_offset)
    # +0300
    tz_offset = tz.localize(datetime.datetime(2017,11,1)).strftime('%z')
    print(tz_offset)
    # +0200
    

    If you don't localize, you only get the local mean time. With dateutil, you would not have to localize and could implement the timezone directly:

    import dateutil
    tz = dateutil.tz.gettz('Africa/Khartoum')
    tz_offset = datetime.datetime(2017,10,31, tzinfo=tz).strftime('%z')
    print(tz_offset)
    # +0300
    tz_offset = datetime.datetime(2017,11,1, tzinfo=tz).strftime('%z')
    print(tz_offset)
    # +0200