using System; using NBC; using UnityEngine; namespace NBF { public class GameTimer { static GameTimer() { SetServerTime(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()); } // 游戏纪元开始时间(Unix 时间戳,毫秒) private const long GameEpoch = 1672531200000; // 2023-01-01 00:00:00 UTC // 时间加速比例 (1现实秒 = 15游戏秒) private const int TimeAcceleration = 200; //一天, 一小时, 一分钟固定时长(毫秒) public const long DAY_MILLS = 86400000; public const long HOUR_MILLS = 3600000; public const long MINUTE_MILLS = 60000; public const long SECOND_MILLS = 1000; private static long _serverTime; /// /// 更新服务器时间时的unity运行时间 /// private static float _serverTimeLocalTime; /// /// 当前服务器时间(ms) /// public static long serverTime { get { var offsetLocalTime = (long)((Time.realtimeSinceStartup - _serverTimeLocalTime) * 1000); return _serverTime + offsetLocalTime; } } /// /// 当前游戏时间 /// public static long gameTime => RealToGameTimestamp(serverTime); public static string gameTimeString { get { var realTime = DateTimeOffset.FromUnixTimeMilliseconds(gameTime); return $"{realTime.Hour:D2}:{realTime.Minute:D2}"; } } public static DateTime ServerDateTime => ConvertUtcToDateTime(serverTime); public static void SetServerTime(long time) { Log.Info($"设置服务器时间={time}"); _serverTime = time; _serverTimeLocalTime = Time.realtimeSinceStartup; } /// /// 获取本地时区 /// /// public static int GetLocalTimeZoneOffset() { TimeZoneInfo localTimeZone = TimeZoneInfo.Local; int offset = (int)localTimeZone.BaseUtcOffset.TotalHours; return offset; } /// /// 现实时间戳转游戏时间戳 /// /// 现实时间戳(毫秒) /// 游戏时间戳(毫秒) public static long RealToGameTimestamp(long realTimestamp) { long realElapsed = realTimestamp - GameEpoch; long gameElapsed = realElapsed * TimeAcceleration; return GameEpoch + gameElapsed; } /// /// 游戏时间戳转现实时间戳 /// /// 游戏时间戳(毫秒) /// 现实时间戳(毫秒) public static long GameToRealTimestamp(long gameTimestamp) { long gameElapsed = gameTimestamp - GameEpoch; long realElapsed = gameElapsed / TimeAcceleration; return GameEpoch + realElapsed; } /// /// 13位时间戳转化为时间 /// /// 时间戳 /// public static DateTime ConvertUtcToDateTime(long utcTime) { var startTime = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Utc); var cTime = startTime.AddTicks(utcTime * 10000); return cTime; } /// /// 时间转化为10位时间戳 /// /// 获取的时间 /// public static long ConvertDateTimeToUtc_10(DateTime time) { TimeSpan timeSpan = time.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(timeSpan.TotalSeconds); } /// /// 转为毫秒时间戳 13位 /// /// /// public static long ConvertDateTimeToUtc(DateTime time) { TimeSpan timeSpan = time - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(timeSpan.TotalMilliseconds); } /// /// 将一个秒数转换成"00:00:00"格式 /// /// /// public static string GetTimeStringHMD(long second) { int h = Mathf.FloorToInt(second / 3600f); int m = Mathf.FloorToInt(second / 60f - h * 60f); int s = Mathf.FloorToInt(second - m * 60f - h * 3600f); // 直接返回格式化好的小时、分钟、秒 return string.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s); } /// /// 将一个秒数转换成"00:00"格式 /// /// /// public static string GetTimeStringMD(int second) { if (second <= 0) { return "00:00"; } float m = Mathf.FloorToInt(second / 60f); float s = Mathf.FloorToInt(second % 60); // 使用ZString进行高效的字符串拼接 return string.Format("{0:D2}:{1:D2}", (int)m, (int)s); } /// /// 获取游戏时间在当天的进度(0到1之间的值) /// 0表示当天0点,1表示当天24点 /// public static float GetGameDayProgress() { // 获取当天的总毫秒数 double totalMillisecondsInDay = 24 * 60 * 60 * 1000; // 86400000ms // 计算当天已过去的毫秒数 double elapsedMilliseconds = ConvertUtcToDateTime(gameTime).TimeOfDay.TotalMilliseconds; // 计算进度(0-1) return (float)(elapsedMilliseconds / totalMillisecondsInDay); // return 0.2f; } } }