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 = 20;
//一天, 一小时, 一分钟固定时长(毫秒)
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);
}
}
}