using System; using PhxhSDK; using Framework; using Gameplay; using UnityEngine; using Gameplay.Common; public class CrossDayChecker : Singlenton, IUpdatable, IInitable { public bool DeleteSaveData; // 检查时间点 private TimeSpan checkPointTime; // 记录上次检查的时间 private DateTime lastCheckTime; // 服务器时间与本地时间的差值(毫秒) private long serverTimeOffset; private bool _init; public bool disableCheck = false; public void SetCheckTime(TimeSpan checkTime) { checkPointTime = checkTime; } public void Update(float deltaTime) { if (!_init) return; if (disableCheck) return; // 使用本地时间加上差值计算服务器时间,避免频繁网络请求 var now = GetEstimatedServerTime(); // 检测跨天 if (HasCrossedDay(lastCheckTime, now)) { DebugUtil.Log("跨天了!"); EventManager.Instance.Send(EventManager.EventName.CrossDay); } // 检测跨周 if (HasCrossedWeek(lastCheckTime, now)) { DebugUtil.Log("跨周了!"); EventManager.Instance.Send(EventManager.EventName.CrossWeek); } // 检测跨月 if (HasCrossedMonth(lastCheckTime, now)) { DebugUtil.Log("跨月了!"); EventManager.Instance.Send(EventManager.EventName.CrossMonth); } lastCheckTime = now; } public void InitForLoginOk() { // 从配置中获取跨天时间点 checkPointTime = new TimeSpan(GLConfig.Inst.data.DailyChangeHour, 0, 0); // 初始化时计算服务器时间与本地时间的差值 DateTime serverTime = CommonUtils.GetCurTime(CommonUtils.E_TimeType.Server); DateTime localTime = DateTime.Now; serverTimeOffset = (long)(serverTime - localTime).TotalMilliseconds; DebugUtil.Log($"CrossDayChecker: 服务器时间偏移量:{serverTimeOffset}毫秒"); if (PlayerPrefs.HasKey("CrossDayChecker_LastCheckTime")) { string savedTime = PlayerPrefs.GetString("CrossDayChecker_LastCheckTime"); if (DateTime.TryParse(savedTime, out var parsedTime)) { lastCheckTime = parsedTime; DebugUtil.Log($"CrossDayChecker: 成功加载上次检查时间:{lastCheckTime}"); } else { DebugUtil.Log("CrossDayChecker: 无法解析存储的时间,使用当前服务器时间作为初始化时间。"); lastCheckTime = serverTime; SendAllCrossEvent(); } } else { DebugUtil.Log("CrossDayChecker: 本地存储中未找到上次检查时间,使用当前服务器时间作为初始化时间。"); lastCheckTime = serverTime; SendAllCrossEvent(); } _init = true; } /// /// 根据本地时间和时间偏移量估算服务器时间 /// private DateTime GetEstimatedServerTime() { return DateTime.Now.AddMilliseconds(serverTimeOffset); } /// /// 检测是否跨天 /// private bool HasCrossedDay(DateTime previousTime, DateTime currentTime) { var currentCrossTime = GetCrossTime(currentTime); return currentTime >= currentCrossTime && previousTime < currentCrossTime; } /// /// 检测是否跨周 /// private bool HasCrossedWeek(DateTime previousTime, DateTime currentTime) { var previousCrossTime = GetCrossTime(previousTime).StartOfWeek(); var currentCrossTime = GetCrossTime(currentTime).StartOfWeek(); return currentCrossTime > previousCrossTime && currentTime >= currentCrossTime; } /// /// 检测是否跨月 /// private bool HasCrossedMonth(DateTime previousTime, DateTime currentTime) { var previousCrossTime = GetCrossTime(previousTime).StartOfMonth(); var currentCrossTime = GetCrossTime(currentTime).StartOfMonth(); return currentCrossTime > previousCrossTime && currentTime >= currentCrossTime; } /// /// 获取指定时间的检查点时间 /// private DateTime GetCrossTime(DateTime date) { // 验证 date 是否在有效范围内 if (date < DateTime.MinValue || date > DateTime.MaxValue) { throw new ArgumentOutOfRangeException(nameof(date), "Input date is out of valid range."); } var crossTime = date.Date + checkPointTime; if (date.TimeOfDay < checkPointTime) { if (crossTime > DateTime.MinValue.AddDays(1)) { crossTime = crossTime.AddDays(-1); } else { crossTime = DateTime.MinValue; } } return crossTime; } private void SendAllCrossEvent() { EventManager.Instance.Send(EventManager.EventName.CrossDay); EventManager.Instance.Send(EventManager.EventName.CrossWeek); EventManager.Instance.Send(EventManager.EventName.CrossMonth); } public void Init() { } public void Release() { if (DeleteSaveData) return; PlayerPrefs.SetString("CrossDayChecker_LastCheckTime", lastCheckTime.ToString("o")); PlayerPrefs.Save(); DebugUtil.Log($"CrossDayChecker: 保存最后检查时间:{lastCheckTime}"); } } /// /// DateTime 的扩展方法 /// public static class DateTimeExtensions { /// /// 获取指定日期所在周的起始时间(以跨天时间点为准) /// public static DateTime StartOfWeek(this DateTime date) { // 周一为一周的起始 var diff = (int)date.DayOfWeek - (int)DayOfWeek.Monday; if (diff < 0) { diff += 7; } return date.AddDays(-diff).Date; } /// /// 获取指定日期所在月的起始时间(以跨天时间点为准) /// public static DateTime StartOfMonth(this DateTime date) { return new DateTime(date.Year, date.Month, 1); } }