Search code examples
pythondatetimepsycopg2

How to convert datetime.time object coming from psycopg2 to specific time zone?


My database returns a value datetime.time(13, 0, tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=0, name=None)) that I store in my_dt_object.

How can I convert its timezone to Europe/Zurich, so that my_dt_object.strftime('%H') gives 15? (considering the current offset of +02 to UTC?

This is what I tried:

zurich = pytz.timezone("Europe/Zurich")
zurich.localize(my_dt_object)

throws: ValueError: Not naive datetime (tzinfo is already set)

zurich.localize(my_dt_object.replace(tzinfo=None))

throws: TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.timedelta'

Aaaand...

my_dt_object.replace(tzinfo=zurich).strftime('%H')

still gives

13

Solution

  • A long winded way to do this:

    import pytz
    import datetime
    
    zurich = pytz.timezone('Europe/Zurich')
    dt = datetime.datetime.utcnow()
    utc_offset = zurich.utcoffset(dt).seconds/3600 
    
    t = datetime.time(13,0,tzinfo=pytz.utc)
    t
    datetime.time(13, 0, tzinfo=<UTC>)                                                                                                                                                                                           
    
    t = t.replace(tzinfo=None)                                                                                                                                                                                              
    t                                                                                                                                                                                                                       
    datetime.time(13, 0)
    
    zurich_t = t.replace(hour=t.hour+int(utc_offset))
    
    zurich_t                                                                                                                                                                                                                
    datetime.time(15, 0)
    
    zurich_t.hour                                                                                                                                                                                                           
    15
    

    Though this would probably easier to do in the database:

    select '13:00+0'::timetz at time zone 'europe/zurich';
    timezone   
    -------------
     15:00:00+02
    
    

    This assumes the field is timetz and the TimeZone on the server is UTC.