177 lines
6.3 KiB
C#
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);
|
|
}
|
|
} |