首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Python 修改系統時間完整實作:對時伺服器同步與 Win32 API 呼叫

     編輯:更多程式設計知識

本文示範如何使用 Python 連線 NTP 時間伺服器(國家授時中心),解析回傳時間封包,並透過 win32api.SetSystemTime 修改 Windows 系統時間。適用於離線環境、嵌入式裝置、自動化測試需精確校時的場景。

核心流程

  1. UDP 連線 NTP 伺服器(Port 123)
  2. 發送 NTP 請求封包(0x1b + 47 bytes 零填充)
  3. 接收回應,解析第 10 個 32-bit 整數(Traffic Timestamp)
  4. 扣除 NTP 紀元差異(1900→1970:2208988800 秒)
  5. 轉換為 time.gmtime 結構
  6. 呼叫 win32api.SetSystemTime 寫入系統時間

完整程式碼


# -*- coding: utf-8 -*-
import socket
import struct
import time
import win32api

# 國家授時中心 IP(可替換為 pool.ntp.org 等)
TIME_SERVER = '210.72.145.44'
PORT = 123
NTP_EPOCH_OFFSET = 2208988800  # 1900-01-01 到 1970-01-01 的秒數

def get_ntp_time():
    """從 NTP 伺服器取得 Unix timestamp"""
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    client.settimeout(5)
    
    # NTP 請求封包:LI=0, VN=3, Mode=3 (Client) = 0x1b
    data = b'\x1b' + b'\x00' * 47
    client.sendto(data, (TIME_SERVER, PORT))
    
    data, _ = client.recvfrom(1024)
    client.close()
    
    # 解析:第 10 個 32-bit 無號整數為 Transmit Timestamp
    transmit_ts = struct.unpack('!12I', data)[10]
    unix_ts = transmit_ts - NTP_EPOCH_OFFSET
    return unix_ts

def set_system_time():
    """設定 Windows 系統時間"""
    ntp_time = get_ntp_time()
    # gmtime 回傳 struct_time: (年, 月, 日, 時, 分, 秒, 週幾, 年天數, 夏令時)
    tm = time.gmtime(ntp_time)
    
    # win32api.SetSystemTime(year, month, dayOfWeek, day, hour, minute, second, milliseconds)
    # 注意:dayOfWeek 為 0=星期日,time.gmtime 回傳 0=星期一,需轉換
    day_of_week = (tm.tm_wday + 1) % 7  # Python: 0=Mon → Windows: 0=Sun
    
    win32api.SetSystemTime(
        tm.tm_year, tm.tm_mon, day_of_week, tm.tm_mday,
        tm.tm_hour, tm.tm_min, tm.tm_sec, 0
    )
    print("系統時間同步完成!")

if __name__ == '__main__':
    set_system_time()
    # 驗證
    ntp_time = get_ntp_time()
    local = time.localtime(ntp_time)
    print("當前系統時間: %04d-%02d-%02d %02d:%02d:%02d" % local[:6])

關鍵細節說明

項目說明
NTP 封包格式RFC 5905 定義,前 48 bytes 為標準頭部
struct.unpack('!12I')網路序 (big-endian) 解析 12 個 unsigned int
索引 [10]第 11 個欄位為 Transmit Timestamp(伺服器發送時間)
紀元差異NTP 以 1900 為紀元,Unix 以 1970,差 2208988800 秒
weekday 轉換Python tm_wday: 0=Mon;Windows: 0=Sun,需 (wday+1)%7
權限需求修改系統時間需管理員權限執行

跨平台替代方案

  • Linux:os.system('date -s @"%d"' % ts) 或 ctypes 呼叫 clock_settime
  • 純 Python(無管理員權限):無法修改系統時間,僅能在應用層維護邏輯時間
  • 推薦庫:ntplib 封裝 NTP 協定,python-ntp 提供更高階介面

常見問題排查

  • Timeout:防火牆封鎖 UDP 123,嘗試其他 NTP 伺服器(time.windows.com、pool.ntp.org)
  • 時間偏差大:檢查網路延遲,NTP 精度通常在毫秒級
  • win32api 無法匯入:安裝 pywin32:pip install pywin32
  • 夏令時:NTP 回傳 UTC 時間,SetSystemTime 亦為 UTC,系統會依時區自動換算顯示
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved