Skip to main content

NtpTime

Important Attention Reminder

Coding Style wiki


NtpTime is a static clock-synchronization utility for NTP servers or HTTP time APIs. After synchronizing once, it keeps providing the corrected current time (extrapolated as "time of the received response + elapsed time"), unaffected by users changing the device clock — suitable for anti-cheat, daily reset, and other scenarios that need trusted time.

NamespaceOxGKit.TimeSystem
Typepublic static class NtpTime
SourceNtpTime.cs
using OxGKit.TimeSystem;

Quick Start

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

// Synchronize with an NTP server (defaults: time.google.com, 10s timeout)
await NtpTime.Synchronize();

// Read the corrected time once synchronized
if (NtpTime.IsSynchronized())
{
System.DateTime now = NtpTime.GetNow(); // local time
System.DateTime utcNow = NtpTime.GetUtcNow(); // UTC time
}

General Rules

Synchronization Methods

Synchronize picks the synchronization method automatically based on the ntpServer parameter:

MethodntpServer ParameterDescription
NTP (UDP)A host name (e.g. time.google.com)Requests the NTP server over a UDP socket (port 123), executed on the thread pool.
HTTP time APIA URL starting with http:// or https://Requests via UnityWebRequest (WebGL compatible); by default parses the TimeAPI.io Timezone API response format, e.g. https://timeapi.io/api/timezone/zone?timeZone=Asia/Taipei.

Attention WebGL cannot use UDP sockets — synchronize through an HTTP time API instead (pass the API URL as ntpServer).

Behavior While Not Synchronized

Important Synchronize is an async flow — gate reads on IsSynchronized. While not synchronized, the time getters only print a warning log ([NTP] No synchronized.) and fall back to the local system time (GetTimeZone returns an empty string, GetUtcOffset returns 0) — no exception is thrown.

Time Extrapolation

Reminder After a successful sync, the "time of the received response" is recorded, and later reads are extrapolated as synchronized time + elapsed timeno repeated synchronization required; to re-correct (e.g. after the network recovers), simply call Synchronize again.


Methods

Method Overview

MethodDescription
SynchronizeBegins synchronizing with an NTP server or HTTP time API.
IsSynchronizedWhether synchronization has completed.
GetNowGets the corrected local time.
GetUtcNowGets the corrected UTC time.
GetNtpDateGets the corrected time in the original synchronized timezone.
GetTimeZoneGets the timezone name used for synchronization.
GetUtcOffsetGets the UTC offset (hours) of the synchronized time.

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

Begins synchronizing with an NTP server or HTTP time API (the synchronized state is reset to unsynchronized first):

  • ntpServer: an NTP server host name, or a time API URL starting with http(s):// (see Synchronization Methods).
  • requestTimeout: request timeout in seconds (default 10); a timeout prints an error log.
  • The generic version specifies the deserialization format of the HTTP response (must inherit TimeApiResponseFormat).
// NTP (UDP) synchronization
await NtpTime.Synchronize();

// HTTP time API synchronization (WebGL compatible)
await NtpTime.Synchronize("https://timeapi.io/api/timezone/zone?timeZone=Asia/Taipei");

Attention When the network is unreachable (Application.internetReachability is NotReachable), a warning is printed and the call returns without synchronizing.

IsSynchronized

public static bool IsSynchronized()

Returns whether synchronization with the NTP server has completed.

GetNow

public static DateTime GetNow()

Gets the corrected local time; when the system timezone is close to the server timezone (difference under 0.1 hours), the synchronized time is returned as-is, otherwise it is converted to UTC first and then to the system local time. While not synchronized, prints a warning and returns DateTime.Now.ToLocalTime().

GetUtcNow

public static DateTime GetUtcNow()

Gets the corrected UTC time (converted using the UTC offset stored at sync time). While not synchronized, prints a warning and returns DateTime.Now.ToUniversalTime().

GetNtpDate

public static DateTime GetNtpDate()

Gets the corrected time in the original synchronized timezone (kept in the timezone it was received in, only advanced by the elapsed time). While not synchronized, prints a warning and returns DateTime.Now.

GetTimeZone

public static string GetTimeZone()

Gets the timezone name used for synchronization (e.g. Asia/Taipei, provided by the HTTP time API); returns an empty string while not synchronized.

GetUtcOffset

public static double GetUtcOffset()

Gets the UTC offset (hours) of the synchronized time; returns 0 while not synchronized.


Response Format

HTTP time API responses are deserialized with JsonUtility; the format classes are all marked [Serializable]:

public abstract class TimeApiResponseFormat { }

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

Attention The built-in processing currently only supports the TimeApiTimezoneResponse (TimeAPI.io Timezone API) format — it requires the timeZone, currentLocalTime, and currentUtcOffset fields; other formats result in a parse-failure error log.