Skip to content

Instantly share code, notes, and snippets.

@nihal111
Last active May 4, 2024 19:00
Show Gist options
  • Save nihal111/23faa51c3f88a281b676dcbac77ce015 to your computer and use it in GitHub Desktop.
Save nihal111/23faa51c3f88a281b676dcbac77ce015 to your computer and use it in GitHub Desktop.
A python script to update system time in Windows by attempting to fetch time from multiple NTP servers from a defined list.
import socket
import struct
import sys
import time
import datetime
import win32api
# List of servers in order of attempt of fetching
server_list = ['ntp.iitb.ac.in', 'time.nist.gov', 'time.windows.com', 'pool.ntp.org']
'''
Returns the epoch time fetched from the NTP server passed as argument.
Returns none if the request is timed out (5 seconds).
'''
def gettime_ntp(addr='time.nist.gov'):
# http://code.activestate.com/recipes/117211-simple-very-sntp-client/
TIME1970 = 2208988800 # Thanks to F.Lundh
client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
data = '\x1b' + 47 * '\0'
try:
# Timing out the connection after 5 seconds, if no response received
client.settimeout(5.0)
client.sendto( data, (addr, 123))
data, address = client.recvfrom( 1024 )
if data:
epoch_time = struct.unpack( '!12I', data )[10]
epoch_time -= TIME1970
return epoch_time
except socket.timeout:
return None
if __name__ == "__main__":
# Iterates over every server in the list until it finds time from any one.
for server in server_list:
epoch_time = gettime_ntp(server)
if epoch_time is not None:
# SetSystemTime takes time as argument in UTC time. UTC time is obtained using utcfromtimestamp()
utcTime = datetime.datetime.utcfromtimestamp(epoch_time)
win32api.SetSystemTime(utcTime.year, utcTime.month, utcTime.weekday(), utcTime.day, utcTime.hour, utcTime.minute, utcTime.second, 0)
# Local time is obtained using fromtimestamp()
localTime = datetime.datetime.fromtimestamp(epoch_time)
print("Time updated to: " + localTime.strftime("%Y-%m-%d %H:%M") + " from " + server)
break
else:
print("Could not find time from " + server)
@nihal111
Copy link
Author

A python script to update system time in Windows by attempting to fetch time from multiple NTP servers from a defined list.
Useful for IIT-Bombay, where outside NTP servers are inaccessible due to external port 123 being blocked.
IIT- Bombay has its own NTP server- ntp.iitb.ac.in, to which the first request is made.
On timeout of the request, a subsequent server from the server-list is attempted. Uses win32api (earlier pywin32) to set the system time. Needs to be run with administrator permissions.

@nihal111
Copy link
Author

nihal111 commented Mar 29, 2018

Install pywin32 from here or pip install pywin32.
Use Windows Task Scheduler to schedule the python script to run on every startup. Follow instructions from here

Create a Task
In General, check "Run with highest privileges"
Set Trigger as "On workstation unlock"
Set Action as "Start a Program" with Program/Script="C:\Python27\python.exe" and Argument="C:\Python27\ntp_update_time.py"

@fedmich
Copy link

fedmich commented May 25, 2018

Thanks, worked fine on my machine. I'm using time.windows.com , the others servers doesn't work sometimes.

@marcfelipe
Copy link

marcfelipe commented Jul 27, 2018

Here I had to make one change. I'm using Python 3.6.3 and I think this is the reason. The change was to convert data to bytes with encode function.
after data = '\x1b' + 47 * '\0' , I typed
data=data.encode()

@StakedWins
Copy link

@marcfelipe
Same was needed for me thank you

@AnimusXCASH
Copy link

Hey,
thanks first of all for script. Would you be able to make Ubuntu version? thanks

@astuvan
Copy link

astuvan commented Nov 9, 2020

@marcfelipe Same was needed for me :P

@thomas-vincent
Copy link

The only windows specific function is win32.SetSystemTime
You can replace as in https://stackoverflow.com/questions/12081310/python-module-to-change-system-date-and-time#12292874

@DrPaprikaa
Copy link

win32api.SetSystemTime() requires admin privileges, is there a workaround ?
I've seen this SO answer but it's not what I' looking for. My code runs 24/7 and I need to update the clock regularly : ideally I would like this method only to have admin privileges, not the whole script

@uniextra
Copy link

Getting this error.
Traceback (most recent call last):
File "ntp_update_time.py", line 35, in
epoch_time = gettime_ntp(server)
File "ntp_update_time.py", line 23, in gettime_ntp
client.sendto( data, (addr, 123))
TypeError: a bytes-like object is required, not 'str'

@mahakg290399
Copy link

Getting this error.
Traceback (most recent call last):
File "ntp_update_time.py", line 35, in
epoch_time = gettime_ntp(server)
File "ntp_update_time.py", line 23, in gettime_ntp
client.sendto( data, (addr, 123))
TypeError: a bytes-like object is required, not 'str'

I am also getting the same error.

@erwanito12
Copy link

erwanito12 commented Dec 1, 2021

we must add this except line 31:

except socket.gaierror:
return None

to correct this error :

Getting this error.
Traceback (most recent call last):
File "ntp_update_time.py", line 35, in
epoch_time = gettime_ntp(server)
File "ntp_update_time.py", line 23, in gettime_ntp
client.sendto( data, (addr, 123))
TypeError: a bytes-like object is required, not 'str'

@holahapi
Copy link

it works for my script(utf-8) by replace line 19 with
data = bytes('\x1b' + 47 * '\0','utf-8')

you also need to run as admin to change the time,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment