NTPsyncer/main.py
2024-06-16 16:50:01 +08:00

268 lines
9.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import os
import ntplib
import time
import logging
from datetime import datetime
import win32api
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# ASCII 图像和软件信息
ascii_art = r"""
_ ____________
/ | / /_ __/ __ \ _______ ______ ________ _____
/ |/ / / / / /_/ / / ___/ / / / __ \/ ___/ _ \/ ___/
/ /| / / / / ____/ (__ ) /_/ / / / / /__/ __/ /
/_/ |_/ /_/ /_/ /____/\__, /_/ /_/\___/\___/_/
/____/
"""
software_info = """
NTP syncer v1.0
Version Date: 2024-06-16
Copyright © 2024 earthjasonlin
Homepage: https://git.loliquq.cn/earthjasonlin/NTP-syncer
Description: This tool synchronizes your system time with multiple NTP servers, considering network delay and time correction.
========================================
"""
# 打印 ASCII 图像和软件信息
print(ascii_art)
print(software_info)
# 定义 NTP 服务器池
# ntp_servers = [
# # 国家授时中心 NTP 服务器
# "ntp.ntsc.ac.cn", "114.118.7.161", "114.118.7.163",
# # 中国 NTP 快速授时服务
# "cn.ntp.org.cn", "223.113.97.98", "114.67.103.73", "119.29.26.206", "120.25.115.20",
# # 教育网
# "edu.ntp.org.cn", "202.118.1.130", "202.118.1.81", "116.13.10.10",
# # 中国计量科学研究院 NIM 授时服务
# "ntp1.nim.ac.cn", "ntp2.nim.ac.cn", "111.203.6.13",
# # 国际 NTP 快速授时服务
# "cn.pool.ntp.org", "120.25.115.20", "111.230.189.174", "119.28.183.184",
# # 阿里云公共 NTP 服务器
# "ntp.aliyun.com", "ntp1.aliyun.com", "ntp2.aliyun.com", "ntp3.aliyun.com",
# "ntp4.aliyun.com", "ntp5.aliyun.com", "ntp6.aliyun.com", "ntp7.aliyun.com",
# "203.107.6.88", "182.92.12.11", "120.25.108.11",
# # 腾讯云公共 NTP 服务器
# "ntp.tencent.com", "ntp1.tencent.com", "ntp2.tencent.com", "ntp3.tencent.com",
# "ntp4.tencent.com", "ntp5.tencent.com",
# # 高通中国提供 NTP 服务
# "time.izatcloud.net", "time.gpsonextra.net",
# # 教育网(高校自建)
# "ntp.sjtu.edu.cn", "ntp.neu.edu.cn", "ntp.bupt.edu.cn", "ntp.shu.edu.cn",
# # 国际 NTP 快速授时服务
# "pool.ntp.org", "0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org", "3.pool.ntp.org",
# "asia.pool.ntp.org", "64.62.194.188", "81.169.199.94",
# # 谷歌公共 NTP 服务器
# "time1.google.com", "time2.google.com", "time3.google.com", "time4.google.com",
# "216.239.35.0", "216.239.35.4", "216.239.35.8", "216.239.35.12",
# # 苹果公司公共 NTP 服务器
# "time.apple.com", "time1.apple.com", "time2.apple.com", "time3.apple.com",
# "time4.apple.com", "time5.apple.com", "time6.apple.com", "time7.apple.com",
# "17.253.84.123", "17.253.84.125", "17.253.114.253", "17.253.116.253",
# # Cloudflare NTP 服务器
# "time.cloudflare.com", "162.159.200.1", "162.159.200.123",
# # 微软 Windows NTP 服务器
# "time.windows.com", "20.189.79.72", "52.148.114.188", "40.119.6.228", "51.137.137.111",
# # 美国标准技术研究院 NTP 服务器
# "time.nist.gov", "time-nw.nist.gov", "time-a.nist.gov", "time-b.nist.gov",
# "128.138.141.172", "132.163.96.1", "132.163.96.2", "132.163.97.1", "132.163.97.2",
# ]
# 默认配置
default_config = {
"ntp_servers": [
"ntp.ntsc.ac.cn",
"114.118.7.161",
"114.118.7.163",
"cn.ntp.org.cn",
"223.113.97.98",
"114.67.103.73",
"119.29.26.206",
"120.25.115.20",
"edu.ntp.org.cn",
"202.118.1.130",
"202.118.1.81",
"116.13.10.10",
"ntp1.nim.ac.cn",
"ntp2.nim.ac.cn",
"111.203.6.13",
"cn.pool.ntp.org",
"120.25.115.20",
"111.230.189.174",
"119.28.183.184",
"ntp.aliyun.com",
"ntp1.aliyun.com",
"ntp2.aliyun.com",
"ntp3.aliyun.com",
"ntp4.aliyun.com",
"ntp5.aliyun.com",
"ntp6.aliyun.com",
"ntp7.aliyun.com",
"203.107.6.88",
"182.92.12.11",
"120.25.108.11",
"ntp.tencent.com",
"ntp1.tencent.com",
"ntp2.tencent.com",
"ntp3.tencent.com",
"ntp4.tencent.com",
"ntp5.tencent.com",
"time.izatcloud.net",
"time.gpsonextra.net",
"ntp.sjtu.edu.cn",
"ntp.neu.edu.cn",
"ntp.bupt.edu.cn",
"ntp.shu.edu.cn",
"pool.ntp.org",
"0.pool.ntp.org",
"1.pool.ntp.org",
"2.pool.ntp.org",
"3.pool.ntp.org",
"asia.pool.ntp.org",
"64.62.194.188",
"81.169.199.94",
"time1.google.com",
"time2.google.com",
"time3.google.com",
"time4.google.com",
"216.239.35.0",
"216.239.35.4",
"216.239.35.8",
"216.239.35.12",
"time.apple.com",
"time1.apple.com",
"time2.apple.com",
"time3.apple.com",
"time4.apple.com",
"time5.apple.com",
"time6.apple.com",
"time7.apple.com",
"17.253.84.123",
"17.253.84.125",
"17.253.114.253",
"17.253.116.253",
"time.cloudflare.com",
"162.159.200.1",
"162.159.200.123",
"time.windows.com",
"20.189.79.72",
"52.148.114.188",
"40.119.6.228",
"51.137.137.111",
"time.nist.gov",
"time-nw.nist.gov",
"time-a.nist.gov",
"time-b.nist.gov",
"128.138.141.172",
"132.163.96.1",
"132.163.96.2",
"132.163.97.1",
"132.163.97.2",
],
"update_interval": 600
}
# 从 JSON 文件中读取 NTP 服务器列表和更新间隔
def load_config(file_path):
if not os.path.exists(file_path):
with open(file_path, 'w', encoding='utf-8') as file:
json.dump(default_config, file, ensure_ascii=False, indent=4)
logging.info(f"The configuration file {file_path} does not exist. A default configuration file has been created.")
logging.info("=" * 40) # 分隔符
with open(file_path, 'r', encoding='utf-8') as file:
config = json.load(file)
return config['ntp_servers'], config['update_interval']
# 定义初始配置文件路径
config_file_path = 'ntp_config.json'
# 加载 NTP 服务器列表和更新间隔
ntp_servers, update_interval = load_config(config_file_path)
last_successful_index = 0
def get_ntp_time(server):
client = ntplib.NTPClient()
try:
send_time = time.time()
response = client.request(server, version=3)
receive_time = time.time()
# 计算延迟
delay = (receive_time - send_time) / 2
# 计算调整后的时间
ntp_time = response.tx_time + delay
return ntp_time, delay, response.tx_time
except ntplib.NTPException as e:
logging.warning(f"Unable to get NTP time from {server}: {e}")
return None, None, None
def update_system_time(ntp_time):
try:
# 获取当前系统时间(更新前)
current_system_time = datetime.utcnow()
# 格式化 NTP 时间为 datetime 对象(使用 UTC 时间)
dt = datetime.utcfromtimestamp(ntp_time)
# 获取星期几 (0 是星期一, 6 是星期日)
day_of_week = dt.weekday() + 1 # Windows API 需要 1 (星期一) 到 7 (星期日)
# 调用 win32api 设置系统时间
win32api.SetSystemTime(
dt.year, # 年
dt.month, # 月
day_of_week, # 星期几
dt.day, # 日
dt.hour, # 时
dt.minute, # 分
dt.second, # 秒
int(dt.microsecond / 1000) # 毫秒
)
# 获取当前系统时间(更新后)
new_system_time = datetime.utcnow()
# 计算时间偏移更新后的系统时间与NTP时间的差异
correction = (new_system_time - current_system_time).total_seconds()
logging.info(f"System time updated to: {dt.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]} UTC")
logging.info(f"Time correction: {correction*1000:.3f} ms")
except Exception as e:
logging.error(f"Unable to update system time: {e}")
def main():
global last_successful_index
while True:
for i in range(len(ntp_servers)):
index = (last_successful_index + i) % len(ntp_servers)
server = ntp_servers[index]
ntp_time, delay, raw_ntp_time = get_ntp_time(server)
if ntp_time:
last_successful_index = index
logging.info(f"Got NTP time from {server}: {datetime.utcfromtimestamp(raw_ntp_time).strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]} UTC")
logging.info(f"Network delay: {delay*1000:.3f} ms")
update_system_time(ntp_time)
break
else:
logging.warning("All NTP servers attempted but unable to get time. Waiting for next attempt...")
# 每隔一段时间检查一次
time.sleep(update_interval)
logging.info("=" * 40) # 分隔符
if __name__ == "__main__":
main()