-1

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.

CMR
  • 1,366
  • 4
  • 15
  • 31
  • The entire approach is flawed from the beginning, but particularly this bit is a pitfall: you get the offset for `datetime.now(user_timezone)`, but the offset may be something different at the actual time of the event, due to DST! At the very least you'd need to get the offset for the event time. But again, the `datetime` API abstracts that from you and you don't need to think about offsets at all if you use it correctly. – deceze Jun 24 '20 at 12:15

1 Answers1

3

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)
deceze
  • 510,633
  • 85
  • 743
  • 889
  • Hi, that seems to go in the wrong way for the adjustment. It gives me 7PM UTC time instead of 9PM. – CMR Jun 24 '20 at 12:10
  • 8pm Europe/London ***is*** 7pm UTC. – deceze Jun 24 '20 at 12:11
  • oh yeah, sorry. its confusing working with all these timezones – CMR Jun 24 '20 at 12:12
  • It helps to always visualise the globe and how the sun moves east to west. It's a bit annoying with London in particular being in the same "location" as UTC, but for any other cities it helps. – deceze Jun 24 '20 at 12:18