跳至主要内容

NtpTime

重要 注意 提醒

Coding Style wiki


NtpTime與 NTP 伺服器或 HTTP 時間 API 進行時鐘同步的靜態授時工具,同步一次後即可持續取得經過校正的當前時間 (以「收到回應的時間點 + 經過時間」推算),不受用戶修改裝置時間影響,適用於防作弊、每日重置等需要可信時間的場景。

命名空間OxGKit.TimeSystem
類型public static class NtpTime
原始碼NtpTime.cs
using OxGKit.TimeSystem;

快速上手

using Cysharp.Threading.Tasks;
using OxGKit.TimeSystem;

// 與 NTP 伺服器同步 (預設 time.google.com、10 秒逾時)
await NtpTime.Synchronize();

// 同步完成後取得校正時間
if (NtpTime.IsSynchronized())
{
System.DateTime now = NtpTime.GetNow(); // 本地時間
System.DateTime utcNow = NtpTime.GetUtcNow(); // UTC 時間
}

通用規則

同步方式

SynchronizentpServer 參數自動判斷同步方式:

方式ntpServer 參數說明
NTP (UDP)主機名稱 (如 time.google.com)透過 UDP Socket (Port 123) 向 NTP 伺服器請求 (於執行緒池執行)。
HTTP 時間 APIhttp://https:// 開頭的網址透過 UnityWebRequest 請求 (WebGL 相容),預設解析 TimeAPI.io Timezone API 響應格式,如 https://timeapi.io/api/timezone/zone?timeZone=Asia/Taipei

注意 WebGL 平台無法使用 UDP Socket,請改用 HTTP 時間 API 方式同步 (將 API 網址傳入 ntpServer)。

未同步的返回行為

重要 Synchronize異步流程,請以 IsSynchronized 判斷同步完成後再取時;未同步時各取時方法只會輸出警告日誌 ([NTP] No synchronized.) 並改返回本地系統時間 (GetTimeZone 返回空字串、GetUtcOffset 返回 0),不會擲出例外。

時間推算

提醒 同步成功後會記錄「收到回應的時間點」,之後的取時皆以同步時間 + 經過時間推算,不需重複同步;如需重新校正 (例如網路恢復後),再次呼叫 Synchronize 即可。


方法

方法總覽

方法說明
Synchronize開始與 NTP 伺服器或 HTTP 時間 API 同步。
IsSynchronized是否已完成同步。
GetNow取得校正後的本地時間。
GetUtcNow取得校正後的 UTC 時間。
GetNtpDate取得校正後的原始同步時區時間。
GetTimeZone取得同步使用的時區名稱。
GetUtcOffset取得同步時間的 UTC 偏移 (小時)。

Synchronize

public static UniTask Synchronize(string ntpServer = "time.google.com", int requestTimeout = 10)

public static UniTask Synchronize<TResponseFormat>(string ntpServer = "time.google.com", int requestTimeout = 10) where TResponseFormat : TimeApiResponseFormat

開始與 NTP 伺服器或 HTTP 時間 API 同步 (會先將同步狀態重置為未同步):

  • ntpServer:NTP 伺服器主機名稱,或 http(s):// 開頭的時間 API 網址 (詳見同步方式)。
  • requestTimeout:請求逾時秒數 (預設 10 秒),逾時會輸出錯誤日誌。
  • 泛型版本可指定 HTTP 響應的反序列化格式 (需繼承 TimeApiResponseFormat)。
// NTP (UDP) 同步
await NtpTime.Synchronize();

// HTTP 時間 API 同步 (WebGL 相容)
await NtpTime.Synchronize("https://timeapi.io/api/timezone/zone?timeZone=Asia/Taipei");

注意 網路不可達時 (Application.internetReachability 為 NotReachable) 會輸出警告並直接返回,不會進行同步。

IsSynchronized

public static bool IsSynchronized()

返回是否已完成與 NTP 伺服器的同步。

GetNow

public static DateTime GetNow()

取得校正後的本地時間;當系統時區與伺服器時區相近 (差距小於 0.1 小時) 時直接返回同步時間,否則會先轉為 UTC 再轉為系統本地時間。未同步時輸出警告並返回 DateTime.Now.ToLocalTime()

GetUtcNow

public static DateTime GetUtcNow()

取得校正後的 UTC 時間 (依同步時儲存的時區偏移換算)。未同步時輸出警告並返回 DateTime.Now.ToUniversalTime()

GetNtpDate

public static DateTime GetNtpDate()

取得校正後的原始同步時區時間 (保持收到回應時的時區,僅加上經過時間)。未同步時輸出警告並返回 DateTime.Now

GetTimeZone

public static string GetTimeZone()

取得同步使用的時區名稱 (如 Asia/Taipei,由 HTTP 時間 API 提供);未同步時返回空字串。

GetUtcOffset

public static double GetUtcOffset()

取得同步時間的 UTC 偏移 (小時);未同步時返回 0。


響應格式

HTTP 時間 API 的響應以 JsonUtility 反序列化,格式類別皆標註 [Serializable]

public abstract class TimeApiResponseFormat { }

public class TimeApiTimezoneResponse : TimeApiResponseFormat
{
public string timeZone; // 如 "Asia/Taipei"
public string currentLocalTime; // 如 "2025-05-15T12:55:08.5386566"
public UtcOffset currentUtcOffset;
public UtcOffset standardUtcOffset;
public bool hasDayLightSaving;
public bool isDayLightSavingActive;
public DstInterval dstInterval;
}

注意 內建處理流程目前僅支持 TimeApiTimezoneResponse (TimeAPI.io Timezone API) 格式:需要包含 timeZonecurrentLocalTimecurrentUtcOffset 欄位,其他格式會輸出解析失敗的錯誤日誌。