Search code examples
pythondatetimeutcclock

Python - Get current UTC time. Ignore computer clock always


Does anyone have any tips to get the current UTC time, from online somewhere, and write some decent python code assuming my computer clock is always wrong?

current_datetime = datetime.datetime.utcnow() #---> assume always wrong
current_datetime = datetime.datetime.now()    #---> assume always wrong

Using '.utcnow()' or '.now()' both depend upon the accuracy of my computer clock. I want to write the code assuming that if it runs from a computer with a bad clock, it still gets the correct time.

BACKGROUND:

I am trying to retool my code to entirely live in UTC time. My use case is to do some time series analysis. I keep finding myself accidentally being off 5 hours from EST, or off 1 hour from daylight savings when doing calculations. The tools within the datetime.datetime objects are great, however it would be nice be able to flag some setting when importing the datetime library and prevent reading my computer clock entirely, to avoid any accidental clock badness issue.

EXAMPLE OF CODE I AM LOOKING FOR:

import datetime
import requests

#force datetime libaries to never read my computer clock:
datetime.some_settings_function( readcomputerclock = False/'Never' )

#get the current time with some API:
current_utc_date_and_time_from_online = requests.get(...) #some api get request
current_utc_datetime = transform( current_utc_date_and_time_from_oneline )

#Transform back and forth to UTC Epoch time:
current_utc_epoch = current_utc_datetime.timestamp()
current_utc_datetime_again = datetime.datetime.fromtimestamp(current_utc_epoch)
#current_utc_datetime == current_utc_datetime_again

#Trigger exception with new settings, when i accidentally write code 
#    that would ask datetime library to attempt to read computer clock:
fail_code_line = datetime.datetime.now()
# >>> trigger some exception here 

TLDR; I am looking for a reliable UTC api for python, and a way to prevent datetime from ever reading my computer clock again.

UPDATE: After accepting the provided answer it has become clear to me for my purposes, trusting my computer clock for a few seconds after updating my computer clock from a trusted source, then asking my computer clock for UTC time within those few seconds is good enough. It is a feasible coding practice to write a "get UTC time now" code using all the information within the accepted answer, that is accurate to within a second or two. (No I have not done the statistical confidence interval posterior on the accuracy) It is then further feasible to write all the rest of my code such that all logic will assume UTC time.


Solution

  • Getting correct, timezone aware datetimes and unix timestamps

    Turns out this question was rather about how to convert to / from unix timestamps and datetimes.

    The correct solution in python 3 should be:

    from datetime import datetime, timezone
    
    # get the current utc time
    t = datetime.now(timezone.utc)
    
    # convert to unix, this will keep the utc timezone
    unix = t.timestamp()
    
    # convert back to datetime, specifying that the timestamp is in UTC
    t2 = datetime.fromtimestamp(unix, tz=timezone.utc)
    

    Other timezones

    Since python 3.9, the stdlib has the zoneinfo library, you can use this to convert between timezones. For python < 3.9, you have to use a thirdparty library like dateutil.

    from datetime import datetime
    from zoneinfo import ZoneInfo
    
    now_berlin = datetime.now(ZoneInfo('Europe/Berlin'))
    now_ny = now_berlin.astimezone(ZoneInfo('America/New_York'))
    
    print('Time in Berlin:', now_berlin)
    print('Time in New York', now_ny)
    

    Actually using ntp instead of the computer clock

    You can use ntplib:

    from ntplib import NTPClient
    from datetime import datetime, timezone
    
    client = NTPClient()
    response = client.request('europe.pool.ntp.org', version=3)
    
    time = datetime.fromtimestamp(resp.tx_time, tz=timezone.utc)
    

    Edit: I however don't see a real reason, why just from traveling this should go wrong:

    from datetime import datetime, timezone
    
    dt = datetime.now(timezone.utc)
    

    for more information see: https://blog.ganssle.io/articles/2019/11/utcnow.html