Search code examples
pythonpython-3.xtimezonetimezone-offsetpytz

Adjusting a datetime by a given offset


python 3.8.0 (But could update to higher if neccesary)

Users in my system can set their timezone, which is stored as a string, e.g. Europe/London.

Using this, I can work out their offset compared to the server time (UTC), so for example a user who sets Europe/London, their offset is +0100

Basically what I am trying to achieve is, that when a user schedules an event to happen, they will input the date and time they want it to happen in their timezone, then I need to convert that to a UTC timestamp, so it will run at the correct time on the server.

So, as an example, here is a simplified script:

import pytz
from datetime import datetime, timezone, timedelta

server_time = datetime.today()

user_timezone_setting = 'Europe/London'
user_timezone = pytz.timezone(user_timezone_setting)
user_time = datetime.now(user_timezone)
offset = datetime.now(user_timezone).strftime('%z')

print('Server Time: ' + str(server_time.strftime('%H:%M:%S')))
print('User Timezone: ' + user_timezone_setting)
print('User Time: ' + str(user_time.strftime('%H:%M:%S')))
print('Offset to Server Time: ' + str(offset))

print()

time_to_adjust = datetime.strptime('24-06-2020 20:00', '%d-%m-%Y %H:%M')
print('Date Time to adjust by offset: ' + str(time_to_adjust))
print('Timestamp: ' + str(int(time_to_adjust.timestamp())))

print('Adding offset '+ offset + ' to the date time... Expected result (1593032400)')

adjusted = None
print('Adjusted time: ' + str(adjusted))

So firstly, we work out the offset of their timezone compared to the server time and store this in the offset variable.

Then we simulate their chosen date time for their event to schedule, in this case 24-06-2020 at 20:00. And we want that datetime in the Europe/London timezone.

So we load that datetime string into a datetime variable on the server, which is now storing that datetime in UTC (1593028800).

Then I want to basically just apply the offset to the datetime, such that I could do something along the lines of:

adjusted = time_to_adjust.adjust_by_offset(offset).timestamp()

and get the expected result of (1593032400).


Could anyone advise on how to achieve this? Thanks.


Solution

  • You're way overcomplicating that.

    user_timezone = pytz.timezone(user_timezone_setting)
    the_event = datetime.strptime('24-06-2020 20:00', '%d-%m-%Y %H:%M')  # datetime(2020, 6, 24, 20, 0)
    localized_event = user_timezone.localize(the_event)  # datetime(2020, 6, 24, 20, 0, tzinfo=<DstTzInfo 'Europe/London' BST+1:00:00 DST>)
    print(localized_event.timestamp())  # 1593025200.0
    

    That's all you need. This gives you the UNIX timestamp of the event.

    If you rather want to see the time localised to UTC:

    utc_event = localized_event.astimezone(timezone.utc)
    print(utc_event)  # datetime(2020, 6, 24, 19, 0, tzinfo=datetime.timezone.utc)