/*---------------------------------------------------------------------------------------------- Core routine to map between local and Utc. This assumes that DST doesn't kick in near a year boundary so that when the switch happens, the DST and STD times are in the same year. ----------------------------------------------------------------------------------------------*/ int64 TimeMapper::MapMsec(int64 msecSrc, bool fToUtc) { int64 msecT; int msecDay; int day; int dayMin; int dyear; int yday; int yt; int ymin; // First determines the year type and minute within the year. // Mod to 400 year period. msecT = ModPos(msecSrc, kmsecPerPeriod); // Find the day within the 400 year period. day = (int)(msecT / kmsecPerDay); Assert(0 <= day && day < kdayPerPeriod); // Get the time within the day. msecDay = (int)(msecT - day * (int64)kmsecPerDay); Assert(0 <= msecDay && msecDay < kmsecPerDay); // Find the year within the 400 year period (dyear) and the day within that year (yday). Assert(0 <= day && day < 146097); dyear = YearFromDayInPeriod(day, &yday); Assert(0 <= dyear && dyear < 400); Assert(0 <= yday && (yday < 365 || yday == 365 && SilTime::IsLeapYear(dyear + kyearBase))); // Calculate the day number (within the 400 year period) of the first day of // the year (dayMin). dayMin = day - yday; Assert(dayMin == DayFromYearInPeriod(dyear)); // Get the year type. kdayMonday is used because T0 is a Monday. yt = ModPos(dayMin + kwdayMonday, kdayPerWeek); if (SilTime::IsLeapYear(dyear + kyearBase)) yt += kdayPerWeek; // Calculate the minute within the year. ymin = yday * kminPerDay + msecDay / kmsecPerMin; if (!fToUtc) { // Mapping from utc to local. if (m_rgyminMin[yt] <= ymin && ymin < m_rgyminLim[yt]) return msecSrc + Mul(m_dminTz2, kmsecPerMin); return msecSrc + Mul(m_dminTz1, kmsecPerMin); } // The overlap is always ambiguous and there's nothing we can do about it. ymin -= m_dminTz2; if (m_rgyminMin[yt] <= ymin && ymin < m_rgyminLim[yt]) return msecSrc - Mul(m_dminTz2, kmsecPerMin); return msecSrc - Mul(m_dminTz1, kmsecPerMin); }
/*---------------------------------------------------------------------------------------------- Fill in the SilTimeInfo structure from this time. ----------------------------------------------------------------------------------------------*/ void SilTime::GetTimeInfo(SilTimeInfo * psti, bool fUtc) const { AssertPtr(psti); int dyear; int day; int msecDay; int yday; int64 msec = m_msec; if (!fUtc) msec = g_tmm.ToLcl(msec); // Decompose m_msec into which 400 year period it is in (relative to T0) and // the millisecond within the 400 year period. psti->year = (int)FloorDiv(msec, kmsecPerPeriod) * kyearPerPeriod + kyearBase; msec = ModPos(msec, kmsecPerPeriod); Assert(0 <= 0 && msec < kmsecPerPeriod); // Find the day within the 400 year period. day = (int)(msec / kmsecPerDay); Assert(0 <= day && day < kdayPerPeriod); // Get the time within the day. msecDay = (int)(msec - day * (int64)kmsecPerDay); Assert(0 <= msecDay && msecDay < kmsecPerDay); // Find the year within the 400 year period (dyear) and the day within that year (yday). Assert(0 <= day && day < 146097); dyear = YearFromDayInPeriod(day, &yday); Assert(0 <= dyear && dyear < 400); Assert(0 <= yday && (yday < 365 || yday == 365 && SilTime::IsLeapYear(dyear + kyearBase))); // Add dyear into the year. psti->year += dyear; // Find the month and day in the month. const int * prgday = g_rgyday[IsLeapYear(psti->year)]; for (psti->ymon = 1; yday >= prgday[psti->ymon]; psti->ymon++) ; psti->mday = yday - prgday[psti->ymon - 1] + 1; // Calculate the week day. // kdayMonday is used because T0 is a Monday. Note that kdayPerPeriod is divisible by 7 // so we don't have to adjust the day of the week. psti->wday = ModPos(day + kwdayMonday, kdayPerWeek); // Fill in the time. psti->hour = msecDay / kmsecPerHour; psti->min = (msecDay % kmsecPerHour) / kmsecPerMin; psti->sec = (msecDay % kmsecPerMin) / kmsecPerSec; psti->msec = msecDay % kmsecPerSec; }
float LerpMod(float a, float b, float mod, float t) { a = ModPos(a, mod); b = ModPos(b, mod); if (Abs(b-a) * 2.f <= mod) return Lerp(a, b, t); else { if (a < b) return ModPos(Lerp(a + mod, b, t), mod); else return ModPos(Lerp(a, b + mod, t), mod); } }
/*---------------------------------------------------------------------------------------------- Set the value of this SilTime according to the information in psti. ----------------------------------------------------------------------------------------------*/ void SilTime::SetTimeInfo(const SilTimeInfo & sti, bool fUtc) { int dyear = sti.year + FloorDiv(sti.ymon - 1, kmonPerYear) - kyearBase; int mon = ModPos(sti.ymon - 1, kmonPerYear); // Calculate the day number. int64 day = (int64)365 * dyear + FloorDiv(dyear, 4) - FloorDiv(dyear, 100) + FloorDiv(dyear, 400) + g_rgyday[IsLeapYear(dyear + kyearBase)][mon] + sti.mday - 1; m_msec = day * kmsecPerDay + sti.hour * (int64)kmsecPerHour + sti.min * (int64)kmsecPerMin + sti.sec * (int64)kmsecPerSec + sti.msec; if (!fUtc) m_msec = g_tmm.ToUtc(m_msec); }
/*---------------------------------------------------------------------------------------------- Set the value of this SilTime according to the information in psti. ----------------------------------------------------------------------------------------------*/ void SilTime::SetTimeInfo(const SilTimeInfo & sti, bool fUtc) { int dyear = sti.year + FloorDiv(sti.ymon - 1, kmonPerYear) - kyearBase; int mon = ModPos(sti.ymon - 1, kmonPerYear); // Calculate the day number. int64 day = (int64)365 * dyear + FloorDiv(dyear, 4) - FloorDiv(dyear, 100) + FloorDiv(dyear, 400) + g_rgyday[IsLeapYear(dyear + kyearBase)][mon] + sti.mday - 1; m_msec = day * kmsecPerDay + sti.hour * (int64)kmsecPerHour + sti.min * (int64)kmsecPerMin + sti.sec * (int64)kmsecPerSec + sti.msec; #if WIN32 if (!fUtc) m_msec = g_tmm.ToUtc(m_msec); #else // WIN32 if (!fUtc && (sti.year > 1970)) { m_msec *= kfttPerMsec; m_msec /= kfttPerSec; m_msec -= SECS_1601_TO_1970; time_t t = m_msec; struct tm *tm_lcl; tm_lcl = localtime(&t); int64 bias = tm_lcl->tm_gmtoff; m_msec += bias; m_msec += SECS_1601_TO_1970; m_msec *= kfttPerSec; m_msec /= kfttPerMsec; } #endif // WIN32 }
float ModPos(float x, int mod) { ///@todo Optimize. return ModPos(x, (float)mod); }