/* Sog 游戏基础库 2016 by zouwei */ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; namespace Sog { public class AppTime { public static AppTime ServerAppTime { get; private set; } public static int TimeZone { get; private set; } private static int TimeZoneSecond; //每天早上0点重置一天的时间 改为0点 private static int GAME_RESET_HOUR_EVERYDAY = 0; public const int SECONDS_ADAY = 24 * 3600; public const int SECONDS_AHOUR = 3600; public const int SECONDS_AMINUTE = 60; public const int SECONDS_AWEEK = 24 * 3600 * 7; public const int SECONDS_AYEAR = SECONDS_ADAY * 365; public const string TIME_FORMAT_STYLE = "yyyy-MM-dd HH:mm:ss"; public const string TIME_FORMAT_STYLE_SHORT = "yyyy-MM-dd"; public const long StarTime_2022 = 1640966400; //北京时间 2022年1月1日0点 private static DateTime m_dateTime1970_utc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static DateTime m_dateTime1970 = m_dateTime1970_utc.ToLocalTime(); private long m_milliSecond = 0; private long m_second = 0; private DateTime m_nowDateTimeWithOffset; //time offset,be used by addservertime private long m_offsetSecond = 0; public AppTime() { if(ServerAppTime == null) { ServerAppTime = this; } } public static void UpdateGameResetHour(int hour) { GAME_RESET_HOUR_EVERYDAY = hour; } public static int GetGameResetHour() { return GAME_RESET_HOUR_EVERYDAY; } public void UpdateTime() { m_milliSecond = GetTime(DateTime.Now) + m_offsetSecond * 1000; m_second = m_milliSecond / 1000; m_nowDateTimeWithOffset = ConvertUnixTimeToDateTime(m_milliSecond); } //这个等价于GetTime(DateTime t) public static long ConvertDateTimeToUnixTime(DateTime datatime) { TimeSpan ts = datatime - m_dateTime1970; long timeMs = (long)ts.TotalMilliseconds; return timeMs; } //一定要注意,这里是毫秒,不是秒!!! public static DateTime ConvertUnixTimeToDateTime(long millSecond) { DateTime startTime = m_dateTime1970; return startTime.AddMilliseconds(millSecond); } //一定要注意,这里是秒,不是毫秒!!! public static DateTime ConvertUnixTimeToDateTime1(long second) { DateTime startTime = m_dateTime1970; return startTime.AddMilliseconds(second*1000); } //把一个时间撮转为可读字符串时间 public static string ConvertUnixTimeToString(long seconds, string format = TIME_FORMAT_STYLE) { return ConvertUnixTimeToDateTime1(seconds).ToString(format); } //将一个可读字符串转化为时间 public static DateTime ConvertStringToDateTime(string dateString,string format = TIME_FORMAT_STYLE) { return DateTime.ParseExact(dateString, format, CultureInfo.InvariantCulture); } // return total offsetsecond public long AddOffset(long offsetSecond) { m_offsetSecond += offsetSecond; return m_offsetSecond; } public void SetOffset(long offsetSecond) { m_offsetSecond = offsetSecond; } /// /// 毫秒 /// /// public long GetTime() { return m_milliSecond; } public DateTime GetDateTime() { return m_nowDateTimeWithOffset; } public static long GetTime(DateTime time) { TimeSpan ts = time - m_dateTime1970; long timeMs = (long)ts.TotalMilliseconds; return timeMs; } /// /// 秒 /// /// public long GetTimeSecond() { return m_second; } public static long GetTimeSecond(DateTime time) { return GetTime(time)/1000; } public static long GetTimeSecond(string dateString) { return GetTimeSecond(ConvertStringToDateTime(dateString)); } //获取没有偏移的系统时间 public static long GetNowSysMs() { TimeSpan ts = DateTime.Now - m_dateTime1970; return (long)ts.TotalMilliseconds; } public static long GetNowSysSecond() { return GetNowSysMs() / 1000; } public static DateTime GetNow() { return TimeSpanToDateTime(GetNowSysSecond()); } public static DateTime TimeSpanToDateTime(long nowSecond) { return DateTimeOffset.FromUnixTimeSeconds(nowSecond).LocalDateTime; } public static void InitTimeZone() { TimeZone = TimeZoneInfo.Local.BaseUtcOffset.Hours; TimeZoneSecond = TimeZone * 3600; } /// /// 获取下一个固定时间点的, /// /// 现在的时间或者后面的时间 /// 周几 /// 几点 public static long GetNextTime(long tTime, int iWeek, int iHour) { DateTime dateTime = AppTime.ConvertUnixTimeToDateTime(tTime * 1000); //现在是周几 int nWeekDay = GetWeekDay127(tTime, 0); //现在是几时 int nHour = GetHour(tTime); int iHourSecond = iHour * 3600; //与周几无关 if (iWeek == 0) { if(nHour >= iHour) { return GetTodayStartTime(tTime + SECONDS_ADAY, 0) + iHourSecond; } else { return GetTodayStartTime(tTime, 0) + iHourSecond; } } else { if(nWeekDay == iWeek) { if (nHour >= iHour) { return GetTodayStartTime(tTime + SECONDS_ADAY*7, 0) + iHourSecond; } else { return GetTodayStartTime(tTime, 0) + iHourSecond; } } int i = 1; for (; i <= 7;i++) { if((iWeek == 7 && (nWeekDay + i) % 7 ==0)||(nWeekDay+i)%7 == iWeek) { break; } } return GetTodayStartTime(tTime + SECONDS_ADAY * i, 0) + iHourSecond; } } /// /// 获取下一个(月X号X点) /// /// 现在的时间或者后面的时间 /// 几号 /// 几点 public static long GetNextMonthTime(long timeSec, int iDay = 1) { int iHour = GAME_RESET_HOUR_EVERYDAY; long startTime = GetTodayStartTime(timeSec, 0); //指定时间当天0点 long addHourTime = iHour * SECONDS_AHOUR; DateTime dateTime = AppTime.ConvertUnixTimeToDateTime(startTime * 1000); DateTime nowMonthStart = dateTime.AddDays(iDay - dateTime.Day); //当月X号0点 long monthBegin = GetTimeSecond(nowMonthStart) + addHourTime; if (monthBegin >= timeSec) { return monthBegin; } DateTime nextMonthStart = nowMonthStart.AddMonths(1); monthBegin = GetTimeSecond(nextMonthStart) + addHourTime; return monthBegin; } /// /// 判断2个时间过去了几天, /// /// 现在的时间或者后面的时间 /// 之前的时间 /// 几点重置一天时间(游戏里一般都不是24点重置) /// 0表示同一天 public static int GetDayElapse(long tNow, long tTime) { return GetDayElapse(tNow, tTime, GAME_RESET_HOUR_EVERYDAY); } public static int GetDayElapse(long tNow, long tTime, int iHour) { //要考虑对时引起的时间后退问题 if (tNow <= tTime) { return 0; } int iHourSecond = iHour * 3600; return GetDayElapseBySecond(tNow, tTime, iHourSecond); } // 判断2个时间过去了几天,以second作为每天的分割点 // 一定要清楚你为何需要调用它, 否则请使用上面以 GAME_RESET_HOUR_EVERYDAY 作为默认参数的接口 public static int GetDayElapseBySecond(long tNow, long tTime, int seconds) { //要考虑对时引起的时间后退问题 if (tNow <= tTime) { return 0; } //UTC long tNowLocal = tNow + TimeZoneSecond - seconds; long tTimeLocal = tTime + TimeZoneSecond - seconds; long tNowDays = tNowLocal / SECONDS_ADAY; long tTimeDays = tTimeLocal / SECONDS_ADAY; return (int)(tNowDays - tTimeDays); } /// /// 获取今天开始时间,早上5点 /// /// /// /// public static long GetTodayStartTime(long tTimeNow) { int iHour = GAME_RESET_HOUR_EVERYDAY; return GetTodayStartTime(tTimeNow, iHour); } public static long GetTodayStartTime(long tTimeNow, int iHour) { int iHourSecond = iHour * 3600; //UTC long tNowLocal = tTimeNow + TimeZoneSecond - iHourSecond; long tNowDays = tNowLocal / SECONDS_ADAY; long tNowDayStart = tNowDays * SECONDS_ADAY; tNowDayStart = tNowDayStart - TimeZoneSecond + iHourSecond; return tNowDayStart; } public static long GetTodayEndTime(long tTimeNow) { return GetTodayStartTime(tTimeNow) + 86400; } /// /// 秒 /// /// /// /// public static bool IsSameHour(long tA, long tB) { if (tA == tB) { return true; } long tAHours = tA / SECONDS_AHOUR; long tBHours = tB / SECONDS_AHOUR; if (tAHours == tBHours) { return true; } return false; } /// /// 秒 /// /// /// /// public static bool IsSameMinute(long tA, long tB) { long tAMinute = tA / 60; long tBMinute = tB / 60; if (tAMinute == tBMinute) { return true; } return false; } public static bool IsSameDay(long tCur, long tBefore) { int iHour = GAME_RESET_HOUR_EVERYDAY; return IsSameDay(tCur, tBefore, iHour); } public static bool IsSameDay(long tCur, long tBefore, int iHour ) { //只是判断是否同一天,两个时间大小应该不做要求 if (tCur < tBefore) { return GetDayElapse(tBefore, tCur, iHour) == 0; } return GetDayElapse(tCur, tBefore, iHour) == 0; } // 是否同一天, 以seconds作为两天之间的分割时间 public static bool IsSameDayBySecond(long tCur, long tBefore, int seconds) { //只是判断是否同一天,两个时间大小应该不做要求 if (tCur < tBefore) { return GetDayElapseBySecond(tBefore, tCur, seconds) == 0; } return GetDayElapseBySecond(tCur, tBefore, seconds) == 0; } public static bool IsSameMonth(long sec1, long sec2) { int iHour = GAME_RESET_HOUR_EVERYDAY; int iHourSecond = iHour * 3600; DateTime date1 = ConvertUnixTimeToDateTime((sec1 - iHourSecond) * 1000); DateTime date2 = ConvertUnixTimeToDateTime((sec2 - iHourSecond) * 1000); return date1.Month == date2.Month; } /// /// 礼拜1到礼拜天算是一个游戏礼拜周期,礼拜1是第一天,返回1 /// /// /// 时间偏移,默认5点 /// public static int GetWeekDay127(long tTime) { int iHour = GAME_RESET_HOUR_EVERYDAY; return GetWeekDay127(tTime, iHour); } public static int GetWeekDay127(long tTime, int iHour) { long iLocalTime = tTime + TimeZoneSecond - iHour * SECONDS_AHOUR; long iWeekDay = ((iLocalTime / SECONDS_ADAY + 3) % 7) + 1; return (int)iWeekDay; } public static int GetHour(long tTime) { long iLocalTime = tTime + TimeZoneSecond; return (int)(iLocalTime / 3600) % 24 ; } /// /// 过去了几个礼拜 /// /// /// /// public static int GetOffsetWeeks(long tNow ,long tTime) { if (tTime >= tNow) { return 0; } long tTimeWeekStart = GetThisWeekStartTime1(tTime); long tNowWeekStart = GetThisWeekStartTime1(tNow); if (tTimeWeekStart >= tNowWeekStart) { return 0; } return (int)(tNowWeekStart - tTimeWeekStart) / SECONDS_AWEEK; } /// /// 返回时间tTime的这个礼拜1的开始时间 /// /// /// /// public static long GetThisWeekStartTime1(long tTime) { int iHour = GAME_RESET_HOUR_EVERYDAY; return GetThisWeekStartTime1(tTime, iHour); } public static long GetThisWeekStartTime1(long tTime, int iHour) { int iHourSecond = iHour * 3600; //5 * 3600 long iLocalTime = tTime + TimeZoneSecond - iHourSecond; long iLocalDayStartTime = (iLocalTime / SECONDS_ADAY) * SECONDS_ADAY; int iWeekDay = GetWeekDay127(tTime - iHourSecond, 0); long iLocalThisWeekStartTime1 = iLocalDayStartTime - (iWeekDay - 1) * SECONDS_ADAY; return iLocalThisWeekStartTime1 - TimeZoneSecond + iHourSecond;//to GMT } /// /// 返回时间tTime的这个礼拜N的开始时间 /// /// /// /// /// public static long GetThisWeekStartTimeN(long tTime,int day) { int iHour = GAME_RESET_HOUR_EVERYDAY; int iHourSecond = iHour * 3600; //5 * 3600 long iLocalTime = tTime + TimeZoneSecond - iHourSecond; long iLocalDayStartTime = (iLocalTime / SECONDS_ADAY) * SECONDS_ADAY; int iWeekDay = GetWeekDay127(tTime - iHourSecond, 0); long iLocalThisWeekStartTime1 = iLocalDayStartTime - (iWeekDay - day) * SECONDS_ADAY; return iLocalThisWeekStartTime1 - TimeZoneSecond + iHourSecond;//to GMT } /// /// 返回时间tTime的这个礼拜7的开始时间 /// /// /// /// public static long GetThisWeekEndTime(long tTime) { int iHour = GAME_RESET_HOUR_EVERYDAY; int iHourSecond = iHour * 3600; long iLocalTime = tTime + TimeZoneSecond - iHourSecond; long iLocalDayStartTime = (iLocalTime / SECONDS_ADAY) * SECONDS_ADAY; int iWeekDay = GetWeekDay127(tTime - iHourSecond, 0); long iLocalThisWeekEndTime = iLocalDayStartTime + (7 - (iWeekDay - 1)) * SECONDS_ADAY; return iLocalThisWeekEndTime - TimeZoneSecond + iHourSecond; } /// /// 是不是同一个礼拜,1-7 /// /// /// /// /// public static bool IsSameWeek127(long tNow, long tBeforeTime) { int iHour = GAME_RESET_HOUR_EVERYDAY; return IsSameWeek127(tNow, tBeforeTime, iHour); } public static bool IsSameWeek127(long tNow, long tBeforeTime, int iHour) { // if (tNow <= tBeforeTime) { //return true; long temp = tNow; tNow = tBeforeTime; tBeforeTime = temp; } return GetThisWeekStartTime1(tNow, iHour) == GetThisWeekStartTime1(tBeforeTime, iHour); } /// /// 后去时间在今天过去了多少秒,注意不是以5点开始一天计算 /// /// /// public static int GetTimeSecondTodayFrom0(DateTime time) { return time.Hour * 3600 + time.Minute * 60 + time.Second; } /// /// 距离2022年1月1日过了多少天 最小为0 /// /// /// public static int GetPassDayFrom2022(long timeSec) { if(timeSec < StarTime_2022) { return 0; } return (int)((timeSec - StarTime_2022) / SECONDS_ADAY); } } }