通过时间戳跨天计算.md 6.2 KB

#unity/日常积累

不同的时区,会有不同的时间偏移

/// <summary>  
/// UTC:世界时,格林尼治标准时  
/// 时间戳定义:此刻的格林威治时间距离UTC_START_DATE的秒数  
/// 注意:一般来说,用来显示给玩家看的DateTime,使用本地时区;用来判断跨天、跨周的DateTime,必须使用服务器时区  
/// </summary>
#region 常量定义  
  
public const int DEFAULT_TIMEZONE_OFFSET = 28800;//8 * 3600 东八区  
public const int DAY_SECOND = 86400;  
public const int WEEK_SECOND = 86400 * 7;  //一周时间秒数  
public const int HOUR_SECOND = 3600;  
public const int MINUTE_SECOND = 60;  
static readonly DateTime UTC_START_DATE = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);  
  
#endregion

/// <summary>  
/// 把UTC时间戳转换成指定时区的DateTime  
/// </summary>  
/// <param name="timeStamp">UTC时间戳</param>  
/// <param name="timeZoneOffset">指定时区离UTC时间的偏差值(秒)</param>  
/// <returns></returns>  
private static DateTime GetDateWithTimeZone(int timeStamp, int timeZoneOffset)  
{  
    return UTC_START_DATE.AddSeconds(timeStamp + timeZoneOffset);  
}

/// <summary>  
/// 把UTC时间戳转换成当前时区的DateTime  
/// MainLand地区默认为东八区  
/// 其他地区读取本机的时区设置  
/// </summary>  
/// <param name="timeStamp">UTC时间戳</param>  
/// <returns></returns>  
public static DateTime GetDateWithLocalTimeZone(int timeStamp)  
{  
    return GetDateWithTimeZone(timeStamp, LocalTimeZoneOffset);  
}


private static int FixTotalSeconds(this TimeSpan span)  
{  
    return span.Days * DAY_SECOND + span.Hours * HOUR_SECOND + span.Minutes * MINUTE_SECOND + span.Seconds;  
}


/// <summary>  
/// 把UTC时间戳转换成指定时区的DateTime  
/// </summary>  
/// <param name="timeStamp">UTC时间戳</param>  
/// <param name="timeZoneOffset">指定时区离UTC时间的偏差值(秒)</param>  
/// <returns></returns>  
private static DateTime GetDateWithTimeZone(int timeStamp, int timeZoneOffset)  
{  
    return UTC_START_DATE.AddSeconds(timeStamp + timeZoneOffset);  
}

/// <summary>  
/// 返回星期一  
/// </summary>  
/// <param name="timeStamp"></param>  
/// <returns></returns>  
public static int GetThisMonday(int timeStamp)  
{  
    DateTime date = GetDateWithLocalTimeZone(timeStamp);  
    int days = 0;  
    switch (date.DayOfWeek)  
    {       
		 case DayOfWeek.Monday:  
            days = 0;  
            break;       
         case DayOfWeek.Tuesday:  
            days = 1;  
            break;        
        case DayOfWeek.Wednesday:  
            days = 2;  
            break;        
        case DayOfWeek.Thursday:  
            days = 3;  
            break;        
        case DayOfWeek.Friday:  
            days = 4;  
            break;       
        case DayOfWeek.Saturday:  
            days = 5;  
            break;        
        case DayOfWeek.Sunday:  
            days = 6;  
            break;    
    }  
    return timeStamp - FixTotalSeconds(date.TimeOfDay) - days*DAY_SECOND;  
}

/// <summary>  
/// 计算跨自然天的小时数  
/// </summary>  
/// <param name="oldTimeStamp">之前时间戳</param>  
/// <param name="newTimeStamp">现在时间戳</param>  
/// <param name="timeZoneOffset">时区</param>  
/// <returns></returns>  
private static int ComputeCrossHours(int oldTimeStamp, int newTimeStamp, int timeZoneOffset)  
{  
    if (oldTimeStamp >= newTimeStamp)  
    {        
	    return 0;  
    }  
    DateTime oldDate = GetDateWithTimeZone(oldTimeStamp, timeZoneOffset);  
    DateTime newDate = GetDateWithTimeZone(newTimeStamp, timeZoneOffset);  
  
    TimeSpan offsetSpan = newDate.Subtract(oldDate);  
    int crossHours = Mathf.FloorToInt((float) offsetSpan.TotalHours);  
    if (crossHours >= 24)  
    {        
	    crossHours = crossHours % 24;  
    }  
    return crossHours;  
}


/// <summary>  
/// 计算跨自然天的天数,小于1天都返回0  
/// </summary>  
/// <param name="oldTimeStamp">之前时间戳</param>  
/// <param name="newTimeStamp">现在时间戳</param>  
/// <param name="timeZoneOffset">时区</param>  
/// <returns></returns>  
private static int ComputeCrossDays(int oldTimeStamp, int newTimeStamp, int timeZoneOffset)  
{  
    if (oldTimeStamp >= newTimeStamp)  
    {        
	    return 0;  
    }  
    DateTime oldDate = GetDateWithTimeZone(oldTimeStamp, timeZoneOffset);  
    DateTime newDate = GetDateWithTimeZone(newTimeStamp, timeZoneOffset);  
  
    TimeSpan offsetSpan = newDate.Subtract(oldDate);  
    //满24小时的跨天天数  
    int crossDays = Mathf.FloorToInt((float) offsetSpan.TotalDays);  
    //减掉满24小时的天后剩下的newDate  
    DateTime newDateLeft = newDate.AddDays(-crossDays);  
    if (newDateLeft.Day != oldDate.Day)  
    {
	    //如果不是同一天,说明虽然不满24小时,也跨天了  
        crossDays += 1;  
    }  
    return crossDays;  
}

  
/// <summary>  
/// 基于服务器时区,计算跨自然天天数  
/// </summary>  
/// <param name="oldTimeStamp"></param>  
/// <param name="newTimeStamp"></param>  
/// <returns></returns>  
public static int ComputeCrossServerDays(int oldTimeStamp, int newTimeStamp)  
{  
    return ComputeCrossDays(oldTimeStamp, newTimeStamp, ServerTimeZoneOffset);  
}

/// <summary>  
/// 基于服务器时区,计算跨自然周数  
/// </summary>  
/// <param name="oldTimeStamp">之前时间</param>  
/// <param name="newTimeStamp">现在时间</param>  
/// <returns></returns>        
public static int ComputeCrossServerWeeks(int oldTimeStamp, int newTimeStamp)  
{  
	if (oldTimeStamp > newTimeStamp)  
	{
	#if UNITY_EDITOR  
		if (GLog.IsLogInfoEnabled)  
		{                    
			GLog.LogError("oldTimeStamp bigger than newTimeStamp");  
		}  
	#endif  
	}  
	int crossDays = ComputeCrossServerDays(oldTimeStamp,newTimeStamp);  
	//如果跨天小于 7天,且所在的周一不同  
	if (crossDays > 0 && crossDays < 7)   
	{  
		int oldMonday = GetThisMonday(oldTimeStamp);  
		int newMonday = GetThisMonday(newTimeStamp);  
		if (newMonday > oldMonday)  
		{                    
			return 1;  
		}  
		else if (newMonday == oldMonday)  
		{                   
			 return 0;  
		}   
	}  
	return crossDays / 7;  
}