/*---------------------------------------------------------------------------------------------- Return a variant time from this SilTime. ----------------------------------------------------------------------------------------------*/ double SilTime::VarTime(void) const { double vtim; int64 msec; // Convert to local time. #if WIN32 msec = g_tmm.ToLcl(m_msec); #else // WIN32 msec = 0; // TODO-Linux: not called by views #endif // WIN32 // Convert to an automation date. vtim = (double)msec / kmsecPerDay + kvtimJanuary1st1601; // vtim is the actual number of days since 0000h 12/30/1899. // Convert this to a true Automation-style date. if (vtim < 0.0) { vtim = 2.0 * floor(vtim) - vtim; double vtimT = vtim - floor(vtim); if (vtimT <= kvtimHalfSecond && 0.0 < vtimT) vtim = ceil(vtim) + 1.0; } return vtim; }
/*---------------------------------------------------------------------------------------------- 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; }
/*---------------------------------------------------------------------------------------------- Set this SilTime to the indicated variant time. Variant time is always in local time. ----------------------------------------------------------------------------------------------*/ void SilTime::SetToVarTime(double vtim) { double dbl = vtim; // So that the arithmetic works even for negative dates, convert the // date to the _actual number of days_ since 0000h 12/30/1899. if (dbl < 0.0) dbl = 2.0 * ceil(dbl) - dbl; // Get the local time value. dbl = (dbl - kvtimJanuary1st1601) * kmsecPerDay; m_msec = g_tmm.ToUtc((int64)dbl); }
/*---------------------------------------------------------------------------------------------- Return the timezone offset: local time minus utc. ----------------------------------------------------------------------------------------------*/ int SilTime::TimeZoneOffset(void) const { #if WIN32 return (int)((g_tmm.ToLcl(m_msec) - m_msec) / kmsecPerMin); #else time_t t; struct tm *tm_lcl; time(&t); tm_lcl = localtime(&t); int64 bias = tm_lcl->tm_gmtoff; return (int) bias; #endif }
/*---------------------------------------------------------------------------------------------- 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 }
/*---------------------------------------------------------------------------------------------- Return the timezone offset: local time minus utc. ----------------------------------------------------------------------------------------------*/ int SilTime::TimeZoneOffset(void) const { return (int)((g_tmm.ToLcl(m_msec) - m_msec) / kmsecPerMin); }