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

/*
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);
}
}
}