You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
586 lines
19 KiB
586 lines
19 KiB
/*
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 毫秒
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 秒
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取下一个固定时间点的,
|
|
/// </summary>
|
|
/// <param name="tNow">现在的时间或者后面的时间</param>
|
|
/// <param name="iWeek">周几</param>
|
|
/// <param name="iHour">几点</param>
|
|
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;
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取下一个(月X号X点)
|
|
/// </summary>
|
|
/// <param name="timeSec">现在的时间或者后面的时间</param>
|
|
/// <param name="iDay">几号</param>
|
|
/// <param name="iHour">几点</param>
|
|
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;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 判断2个时间过去了几天,
|
|
/// </summary>
|
|
/// <param name="tNow">现在的时间或者后面的时间</param>
|
|
/// <param name="tTime">之前的时间</param>
|
|
/// <param name="iHour">几点重置一天时间(游戏里一般都不是24点重置)</param>
|
|
/// <returns>0表示同一天</returns>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取今天开始时间,早上5点
|
|
/// </summary>
|
|
/// <param name="tTimeNow"></param>
|
|
/// <param name="iHour"></param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 秒
|
|
/// </summary>
|
|
/// <param name="tA"></param>
|
|
/// <param name="tB"></param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 秒
|
|
/// </summary>
|
|
/// <param name="tA"></param>
|
|
/// <param name="tB"></param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 礼拜1到礼拜天算是一个游戏礼拜周期,礼拜1是第一天,返回1
|
|
/// </summary>
|
|
/// <param name="tTime"></param>
|
|
/// <param name="iHour">时间偏移,默认5点</param>
|
|
/// <returns></returns>
|
|
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 ;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 过去了几个礼拜
|
|
/// </summary>
|
|
/// <param name="tTime"></param>
|
|
/// <param name="tNow"></param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 返回时间tTime的这个礼拜1的开始时间
|
|
/// </summary>
|
|
/// <param name="tTime"></param>
|
|
/// <param name="iHour"></param>
|
|
/// <returns></returns>
|
|
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
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 返回时间tTime的这个礼拜N的开始时间
|
|
/// </summary>
|
|
/// <param name="tTime"></param>
|
|
/// <param name="day"></param>
|
|
/// <param name="iHour"></param>
|
|
/// <returns></returns>
|
|
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
|
|
}
|
|
|
|
/// <summary>
|
|
/// 返回时间tTime的这个礼拜7的开始时间
|
|
/// </summary>
|
|
/// <param name="tTime"></param>
|
|
/// <param name="iHour"></param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是不是同一个礼拜,1-7
|
|
/// </summary>
|
|
/// <param name="tNow"></param>
|
|
/// <param name="tBeforeTime"></param>
|
|
/// <param name="iHour"></param>
|
|
/// <returns></returns>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 后去时间在今天过去了多少秒,注意不是以5点开始一天计算
|
|
/// </summary>
|
|
/// <param name="time"></param>
|
|
/// <returns></returns>
|
|
public static int GetTimeSecondTodayFrom0(DateTime time)
|
|
{
|
|
return time.Hour * 3600 + time.Minute * 60 + time.Second;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 距离2022年1月1日过了多少天 最小为0
|
|
/// </summary>
|
|
/// <param name="time"></param>
|
|
/// <returns></returns>
|
|
public static int GetPassDayFrom2022(long timeSec)
|
|
{
|
|
if(timeSec < StarTime_2022)
|
|
{
|
|
return 0;
|
|
}
|
|
return (int)((timeSec - StarTime_2022) / SECONDS_ADAY);
|
|
}
|
|
}
|
|
}
|
|
|