local Time_Utility = {} local private = {} --默认北京时区,在公告中获取服务器时区进行调整 local ServerTimeZone = 8 --物理上本地和服务器差的秒数 local LocalServerDiffSeconds = 0 --显示上本地和服务器差的描述,只用于时辰的计算,如果没有夏令时的区域,则为LocalServerDiffSeconds local DisplayLocalServerDiffSeconds = 0 --物理上的本地时区 local LocalTimeZone = 0 --本地显示的时区,如果有夏令时则计算夏令时,如果没有则==LocalTimeZone local DisplayLocalTimeZone = 0 local OSTimeTab = {year=0, month=0, day=0, hour=0, min=0, sec=0} Time_Utility.TotalSecondsOneWeek = 604800 Time_Utility.TotalSecondsOneDay = 86400 Time_Utility.TotalSecondsOneHour = 3600 Time_Utility.TotalSecondsOneMinute = 60 local CrossDayTimeId = 1 --跨天时刻的id local LastOSTime --上次获取的本地时间,避免1秒内获取多次服务器时间 local ServerTimeStamp --获取的服务器时间 --本地时区检测,每半小时检测一下 local TimeZoneCheckInterval = 1800 private.lastTimeZoneCheckTime = 0 --是否已经设置了服务器的时区 private.hasSetServerTimeZone = false private.originalDate = os.date Time_Utility.TimeType = { DAILY = 1, WEEKLY = 2, MONTHLY = 3, YEAR = 4, HOUR = 5, NDAY = 6, LIFETIME = 7, INSERVEROPEN = 8, ATSERVEROPEN = 9, AFTERSERVEROPEN = 10, NEXTDAYTIME = 11, SHOWTIME = 12, SHOWTOADY = 13 } Time_Utility.TimeZoneType = { PreDay = 1, SameDay = 2, Tomorrow = 3, } function Time_Utility.OnStartup() private.InitOsDateUtil() end function Time_Utility.CheckLeftTimeLessOneMinute(expireTime) if expireTime <= 0 then return false end local timeStamp = Time_Utility.GetServerTimestamp() local leftTime = expireTime - timeStamp return leftTime <= Time_Utility.TotalSecondsOneMinute end function Time_Utility.CheckLeftTimeLessOneHour(lastTimeStamp) return (Time_Utility.GetServerTimestamp() - lastTimeStamp) <= Time_Utility.TotalSecondsOneHour end function Time_Utility.CheckLeftTimeLessOneDay(lastTimeStamp) return (Time_Utility.GetServerTimestamp() - lastTimeStamp) <= Time_Utility.TotalSecondsOneDay end function Time_Utility.GetLeftTime_SimpleFormat(expireTime, isTitle) if not expireTime or expireTime <= 0 then return nil end local timeStamp = Time_Utility.GetServerTimestamp() local leftTime = expireTime - timeStamp if leftTime >= Time_Utility.TotalSecondsOneDay then if isTitle then return string.FormatByIdsId(Const_IDS.IDS_TimeLeft_Right, UTL.Color.FormatTextByColor(UTL.Color.ModelNameColor.White, math.floor(leftTime / Time_Utility.TotalSecondsOneDay))) else return string.FormatByIdsId(Const_IDS.IDS_TimeLeft, math.floor(leftTime / Time_Utility.TotalSecondsOneDay)) end elseif leftTime >= Time_Utility.TotalSecondsOneHour then if isTitle then return string.FormatByIdsId(Const_IDS.IDS_TimeLeft_Hour_Right, UTL.Color.FormatTextByColor(UTL.Color.ModelNameColor.White, math.floor(leftTime / Time_Utility.TotalSecondsOneHour))) else return string.FormatByIdsId(Const_IDS.IDS_TimeLeft_Hour, math.floor(leftTime / Time_Utility.TotalSecondsOneHour)) end elseif leftTime >= 0 then if isTitle then return string.FormatByIdsId(Const_IDS.IDS_TimeLeft_Minute_Right, UTL.Color.FormatTextByColor(UTL.Color.ModelNameColor.White, math.floor(leftTime / Time_Utility.TotalSecondsOneMinute))) else return string.FormatByIdsId(Const_IDS.IDS_TimeLeft_Minute, math.floor(leftTime / Time_Utility.TotalSecondsOneMinute)) end else return string.FormatByIdsId(Const_IDS.IDS_TimeLeft_Minute, 0) end end function Time_Utility.TransToHours(seconds) return math.floor(seconds / Time_Utility.TotalSecondsOneHour) end function Time_Utility.GetShowTimeByMinutes(minutes) local result --大于1天 if (minutes >= 1440) then local day = math.floor(minutes / 1440) result = string.FormatByIdsId(Const_IDS.IDS_Item_Time_Day, day) elseif minutes >= Time_Utility.TotalSecondsOneMinute then --大于1小时 local hours = math.floor(minutes / Time_Utility.TotalSecondsOneMinute) result = string.FormatByIdsId(Const_IDS.IDS_Item_Time_Hour, hours) elseif minutes > 0 then result = string.FormatByIdsId(Const_IDS.IDS_Item_Time_Minute, minutes) else result = UIUtils.GetLocalizedTxt(Const_IDS.IDS_Item_OverTime) end return result end function Time_Utility.GetShowTimeBySeconds(seconds) local result if seconds >= Time_Utility.TotalSecondsOneDay then --大于一天 local day = math.floor(seconds / Time_Utility.TotalSecondsOneDay) result = string.FormatByIdsId(Const_IDS.IDS_Item_Time_Day, day) elseif seconds >= Time_Utility.TotalSecondsOneHour then --大于1小时 local hour = math.floor(seconds / Time_Utility.TotalSecondsOneHour) result = string.FormatByIdsId(Const_IDS.IDS_Item_Time_Hour, hour) elseif seconds >= Time_Utility.TotalSecondsOneMinute then --大于1分钟 local minutes = math.floor(seconds / Time_Utility.TotalSecondsOneMinute) result = string.FormatByIdsId(Const_IDS.IDS_Item_Time_Minute, minutes) elseif seconds > 0 then result = string.FormatByIdsId(Const_IDS.IDS_TimeSecond, seconds) end return result end --- 以本地时区自然日0点为节点,获取本地时区倒计时格式化文本 function Time_Utility.GetLocalShowTimeCountDownByTimestamp(timestamp, now) local diffTimeSeconds = timestamp - Time_Utility.GetServerTimestamp() if diffTimeSeconds < 0 then return nil end local localActivityData = Time_Utility.OsDateOriginal("*t", timestamp) local localDate = Time_Utility.OsDateOriginal("*t", Time_Utility.GetServerTimestamp()) local dayDiff = localActivityData.yday - localDate.yday if dayDiff > 0 then return string.FormatByIdsId(Const_IDS["IDS_Title_Day"], dayDiff) end local hourDiff = math.floor(diffTimeSeconds / Time_Utility.TotalSecondsOneHour) if hourDiff > 0 then return string.FormatByIdsId(Const_IDS["IDS_Title_Hour"], hourDiff) end local minutesDiff = math.ceil(diffTimeSeconds / Time_Utility.TotalSecondsOneMinute) if diffTimeSeconds >= Time_Utility.TotalSecondsOneMinute then return string.FormatByIdsId(Const_IDS["IDS_Item_Time_Minute"], minutesDiff) end return string.FormatByIdsId(Const_IDS["IDS_SecondsCountdown"], diffTimeSeconds) end function Time_Utility.FormatTimeByFrameCount(timeFrame) local timeStr = "00:00" local totalSecond = math.floor(timeFrame / 20) local second = math.fmod(totalSecond, Time_Utility.TotalSecondsOneMinute) local minute = math.floor(totalSecond / Time_Utility.TotalSecondsOneMinute) timeStr = string.format("%02d:%02d", minute, second) return timeStr end --00:00 function Time_Utility.FormatTimeSeconds(seconds) if seconds >= Time_Utility.TotalSecondsOneMinute then local min = math.floor(seconds / Time_Utility.TotalSecondsOneMinute) seconds = seconds % Time_Utility.TotalSecondsOneMinute return string.format("%02d:%02d", min, seconds) else return string.format("00:%02d", seconds) end end --00:00:00 function Time_Utility.FormatTimeClockBySeconds(seconds,formatStr) local hour = math.floor(seconds / Time_Utility.TotalSecondsOneHour) local sec = seconds % Time_Utility.TotalSecondsOneHour local min = math.floor(sec / Time_Utility.TotalSecondsOneMinute) sec = sec % Time_Utility.TotalSecondsOneMinute formatStr = formatStr or "%02d:%02d:%02d" return string.format(formatStr, hour, min, sec) end --x分x秒 function Time_Utility.FormatTimeBySeconds(seconds) if seconds > Time_Utility.TotalSecondsOneMinute then local min = math.floor(seconds / Time_Utility.TotalSecondsOneMinute) local sec = seconds % Time_Utility.TotalSecondsOneMinute local minText = string.FormatByIdsId(Const_IDS.IDS_TimeMinute, min) local secText = string.FormatByIdsId(Const_IDS.IDS_TimeSecond, sec) return string.format("%s %s", minText, secText) else return string.FormatByIdsId(Const_IDS.IDS_TimeSecond, seconds) end end -- x小时x分x秒,最短显示 function Time_Utility.FormatTimeBySecondsToHour(seconds) local hour, min, sec = 0, 0, 0 local textList = {} local hourText, minText, secText if seconds >= Time_Utility.TotalSecondsOneHour then hour = math.floor(seconds / Time_Utility.TotalSecondsOneHour) table.insert(textList, string.FormatByIdsId(Const_IDS.IDS_Item_Time_Hour, hour)) end if seconds >= Time_Utility.TotalSecondsOneMinute then min = math.floor(seconds % Time_Utility.TotalSecondsOneHour / Time_Utility.TotalSecondsOneMinute) if min > 0 then table.insert(textList, string.FormatByIdsId(Const_IDS.IDS_TimeMinute, min)) end end sec = math.floor(seconds % Time_Utility.TotalSecondsOneMinute) if sec > 0 then table.insert(textList, string.FormatByIdsId(Const_IDS.IDS_TimeSecond, sec)) end return table.concat(textList) end function Time_Utility.GetDiffLocalTimeZoneById(id) local value = DataSheetManager.TimeRefresh:GetDataByID(id).HMS+Time_Utility.GetDisplayDiffLocalTimeZone() local hour = math.floor(value/Time_Utility.TotalSecondsOneHour) local minutes = value % Time_Utility.TotalSecondsOneHour if hour < 0 then return (hour + 24) * Time_Utility.TotalSecondsOneHour + minutes, Time_Utility.TimeZoneType.PreDay elseif hour >= 0 and hour < 24 then return hour * Time_Utility.TotalSecondsOneHour + minutes, Time_Utility.TimeZoneType.SameDay else return (hour - 24) * Time_Utility.TotalSecondsOneHour + minutes, Time_Utility.TimeZoneType.Tomorrow end end function Time_Utility.GetDiffLocalEndTimeZoneById(endId, startId) local endTimeCfg = DataSheetManager.TimeRefresh:GetDataByID(endId) local endValue = endTimeCfg.HMS + Time_Utility.GetDisplayDiffLocalTimeZone() if endTimeCfg.Timer == Time_Utility.TimeType.DAILY then local startValue = DataSheetManager.TimeRefresh:GetDataByID(startId).HMS + Time_Utility.GetDisplayDiffLocalTimeZone() if endValue <= 0 then if startValue <= 0 then startValue = startValue + Time_Utility.TotalSecondsOneDay local endValueTmp = endValue + Time_Utility.TotalSecondsOneDay if endValueTmp < startValue then -- 次日 endValue = endValue + Time_Utility.TotalSecondsOneDay end else endValue = endValue + Time_Utility.TotalSecondsOneDay end else if endValue < startValue then -- 次日 endValue = endValue + Time_Utility.TotalSecondsOneDay end end end local hour = math.floor(endValue/Time_Utility.TotalSecondsOneHour) local minutes = endValue % Time_Utility.TotalSecondsOneHour if hour < 0 then return (hour + 24) * Time_Utility.TotalSecondsOneHour + minutes, Time_Utility.TimeZoneType.PreDay elseif hour >= 0 and hour < 24 then return hour * Time_Utility.TotalSecondsOneHour + minutes, Time_Utility.TimeZoneType.SameDay else return (hour - 24) * Time_Utility.TotalSecondsOneHour + minutes, Time_Utility.TimeZoneType.Tomorrow end end function Time_Utility.GetDiffLocalStrById(id) local value,timeZoneType = Time_Utility.GetDiffLocalTimeZoneById(id) return Time_Utility.OsDateOriginal("!%H:%M", value) end --通过时区格式化时间 function Time_Utility.GetTimeFormatTimeZone(timePoint) return timePoint + Time_Utility.GetDisplayDiffLocalTimeZone() end --服务器时间,在整点的x秒内返回0,否则返回距离下一个整点的秒数 function Time_Utility.GetOffsetTimeFromHourWithSeconds(seconds) local curDate = Time_Utility.OsDateOriginal("*t", private.LocalToServerDisplayDateTimestamp()) local total = curDate.min * Time_Utility.TotalSecondsOneMinute + curDate.sec if total <= seconds then return 0 else return Time_Utility.TotalSecondsOneHour - total end end --服务器时间,距离当前时刻的HMS还差的秒数 function Time_Utility.DiffHMS(tarHMS) local curDate = Time_Utility.OsDateOriginal("*t", private.LocalToServerDisplayDateTimestamp()) local total = curDate.min * Time_Utility.TotalSecondsOneMinute + curDate.sec return tarHMS - total end function Time_Utility.GetBeginAndEndTime(timeTable, timerColor) local dateDesc, time = Time_Utility.GetDateDescAndTime(timeTable) return string.Concat(dateDesc, (timerColor and UTL.Color.FormatTextByColor(timerColor, time) or time)) end function Time_Utility.GetDateDescAndTimeById(startId,endId) return Time_Utility.GetDateDescAndTime({{StartTime = startId, EndTime = endId}}) end --获取配置的时间显示 function Time_Utility.GetLocalTimeDesc(timeId) return Time_Utility.OsDateOriginal("!%H:%M", Time_Utility.GetDiffLocalTimeZoneById(timeId)) end --参数是一个timetable --返回时间段,参数:{{StartTime= 1000,EndTime = 23333}} --返回时刻,参数:{1000,1001} --具体时间必须相同,只返回第一个,即返回:参数1【每周一、三、五】 参数2【10:30~11:00】 function Time_Utility.GetDateDescAndTime(timeTab) local dateDesc local time for i, v in ipairs(timeTab) do local isTab = type(v) == "table" local value = isTab and v.StartTime or v local data = DataSheetManager.TimeRefresh:GetDataByID(value) local startTime, startType = Time_Utility.GetDiffLocalTimeZoneById(value) local startTimeStr = Time_Utility.OsDateOriginal("!%H:%M", startTime) local endType local endTimeStr local endTime if isTab then endTime, endType = Time_Utility.GetDiffLocalEndTimeZoneById(v.EndTime, v.StartTime) endTimeStr = Time_Utility.OsDateOriginal("!%H:%M", endTime) if endType == startType then time = string.format("%s~%s", startTimeStr, endTimeStr) else time = string.FormatByIdsId(Const_IDS.IDS_Time_ToNext, startTimeStr, endTimeStr) end else time = startTimeStr end if data.Timer == Time_Utility.TimeType.NEXTDAYTIME then if startType == Time_Utility.TimeZoneType.PreDay then dateDesc = UIUtils.GetLocalizedTxt(Const_IDS.IDS_Time_Today) elseif startType == Time_Utility.TimeZoneType.Tomorrow then dateDesc = "" --次日 logging.error(LTAG.ERROR, "NEXTDAYTIME-Tomorrow") else dateDesc = UIUtils.GetLocalizedTxt(Const_IDS.IDS_Time_NextDay) end elseif data.Timer == Time_Utility.TimeType.SHOWTIME or data.Timer == Time_Utility.TimeType.SHOWTOADY then if startType == Time_Utility.TimeZoneType.PreDay then dateDesc = UIUtils.GetLocalizedTxt(Const_IDS.IDS_Time_Yesterday)--前天 elseif startType == Time_Utility.TimeZoneType.Tomorrow then dateDesc = UIUtils.GetLocalizedTxt(Const_IDS.IDS_Time_NextDay) --次日 else dateDesc = data.Timer == Time_Utility.TimeType.SHOWTOADY and UIUtils.GetLocalizedTxt(Const_IDS.IDS_Time_Today) or "" end elseif data.Timer == Time_Utility.TimeType.DAILY then dateDesc = UIUtils.GetLocalizedTxt(Const_IDS.IDS_Daily) return dateDesc, time--这里先这么写 每日玩法 目前只支持一天开一次 elseif data.Timer == Time_Utility.TimeType.WEEKLY then local symbol if GameAppInfo.IsVietnamPackage() then symbol = ', ' elseif Localization.IsEnglish() then symbol = ',' else symbol = '、' end local calender = Localization.IsEnglish() and "" or UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_DayTitle) --英文不显示“周” local date = nil local GetWeekTitleVN = false if startType == Time_Utility.TimeZoneType.PreDay then date = Time_Utility.GetWeekNum(data.Day - 1) --周几减一天 GetWeekTitleVN = Time_Utility.GetWeekTitleVN(data.Day - 1) elseif startType == Time_Utility.TimeZoneType.Tomorrow then date = Time_Utility.GetWeekNum((data.Day + 1) % 7) -- 周几加一天 周日加一天 周一 GetWeekTitleVN = Time_Utility.GetWeekTitleVN((data.Day + 1) % 7) else date = Time_Utility.GetWeekNum(data.Day) GetWeekTitleVN = Time_Utility.GetWeekTitleVN(data.Day) end if Localization.IsJapanese() then if dateDesc == nil then dateDesc = Time_Utility.GetAllDaysFromWeekForJP(timeTab) end else if dateDesc == nil then if GameAppInfo.IsVietnamPackage() and not GetWeekTitleVN then dateDesc = calender .. " " .. date elseif GameAppInfo.IsVietnamPackage() and GetWeekTitleVN then dateDesc = date else dateDesc = calender .. date end else dateDesc = dateDesc .. symbol .. date end end elseif data.Timer == Time_Utility.TimeType.LIFETIME then local startStr = Time_Utility.ShowYMDDesc(data, startTimeStr, startType) if isTab then local endData = DataSheetManager.TimeRefresh:GetDataByID(v.EndTime) local endStr = Time_Utility.ShowYMDDesc(endData, endTimeStr, endType) return startStr, endStr else return startStr end elseif data.Timer == Time_Utility.TimeType.MONTHLY then local symbol = Localization.IsEnglish() and ',' or '、' local calender = UIUtils.GetLocalizedTxt(Const_IDS.IDS_Time_Month) local month = data.Month local day = data.Day --这种类型不好判断 策划说不会有1号的活动 和 28号以后的活动 所以时区不用考虑跨月 if startType == Time_Utility.TimeZoneType.PreDay then day = day - 1 elseif startType == Time_Utility.TimeZoneType.Tomorrow then day = day + 1 end if dateDesc == nil then dateDesc = day else dateDesc = dateDesc .. symbol .. day end if i == #timeTab then dateDesc = string.format(calender, dateDesc) end end end return dateDesc, time end --专门为日本地区的星期显示逻辑的特殊处理 function Time_Utility.GetAllDaysFromWeekForJP(timeTab) local daysStr local symbol = Localization.IsEnglish() and ',' or '、' local calender = Localization.IsEnglish() and "" or UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_DayTitle) --英文不显示“周” for i, v in ipairs(timeTab) do local isTab = type(v) == "table" local value = isTab and v.StartTime or v local data = DataSheetManager.TimeRefresh:GetDataByID(value) local startTime, startType = Time_Utility.GetDiffLocalTimeZoneById(value) local date = nil if data.Timer == Time_Utility.TimeType.WEEKLY then if startType == Time_Utility.TimeZoneType.PreDay then date = Time_Utility.GetWeekNum(data.Day - 1) --周几减一天 elseif startType == Time_Utility.TimeZoneType.Tomorrow then date = Time_Utility.GetWeekNum((data.Day + 1) % 7) -- 周几加一天 周日加一天 周一 else date = Time_Utility.GetWeekNum(data.Day) end if daysStr == nil then daysStr = date else daysStr = daysStr .. symbol .. date end end end return (daysStr .. calender) end function Time_Utility.ShowYMDDesc(data, timeStr,timeZoneType) --返回年月日 时分 local year = data.Year local month = data.Month local day = data.Day if timeZoneType == Time_Utility.TimeZoneType.PreDay then day = day - 1 elseif timeZoneType == Time_Utility.TimeZoneType.Tomorrow then day = day + 1 end if day == 0 then --2021/1/1 变成2020/12/31 month = month - 1 if month == 0 then year = year - 1 month = 12 end end local dayAmount = Time_Utility.OsDateOriginal("%d", Time_Utility.GetOsTimestamp(year, month+1, 0, 0, 0, 0)) dayAmount = tonumber(dayAmount) if day == 0 then day = dayAmount elseif day > dayAmount then -- 2020/12/31 变成2021/1/1 day = day - dayAmount month = month + 1 if month == 13 then year = year + 1 month = 1 end end local dateDesc if GameAppInfo.IsVietnamPackage() then dateDesc = string.format("%s/%s/%s ", day, month, year) else dateDesc = string.format("%s/%s/%s ", year, month, day) end return timeStr and dateDesc .. timeStr or dateDesc end --格式化含有半个小时的时间 function Time_Utility.FormatHalfHour(timeValue) local timeValueFormat if timeValue >= 100 then timeValueFormat = string.format("%.2s", timeValue) else timeValueFormat = string.format("%02d", timeValue) end return timeValueFormat end --根据时间戳判断与当前时间是否为同一天 function Time_Utility.IsTimestampSameDay(timeStamp) local curDate = math.floor(Time_Utility.GetServerTimestamp() / Time_Utility.TotalSecondsOneDay) local date = math.floor(timeStamp / Time_Utility.TotalSecondsOneDay) return curDate == date end --根据时间戳判断与当前时间间隔多少天 function Time_Utility.GetTimestampDay(timeStamp) local curDate = Time_Utility.GetServerTimestamp() return math.ceil(math.abs(curDate - timeStamp) / Time_Utility.TotalSecondsOneDay) end function Time_Utility.IsTimeInADay(timeStamp) local offsetTime = os.difftime(Time_Utility.GetServerTimestamp(), timeStamp) return offsetTime <= Time_Utility.TotalSecondsOneDay end --若0<X<5分钟,则显示为“刚刚” --若5分钟≤X<1小时,则显示为“X分钟前”,不足1分钟向下取整,例如5分59秒记为5分钟 --若1小时≤X<24小时,则显示为“X小时前·”,不足1小时向下取整 --若24小时≤X<168小时,则显示为“X天前”,不足1天向下取整 --若X≥168小时,则显示为“7天以上” function Time_Utility.GetBeyondTime(timeStamp) if timeStamp < Time_Utility.TotalSecondsOneMinute * 5 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Friend_Just) elseif timeStamp >= Time_Utility.TotalSecondsOneMinute * 5 and timeStamp < Time_Utility.TotalSecondsOneHour then return string.FormatByIdsId(Const_IDS.IDS_Friend_MinBefore, math.floor(timeStamp / Time_Utility.TotalSecondsOneMinute)) elseif timeStamp >= Time_Utility.TotalSecondsOneHour and timeStamp < Time_Utility.TotalSecondsOneDay then return string.FormatByIdsId(Const_IDS.IDS_Friend_HoursBefore, math.floor(timeStamp / Time_Utility.TotalSecondsOneHour)) elseif timeStamp >= Time_Utility.TotalSecondsOneDay and timeStamp < Time_Utility.TotalSecondsOneWeek then return string.FormatByIdsId(Const_IDS.IDS_Friend_DayBefore, math.floor(timeStamp / Time_Utility.TotalSecondsOneDay)) else return string.FormatByIdsId(Const_IDS.IDS_Friend_DayAbove, 7) end end --[[ 剩余时间大于1天时,显示天数小时数,若小时数<1,则不显示“小时”,如:48小时54分钟显示为“2天” 剩余时间大于1小时且小于1天时,显示小时数,向下取整,如1小时50分钟显示为1小时 剩余时间大于0且小于1小时,显示为“不足1小时” ]] function Time_Utility.FormatTimeForTitle(offset) if offset > 0 then if offset >= Time_Utility.TotalSecondsOneDay then local day = math.floor(offset / Time_Utility.TotalSecondsOneDay) local sec = offset % Time_Utility.TotalSecondsOneDay if sec >= Time_Utility.TotalSecondsOneHour then local hour = math.floor(sec / Time_Utility.TotalSecondsOneHour) local formatStr = string.Concat(UIUtils.GetLocalizedTxt(Const_IDS.IDS_Title_Day),UIUtils.GetLocalizedTxt(Const_IDS.IDS_Title_Hour)) return string.format(formatStr, day, hour) else return string.format(UIUtils.GetLocalizedTxt(Const_IDS.IDS_Title_Day), day) end elseif offset >= Time_Utility.TotalSecondsOneHour then return string.format(UIUtils.GetLocalizedTxt(Const_IDS.IDS_Title_Hour), math.floor(offset / Time_Utility.TotalSecondsOneHour)) else return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Title_NotEnough) end end return "" end --超过一天显示 天数、小时数,一天以内显示00:00:00 function Time_Utility.FormatTimeForDayOrClock(time) local result if time >= Time_Utility.TotalSecondsOneDay then result = Time_Utility.FormatTimeForTitle(time) else result = Time_Utility.FormatTimeClockBySeconds(time) end return result end --timeStamp与当前时间对比,超过一天显示【年/月/日 时:分】,小于一天显示【时:分】 function Time_Utility.FormatTimeForMsg(timeStamp) if Time_Utility.IsTimestampSameDay(timeStamp) then return os.date("%H:%M", timeStamp) else return os.date("%Y/%m/%d %H:%M", timeStamp) end end -- 返回【年/月/日 时:分】 function Time_Utility.FormatTimeCompletely(timeStamp) return os.date("%Y/%m/%d %H:%M", timeStamp) end -- 返回【月/日 时:分】 function Time_Utility.FormatTimeSimpleNotSpace(timeStamp) return os.date("%m/%d %H:%M", timeStamp) end -- 返回【时:分:秒】 function Time_Utility.FormatTimeSimpleWithHMS(timeStamp) return os.date("%H:%M:%S", timeStamp) end -- 返回【年/月/日】 function Time_Utility.FormatTimeForJP(timeStamp) return os.date("%Y/%m/%d", timeStamp) end -- 返回【月/日】 function Time_Utility.FormatTimeForTab(timeStamp) return os.date("%m/%d", timeStamp) end --返回【月,日,时:分】 function Time_Utility.FormatTimeSimple(timeStamp) local month = Time_Utility.OsDateOriginal("%m", timeStamp) local day = Time_Utility.OsDateOriginal("%d", timeStamp) local hourMinute = os.date("%H:%M", timeStamp) return month,day,hourMinute end ---超过一天返回天时分秒 否则返回时分秒 function Time_Utility.FormatTimeForDay(seconds, dayStr ,hourStr) local hour = math.floor(seconds / Time_Utility.TotalSecondsOneHour) local sec = seconds % Time_Utility.TotalSecondsOneHour local min = math.floor(sec / Time_Utility.TotalSecondsOneMinute) sec = sec % Time_Utility.TotalSecondsOneMinute if Time_Utility.TotalSecondsOneDay <= seconds then local day = math.floor(hour / 24) hour = hour % 24 return string.format(dayStr,day, hour,min,sec) else return string.format(hourStr,hour,min,sec) end end function private.InitOsDateUtil() os.date = function(formatType, date) return Time_Utility.FormatDateForRegions(formatType, date) end end -- 这里的字段为 FormatDateTable 某些地区需要修改的时间格式,可以新增可以拓展。 -- 一般格式要求年月日之间的分隔符必须为斜杆,时分秒的分隔符必须用冒号。 Time_Utility.FormatDateEnum = { YMDHMS = "%Y/%m/%d %H:%M:%S", YMDHM = "%Y/%m/%d %H:%M", MDHMS = "%m/%d %H:%M:%S", MDHM = "%m/%d %H:%M", YMD = "%Y/%m/%d", HMS = "%H:%M:%S", MD = "%m/%d", HM = "%H:%M", MS = "%M:%S", } Time_Utility.FormatDateTable = { ["vn"] = { ["%Y/%m/%d %H:%M:%S"] = "%H:%M:%S %d/%m/%Y", ["%Y/%m/%d %H:%M"] = "%H:%M %d/%m/%Y", ["%m/%d %H:%M:%S"] = "%H:%M:%S %d/%m", ["%m/%d %H:%M"] = "%H:%M %d/%m", ["%Y/%m/%d"] = "%d/%m/%Y", ["%H:%M:%S"] = "%H:%M:%S", ["%m/%d"] = "%d/%m", ["%H:%M"] = "%H:%M", ["%M:%S"] = "%M:%S", } } -- 此方法为专用复写 os.date 方法,用于强行规定游戏内所有自定义时间格式的展示情况。 -- os.date 复写之后只能接受 Time_Utility.FormatDateTable 里面的枚举时间格式。 function Time_Utility.FormatDateForRegions(format, date) if format == Time_Utility.FormatDateEnum.YMDHMS or format == Time_Utility.FormatDateEnum.YMDHM or format == Time_Utility.FormatDateEnum.MDHMS or format == Time_Utility.FormatDateEnum.MDHM or format == Time_Utility.FormatDateEnum.YMD or format == Time_Utility.FormatDateEnum.HMS or format == Time_Utility.FormatDateEnum.MD or format == Time_Utility.FormatDateEnum.HM or format == Time_Utility.FormatDateEnum.MS then if GameAppInfo.IsVietnamPackage() then return private.originalDate(Time_Utility.FormatDateTable[GameAppInfo.Global_PackageType][format], date) else return private.originalDate(format, date) end else logging.error(LTAG.ERROR, "[FormatDateForRegions] Please Check Time_Utility.FormatDateEnum Or Call the UTL.Time.OsDateOriginal Method!") end end -- 此方法为 lua 的 os.date 方法,用于处理非自定义时间格式的情况,例如“%w”,"*t"这种情况。 function Time_Utility.OsDateOriginal(format, date) return private.originalDate(format, date) end function Time_Utility.GetWeekNum(week) if week == 1 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_Monday) elseif week == 2 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_Tuesday) elseif week == 3 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_Wednesday) elseif week == 4 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_Thursday) elseif week == 5 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_Friday) elseif week == 6 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_Saturday) elseif week == 0 or week == 7 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_Sunday) end end -- 越南周一到周六带“周” 周日直接显示日 function Time_Utility.GetWeekTitleVN(week) if week == 0 or week == 7 then return true else return false end end -- 根据时间戳获取该时间戳所在天起始时间戳 function Time_Utility.GetDayStartTimestamp(timeStamp) if not timeStamp then timeStamp = Time_Utility.GetServerTimestamp() end local timeTable = Time_Utility.OsDateOriginal("*t", timeStamp) timeTable.hour = 0 timeTable.min = 0 timeTable.sec = 0 return os.time(timeTable) + DataSheetManager.TimeRefresh:GetDataByID(CrossDayTimeId).HMS end -- 根据当前服务器时间戳获,当前月份、天数、当月最多天数 -- 因为游戏中需要5点刷新,如果处于刷新前则返回前一天时间 function Time_Utility.GetCurDay() local timeStamp = private.LocalToServerDisplayDateTimestamp() if not Time_Utility.IsPassRefreshTime(Time_Utility.TimeType.DAILY) then timeStamp = timeStamp - Time_Utility.TotalSecondsOneDay end local year = Time_Utility.OsDateOriginal("%Y", timeStamp) local month = Time_Utility.OsDateOriginal("%m", timeStamp) local maxDay = Time_Utility.OsDateOriginal("%d", os.time({year = year, month = month + 1, day = 0})) return tonumber(month), tonumber(Time_Utility.OsDateOriginal("%d", timeStamp)), tonumber(maxDay), tonumber(year) end -----------------------------站在服务器的角度去判断(实际现在服务器的时间)------------------------------- --os.time需要注意,isdst:true则强制设置是夏令时,false,则不是夏令时,不设置则采用本地是不是夏令时决定 function Time_Utility.GetOsTimestamp(year, month, day, hour, min, sec) OSTimeTab.year = year OSTimeTab.month = month OSTimeTab.day = day OSTimeTab.hour = hour OSTimeTab.min = min OSTimeTab.sec = sec return os.time(OSTimeTab) end --设置服务器时区,计算本地和服务器时间差(秒) --拉公告的时候服务器会告知客户端服务器部署的时区 --记录两个时间戳的值,一个是本地的真正时区,一个是本地的显示时区,对于不在夏令时时间里的区域,两者是相等的 --如果玩家手动修改了本地的时区,进行校正:在服务器同步时间的时候,每半个小时校正一下时区,如果和上次不同则进行弹框提示 --修改方案:在服务器同步时间的时候,每半个小时校正一下时区,如果和上次不同则进行弹框提示,提示玩家重启游戏 function Time_Utility.SetTimeZoneByServer(timeZone, serverTimestamp) ServerTimeStamp = serverTimestamp ServerTimeZone = timeZone local _localTimeZoneTimestamp, _displayTimeZoneTimestamp = private.GetLocalTimeZoneTimestamp(serverTimestamp) LocalTimeZone = _localTimeZoneTimestamp/Time_Utility.TotalSecondsOneHour DisplayLocalTimeZone = _displayTimeZoneTimestamp/Time_Utility.TotalSecondsOneHour --计算服务器和客户端物理上时区的时间差 logging.crit(LTAG.CRIT, "LocalTimeZone", LocalTimeZone,"DisplayLocalTimeZone", DisplayLocalTimeZone, "ServerTimeZone", ServerTimeZone) LocalServerDiffSeconds = (LocalTimeZone-ServerTimeZone) * Time_Utility.TotalSecondsOneHour DisplayLocalServerDiffSeconds = (DisplayLocalTimeZone-ServerTimeZone) * Time_Utility.TotalSecondsOneHour private.hasSetServerTimeZone = true end --计算真实的本地的时间戳和显示上的时间戳,如果没有夏令时的区域,则返回的两者是相等的 function private.GetLocalTimeZoneTimestamp(timeStamp) local now = timeStamp or os.time() local localutcseconds = os.difftime(now, os.time(Time_Utility.OsDateOriginal("!*t", now))) local isdst = Time_Utility.OsDateOriginal("*t", now).isdst if isdst then return localutcseconds, localutcseconds + Time_Utility.TotalSecondsOneHour else return localutcseconds, localutcseconds end end --获取当前时区与服务器时辰的差距,和时辰戳有关的使用此接口 function Time_Utility.GetDisplayDiffLocalTimeZone() return DisplayLocalServerDiffSeconds end --获取当前时区 function Time_Utility.GetLocalTimeZone() return LocalTimeZone end function Time_Utility.OnApplicationPause(pause) if not pause and private.hasSetServerTimeZone then private.CheckTimeZone() end end function private.CheckTimeZone() local _localTimeZoneTimestamp, _displayTimeZoneTimestamp = private.GetLocalTimeZoneTimestamp(Time_Utility.GetServerTimestamp()) local newDisplayTimeZoneTimestamp = _displayTimeZoneTimestamp/Time_Utility.TotalSecondsOneHour if newDisplayTimeZoneTimestamp ~= DisplayLocalTimeZone then logging.error(LTAG.ERROR, "时区不一致,提示玩家重新启动游戏", DisplayLocalTimeZone, newDisplayTimeZoneTimestamp) UTL.MessageBox.ShowOnlyOkNoCloseBox(Const_IDS.IDS_WARNING, Const_IDS.IDS_Timezone_Tips, function() LuaNetManager.RebootGame() end, nil) end end --获取服务器时间戳,如果服务器不调时间则服务器的时间戳和本地的os.time()其实是相等的 function Time_Utility.GetServerTimestamp() --初始化 if LastOSTime == nil then LastOSTime = Time_Utility.GetLocalTimestamp() end if ServerTimeStamp == nil then ServerTimeStamp = Time_Utility.GetLocalTimestamp() end -- 根据lua的os时间的偏差和 上次的服务器时间,本地计算服务器时间 local currentOSTime = Time.realtimeSinceStartup return ServerTimeStamp + math.floor(currentOSTime - LastOSTime) end --伴随着服务器心跳更新时间戳 function Time_Utility.UpdateServerTimestamp(timestamp) if timestamp and timestamp > 0 then ServerTimeStamp = timestamp LastOSTime = Time.realtimeSinceStartup if private.lastTimeZoneCheckTime == 0 then private.lastTimeZoneCheckTime = ServerTimeStamp end if private.hasSetServerTimeZone and ServerTimeStamp-private.lastTimeZoneCheckTime>TimeZoneCheckInterval then private.lastTimeZoneCheckTime = ServerTimeStamp private.CheckTimeZone() end end end --获取本地时间戳,和服务器的时间戳其实是相等的 function Time_Utility.GetLocalTimestamp() return os.time() end --判断时间戳是否跨天(5点) --将localTimeStamp转换为服务器时间后,拿到距离0点的时间,算出距离5点刷新点的时间差 --和距离服务器的时间进行比较 function Time_Utility.IsTimestampCrossDay(localTimeStamp) local serverTimestamp = localTimeStamp - Time_Utility.GetDisplayDiffLocalTimeZone() local curDate = Time_Utility.OsDateOriginal("*t", serverTimestamp) local offsetHMS = curDate.hour*Time_Utility.TotalSecondsOneHour + curDate.min*Time_Utility.TotalSecondsOneMinute+curDate.sec local crossDayHMS = DataSheetManager.TimeRefresh:GetDataByID(CrossDayTimeId).HMS local crossOffsetTime = 0 if offsetHMS < crossDayHMS then crossOffsetTime = crossDayHMS - offsetHMS else crossOffsetTime = Time_Utility.TotalSecondsOneDay - offsetHMS + crossDayHMS end local interval_Now = Time_Utility.GetServerTimestamp() - localTimeStamp return interval_Now >= crossOffsetTime end -----------------------------站在服务器的角度去判断(实际现在服务器的时间)------------------------------- --本地转为成服务器相同的日期(XX年XX月XX日XX时XX分XX秒)的时间戳 function private.LocalToServerDisplayDateTimestamp() return Time_Utility.GetServerTimestamp()-Time_Utility.GetDisplayDiffLocalTimeZone() end function private.GetWeekday(timeStamp) local curDate = Time_Utility.OsDateOriginal("*t", timeStamp) local weekDay = tonumber(curDate.wday) - 1 if weekDay == 0 then weekDay = 7 end return weekDay end --获取服务器当前周几 function Time_Utility.GetServerWeekday() return private.GetWeekday(private.LocalToServerDisplayDateTimestamp()) end --获取当前服务器零点的时间戳 function Time_Utility.GetServerZeroTimestamp() return Time_Utility.GetServerTimestamp()-Time_Utility.GetServerSecondsIntervalFromZero() end --获取当前服务器零点的时间戳,serverTimestamp服务器的时间戳 function Time_Utility.GetServerZeroTimestampByTimestamp(serverTimestamp) local localToServerDataTimestamp = serverTimestamp-Time_Utility.GetDisplayDiffLocalTimeZone() local curDate = Time_Utility.OsDateOriginal("*t", localToServerDataTimestamp) --已经转换成和服务器显示时间相同了,直接时分秒计算即可 return serverTimestamp - (curDate.hour*Time_Utility.TotalSecondsOneHour + curDate.min*Time_Utility.TotalSecondsOneMinute+curDate.sec) end --获取当前服务器时间距离零点过了多长时间 function Time_Utility.GetServerSecondsIntervalFromZero() local localToServerDataTimestamp = private.LocalToServerDisplayDateTimestamp() local curDate = Time_Utility.OsDateOriginal("*t", localToServerDataTimestamp) --已经转换成和服务器显示时间相同了,直接时分秒计算即可 return curDate.hour*Time_Utility.TotalSecondsOneHour + curDate.min*Time_Utility.TotalSecondsOneMinute+curDate.sec end -- 服务器是否在开放时间内 function Time_Utility.IsServerInOpeningTime(startTime, endTime, isHot) local startTimeRefreshCfg, endTimeRefreshCfg if isHot then startTimeRefreshCfg = MDL.OperationActivity.HotTimeRefresh:GetDataByID(startTime) endTimeRefreshCfg = MDL.OperationActivity.HotTimeRefresh:GetDataByID(endTime) else startTimeRefreshCfg = DataSheetManager.TimeRefresh:GetDataByID(startTime) if endTime and endTime>0 then endTimeRefreshCfg = DataSheetManager.TimeRefresh:GetDataByID(endTime) end end local serverSecondsIntervalFromZero = Time_Utility.GetServerSecondsIntervalFromZero() if startTimeRefreshCfg.Timer == Time_Utility.TimeType.DAILY then local endTimeHMS = endTimeRefreshCfg.HMS local startTimeHMS = startTimeRefreshCfg.HMS if startTimeHMS <= endTimeHMS then return serverSecondsIntervalFromZero >= startTimeHMS and serverSecondsIntervalFromZero < endTimeHMS end -- 跨天活动 return serverSecondsIntervalFromZero < endTimeHMS or serverSecondsIntervalFromZero >= startTimeHMS elseif startTimeRefreshCfg.Timer == Time_Utility.TimeType.WEEKLY then local serverWeekday = Time_Utility.GetServerWeekday() if serverWeekday ~= startTimeRefreshCfg.Day then return false end return serverSecondsIntervalFromZero >= startTimeRefreshCfg.HMS and serverSecondsIntervalFromZero < endTimeRefreshCfg.HMS elseif startTimeRefreshCfg.Timer == Time_Utility.TimeType.LIFETIME then local startTime = Time_Utility.GetOsTimestamp(startTimeRefreshCfg.Year, startTimeRefreshCfg.Month, startTimeRefreshCfg.Day, 0, 0, 0) startTime = startTime + startTimeRefreshCfg.HMS + Time_Utility.GetDisplayDiffLocalTimeZone() local nowTime = Time_Utility.GetServerTimestamp() if endTimeRefreshCfg then local endTime = Time_Utility.GetOsTimestamp(endTimeRefreshCfg.Year, endTimeRefreshCfg.Month, endTimeRefreshCfg.Day, 0, 0, 0) endTime = endTime + endTimeRefreshCfg.HMS + Time_Utility.GetDisplayDiffLocalTimeZone() return nowTime >= startTime and nowTime < endTime end return nowTime >= startTime end return false end --服务器是否在结束和刷新之间的时间内(刷新时间通用每周一凌晨5点和每日凌晨五点) function Time_Utility.IsServerInEndAndRefreshTime(startAndEndTime) local endTimeRefreshCfg = DataSheetManager.TimeRefresh:GetDataByID(startAndEndTime.EndTime) local serverSecondsIntervalFromZero = Time_Utility.GetServerSecondsIntervalFromZero() local refreshTimeCfg = nil if endTimeRefreshCfg.Timer == Time_Utility.TimeType.DAILY then refreshTimeCfg = DataSheetManager.TimeRefresh:GetDataByID(1) if serverSecondsIntervalFromZero<=refreshTimeCfg.HMS or serverSecondsIntervalFromZero>=endTimeRefreshCfg.HMS then return true end elseif endTimeRefreshCfg.Timer == Time_Utility.TimeType.WEEKLY then refreshTimeCfg = DataSheetManager.TimeRefresh:GetDataByID(2) local serverWeekday = Time_Utility.GetServerWeekday() if serverWeekday > endTimeRefreshCfg.Day then return true end if serverWeekday == 1 and serverSecondsIntervalFromZero <= refreshTimeCfg.HMS then return true end if serverWeekday == endTimeRefreshCfg.Day then return serverSecondsIntervalFromZero >= endTimeRefreshCfg.HMS end end return false end -- 判断时间戳是否过了刷新事件(刷新时间通用每周一凌晨5点和每日凌晨五点,读表) function Time_Utility.IsPassRefreshTime(timeType) local serverSecondsIntervalFromZero = Time_Utility.GetServerSecondsIntervalFromZero() if timeType == Time_Utility.TimeType.DAILY then local refreshTimeCfg = DataSheetManager.TimeRefresh:GetDataByID(1) if serverSecondsIntervalFromZero >= refreshTimeCfg.HMS then return true end elseif timeType == Time_Utility.TimeType.WEEKLY then local refreshTimeCfg = DataSheetManager.TimeRefresh:GetDataByID(2) local serverWeekday = Time_Utility.GetServerWeekday() if serverWeekday > refreshTimeCfg.Day then return true end if serverWeekday == 1 and serverSecondsIntervalFromZero >= refreshTimeCfg.HMS then return true end if serverWeekday == refreshTimeCfg.Day then return serverSecondsIntervalFromZero >= refreshTimeCfg.HMS end end return false end --根据TimeRefresh配置获取服务器某一时刻的时间戳 function Time_Utility.GetServerTimestampByTimeId(timeId) local serverZeroTimestamp = Time_Utility.GetServerZeroTimestamp() local timeRefreshCfg = DataSheetManager.TimeRefresh:GetDataByID(timeId) return serverZeroTimestamp+timeRefreshCfg.HMS end --配置时间距离服务器当前时间间隔,比如距离晚上八点的时间 function Time_Utility.GetServerIntervalTimeByTimeId(timeId, isHot) local timeRefreshCfg if isHot then timeRefreshCfg = MDL.OperationActivity.HotTimeRefresh:GetDataByID(timeId) else timeRefreshCfg = DataSheetManager.TimeRefresh:GetDataByID(timeId) end local serverSecondsIntervalFromZero = Time_Utility.GetServerSecondsIntervalFromZero() if timeRefreshCfg.Timer == Time_Utility.TimeType.DAILY then return timeRefreshCfg.HMS - serverSecondsIntervalFromZero elseif timeRefreshCfg.Timer == Time_Utility.TimeType.WEEKLY then local serverWeekday = Time_Utility.GetServerWeekday() if serverWeekday == timeRefreshCfg.Day then return timeRefreshCfg.HMS - serverSecondsIntervalFromZero elseif serverWeekday < timeRefreshCfg.Day then return timeRefreshCfg.HMS - serverSecondsIntervalFromZero+(timeRefreshCfg.Day-serverWeekday) * Time_Utility.TotalSecondsOneDay else return -serverSecondsIntervalFromZero+timeRefreshCfg.HMS - Time_Utility.TotalSecondsOneDay + (timeRefreshCfg.Day-serverWeekday+1) * Time_Utility.TotalSecondsOneDay end elseif timeRefreshCfg.Timer == Time_Utility.TimeType.LIFETIME then local time = Time_Utility.GetOsTimestamp(timeRefreshCfg.Year, timeRefreshCfg.Month, timeRefreshCfg.Day, 0, 0, 0)+Time_Utility.GetDisplayDiffLocalTimeZone() return time + timeRefreshCfg.HMS - Time_Utility.GetServerTimestamp() end end --服务器距离刷新时间的秒数(每日的,第二天五点,周的每周一五点) function Time_Utility.GetServerIntervalTimeToRefresh(timeId) local timeRefreshCfg = DataSheetManager.TimeRefresh:GetDataByID(timeId) local serverSecondsIntervalFromZero = Time_Utility.GetServerSecondsIntervalFromZero() local refreshTimeCfg = nil if timeRefreshCfg.Timer == Time_Utility.TimeType.DAILY then refreshTimeCfg = DataSheetManager.TimeRefresh:GetDataByID(1) if serverSecondsIntervalFromZero < refreshTimeCfg.HMS then return refreshTimeCfg.HMS-serverSecondsIntervalFromZero else return Time_Utility.TotalSecondsOneDay - serverSecondsIntervalFromZero + refreshTimeCfg.HMS end elseif timeRefreshCfg.Timer == Time_Utility.TimeType.WEEKLY then refreshTimeCfg = DataSheetManager.TimeRefresh:GetDataByID(2) local serverWeekday = Time_Utility.GetServerWeekday() if serverWeekday == refreshTimeCfg.Day and serverSecondsIntervalFromZero <= refreshTimeCfg.HMS then return refreshTimeCfg.HMS - serverSecondsIntervalFromZero elseif serverWeekday < refreshTimeCfg.Day then return refreshTimeCfg.HMS - serverSecondsIntervalFromZero+(refreshTimeCfg.Day-serverWeekday-1) * Time_Utility.TotalSecondsOneDay else return Time_Utility.TotalSecondsOneDay - serverSecondsIntervalFromZero + refreshTimeCfg.HMS + (refreshTimeCfg.Day+7-serverWeekday-1) * Time_Utility.TotalSecondsOneDay end end end --配置时间距离服务器当前时间间隔(下一次) function Time_Utility.GetServerIntervalNextTimeByTimeId(timeId) local timeRefreshCfg = DataSheetManager.TimeRefresh:GetDataByID(timeId) local serverSecondsIntervalFromZero = Time_Utility.GetServerSecondsIntervalFromZero() if timeRefreshCfg.Timer == Time_Utility.TimeType.DAILY then if serverSecondsIntervalFromZero < timeRefreshCfg.HMS then return timeRefreshCfg.HMS - serverSecondsIntervalFromZero else return Time_Utility.TotalSecondsOneDay - serverSecondsIntervalFromZero + timeRefreshCfg.HMS end elseif timeRefreshCfg.Timer == Time_Utility.TimeType.WEEKLY then local serverWeekday = Time_Utility.GetServerWeekday() if serverWeekday == timeRefreshCfg.Day and serverSecondsIntervalFromZero <= timeRefreshCfg.HMS then return timeRefreshCfg.HMS - serverSecondsIntervalFromZero elseif serverWeekday < timeRefreshCfg.Day then return timeRefreshCfg.HMS - serverSecondsIntervalFromZero + (timeRefreshCfg.Day - serverWeekday) * Time_Utility.TotalSecondsOneDay else return Time_Utility.TotalSecondsOneDay - serverSecondsIntervalFromZero + timeRefreshCfg.HMS + (timeRefreshCfg.Day + 7 - serverWeekday - 1) * Time_Utility.TotalSecondsOneDay end end end function Time_Utility.GetGetWeekDesc(id) local data = DataSheetManager.TimeRefresh:GetDataByID(id) local calender = Localization.IsEnglish() and "" or UIUtils.GetLocalizedTxt(Const_IDS.IDS_Calendar_DayTitle) --英文不显示“周” local startTime, startType = Time_Utility.GetDiffLocalTimeZoneById(id) local date if startType == Time_Utility.TimeZoneType.PreDay then date = Time_Utility.GetWeekNum(data.Day - 1) --周几减一天 elseif startType == Time_Utility.TimeZoneType.Tomorrow then date = Time_Utility.GetWeekNum((data.Day + 1) % 7) -- 周几加一天 周日加一天 周一 else date = Time_Utility.GetWeekNum(data.Day) end return calender .. date end --获取timeStamp1-timeStamp2的游戏天数 --游戏中的跨天是按照凌晨5点算的(配置数据) --把timeStamp2回退到5点,如果是0-5之间,则回退到前一天的5点 function Time_Utility.GetGameDiffDayCount(timeStamp1, timeStamp2) local localToServerTimeStamp2 = timeStamp2 - Time_Utility.GetDisplayDiffLocalTimeZone() local curDate = Time_Utility.OsDateOriginal("*t", localToServerTimeStamp2) --timeStamp2FromZero距离0点的秒数 local timeStamp2FromZero = curDate.hour*Time_Utility.TotalSecondsOneHour + curDate.min*Time_Utility.TotalSecondsOneMinute+curDate.sec --(5)点距离0点的秒数 local gameCrossDaySeconds = DataSheetManager.TimeRefresh:GetDataByID(CrossDayTimeId).HMS if timeStamp2FromZero >= gameCrossDaySeconds then timeStamp2 = timeStamp2 - (timeStamp2FromZero - gameCrossDaySeconds) else timeStamp2 = timeStamp2 - (timeStamp2FromZero + Time_Utility.TotalSecondsOneDay - gameCrossDaySeconds) end return math.ceil((timeStamp1-timeStamp2)/Time_Utility.TotalSecondsOneDay) end -- 根据对应的TimeRefresh ID获取对应的时间戳 function Time_Utility.GetConfigTimestampById(id) local data = DataSheetManager.TimeRefresh:GetDataByID(id) if data.Timer == Time_Utility.TimeType.DAILY then return Time_Utility.GetServerZeroTimestamp() + data.HMS else OSTimeTab.year = data.Year OSTimeTab.month = data.Month OSTimeTab.day = data.Day OSTimeTab.hour = 0 OSTimeTab.min = 0 OSTimeTab.sec = data.HMS -- os.time(OSTimeTab) 这个值是有可能是 nil 的,因为 TimeRefresh 表里面很多活动没有年月返回值就是小于起始时间 -- 如果不做判空处理 接口外的计算就会直接报错卡死了 解决之前 40778 的报错问题 local timeStamp = os.time(OSTimeTab) if timeStamp == nil then return 0 else return timeStamp end end end return Time_Utility