跳到主要内容

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 时间
}

通用规则​

同步方式​

Synchronize 依 ntpServer 参数自动判断同步方式:

方式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) 格式:需要包含 timeZone、currentLocalTime 与 currentUtcOffset 字段,其他格式会输出解析失败的错误日志。