Files
5.24BuYu/Assets/Framework/Tool/BeijingTimeManager.cs
T
2026-07-25 16:13:21 +08:00

177 lines
6.3 KiB
C#

using System;
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using Newtonsoft.Json.Linq;
/// <summary>
/// 北京时间管理器 - 同步时记录服务器时间与本地系统时间的差值,获取时返回本地时间+差值
/// </summary>
public class BeijingTimeManager : MonoSingleton<BeijingTimeManager>
{
[Header("时间状态")]
[SerializeField] private bool _isTimeSynced = false;
[SerializeField] private TimeSpan _serverTimeOffset; // 服务器时间 - 本地系统时间
/// <summary>
/// 获取当前北京时间
/// </summary>
public DateTime CurrentBeijingTime
{
get
{
if (_isTimeSynced)
{
return DateTime.Now + _serverTimeOffset;
}
return DateTime.Now; // 未同步时返回本地时间
}
}
/// <summary>
/// 获取时间戳(秒)- 1970-01-01 08:00:00 到现在的秒数
/// </summary>
public long CurrentTimestamp
{
get
{
DateTime beijingTime = CurrentBeijingTime;
DateTime epoch = new DateTime(1970, 1, 1, 8, 0, 0); // 北京时间起点
return (long)(beijingTime - epoch).TotalSeconds;
}
}
/// <summary>
/// 获取时间戳(毫秒)
/// </summary>
public long CurrentTimestampMs
{
get
{
DateTime beijingTime = CurrentBeijingTime;
DateTime epoch = new DateTime(1970, 1, 1, 8, 0, 0); // 北京时间起点
return (long)(beijingTime - epoch).TotalMilliseconds;
}
}
public bool IsTimeSynced => _isTimeSynced;
public event Action<DateTime> OnTimeSynced;
private void Start()
{
SyncBeijingTime();
}
/// <summary>
/// 同步北京时间
/// </summary>
public void SyncBeijingTime()
{
StartCoroutine(FetchBeijingTime());
}
private IEnumerator FetchBeijingTime()
{
string[] timeServers = new string[]
{
"https://timeapi.io/api/Time/current/zone?timeZone=Asia/Shanghai",
"http://worldtimeapi.org/api/timezone/Asia/Shanghai",
"https://quan.suning.com/getSysTime.do"
};
foreach (string url in timeServers)
{
using (UnityWebRequest request = UnityWebRequest.Get(url + "?_=" + DateTime.Now.Ticks))
{
request.timeout = 5;
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
string jsonText = request.downloadHandler.text;
Debug.Log($"返回原始数据:{jsonText}");
if (!jsonText.TrimStart().StartsWith("{"))
{
Debug.LogWarning("返回的不是 JSON,跳过该源");
continue;
}
try
{
JObject json = JObject.Parse(jsonText);
if (url.Contains("timeapi.io"))
{
string timeStr = json["dateTime"]?.ToString();
Debug.Log(timeStr);
if (!string.IsNullOrEmpty(timeStr))
{
DateTime serverTime = DateTime.Parse(timeStr);
_serverTimeOffset = serverTime - DateTime.Now;
_isTimeSynced = true;
Debug.Log($"北京时间同步成功:{CurrentBeijingTime:yyyy-MM-dd HH:mm:ss},偏移量:{_serverTimeOffset.TotalSeconds:F1}s");
OnTimeSynced?.Invoke(CurrentBeijingTime);
yield break;
}
}
else if (url.Contains("worldtimeapi"))
{
string timeStr = json["datetime"]?.ToString();
Debug.Log(timeStr);
if (!string.IsNullOrEmpty(timeStr))
{
DateTime serverTime = DateTimeOffset.Parse(timeStr)
.ToOffset(TimeSpan.FromHours(8))
.DateTime;
_serverTimeOffset = serverTime - DateTime.Now;
_isTimeSynced = true;
Debug.Log($"北京时间同步成功:{CurrentBeijingTime:yyyy-MM-dd HH:mm:ss},偏移量:{_serverTimeOffset.TotalSeconds:F1}s");
OnTimeSynced?.Invoke(CurrentBeijingTime);
yield break;
}
}
else if (url.Contains("suning"))
{
string timeStr = json["sysTime2"]?.ToString();
Debug.Log(timeStr);
if (!string.IsNullOrEmpty(timeStr))
{
DateTime serverTime = DateTime.ParseExact(timeStr, "yyyy-MM-dd HH:mm:ss", null);
_serverTimeOffset = serverTime - DateTime.Now;
_isTimeSynced = true;
Debug.Log($"北京时间同步成功:{CurrentBeijingTime:yyyy-MM-dd HH:mm:ss},偏移量:{_serverTimeOffset.TotalSeconds:F1}s");
OnTimeSynced?.Invoke(CurrentBeijingTime);
yield break;
}
}
}
catch (Exception e)
{
Debug.LogWarning($"解析失败:{e.Message}");
continue;
}
}
}
}
Debug.LogError("所有时间服务器都失败了,使用本地时间");
_serverTimeOffset = TimeSpan.Zero;
_isTimeSynced = false;
}
/// <summary>
/// 获取格式化的北京时间
/// </summary>
public string GetFormattedTime(string format = "yyyy-MM-dd HH:mm:ss")
{
return CurrentBeijingTime.ToString(format);
}
}