📄 hightime.cpp
字号:
//////////////////////////////////////////////////////////////////////
//
// HighTime.cpp: implementation of the CHighTime and the CHighTimeSpan classes.
//
//////////////////////////////////////////////////////////////////////
//
// CHighTime and CHighTimeSpan are two classes for high resolution time
// The range is +/-29000 years and smallest step is 0.1 microsecond
// They works like COleDateTime and COleDateTimeSpan.
// I wrote these because MS could not write working time classes
//
// Author: Hakan Trygg, h.kan@home.se
// Classes are not to be sold for profit.
// Please send me a mail if you find it useful and using it
// Revision history:
// 1.0 : 12 Jan 2000 : /HT : Created
// 1.1 : 19 Jan 2000 : /HT : Made it possible to use classes without MFC
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HighTime.h"
#define LLABS(i) (((i)<0)?-(i):(i))
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define MAX_TIME_BUFFER_SIZE 128
// Constant array with months # of days of year
int CHighTime::anMonthDayInYear[13] = {0, 31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334, 365};
// Static member for getting the current time
const CHighTime CHighTime::GetPresentTime()
{
SYSTEMTIME systime;
::GetLocalTime(&systime);
return CHighTime(systime);
} // CHighTime::GetPresentTime()
CHighTime::CHighTime(int nYear, int nMonth, int nDay,
int nHour, int nMinute, int nSecond,
int nMilli , int nMicro ,int nNano)
// nMilli, nMicro & nNano default = 0
{
_HighTimeFormat SrcTime;
SrcTime.nYear = nYear;
SrcTime.nMonth = nMonth;
SrcTime.nDay = nDay;
SrcTime.nHour = nHour;
SrcTime.nMinute = nMinute;
SrcTime.nSecond = nSecond;
SrcTime.nMilli = nMilli;
SrcTime.nMicro = nMicro;
SrcTime.nNano = nNano;
m_status = ConvertTimeToLongLong(SrcTime, m_liTime) ? valid : invalid;
} // CHighTime::CHighTime()
// CHighTime operators
#if defined(USE_MFC)
const CHighTime& CHighTime::operator=(const COleDateTime& dateSrc)
{
_HighTimeFormat SrcTime;
SrcTime.nYear = dateSrc.GetYear();
SrcTime.nMonth = dateSrc.GetMonth();
SrcTime.nDay = dateSrc.GetDay();
SrcTime.nHour = dateSrc.GetHour();
SrcTime.nMinute = dateSrc.GetMinute();
SrcTime.nSecond = dateSrc.GetSecond();
SrcTime.nMilli = 0;
SrcTime.nMicro = 0;
SrcTime.nNano = 0;
m_status = ConvertTimeToLongLong(SrcTime, m_liTime) ? valid : invalid;
return *this;
} // CHighTime::operator=()
const CHighTime& CHighTime::operator=(const CTime& dateSrc)
{
_HighTimeFormat SrcTime;
SrcTime.nYear = dateSrc.GetYear();
SrcTime.nMonth = dateSrc.GetMonth();
SrcTime.nDay = dateSrc.GetDay();
SrcTime.nHour = dateSrc.GetHour();
SrcTime.nMinute = dateSrc.GetMinute();
SrcTime.nSecond = dateSrc.GetSecond();
SrcTime.nMilli = 0;
SrcTime.nMicro = 0;
SrcTime.nNano = 0;
m_status = ConvertTimeToLongLong(SrcTime, m_liTime) ? valid : invalid;
return *this;
} // CHighTime::operator=()
#endif
const CHighTime& CHighTime::operator=(const SYSTEMTIME& systimeSrc)
{
_HighTimeFormat SrcTime;
SrcTime.nYear = systimeSrc.wYear;
SrcTime.nMonth = systimeSrc.wMonth;
SrcTime.nDay = systimeSrc.wDay;
SrcTime.nHour = systimeSrc.wHour;
SrcTime.nMinute = systimeSrc.wMinute;
SrcTime.nSecond = systimeSrc.wSecond;
SrcTime.nMilli = systimeSrc.wMilliseconds;
SrcTime.nMicro = 0;
SrcTime.nNano = 0;
m_status = ConvertTimeToLongLong(SrcTime, m_liTime) ? valid : invalid;
return *this;
} // CHighTime::operator=()
const CHighTime& CHighTime::operator=(const FILETIME& filetimeSrc)
{
SYSTEMTIME systime;
if (FileTimeToSystemTime(&filetimeSrc, &systime)) {
_HighTimeFormat SrcTime;
SrcTime.nYear = systime.wYear;
SrcTime.nMonth = systime.wMonth;
SrcTime.nDay = systime.wDay;
SrcTime.nHour = systime.wHour;
SrcTime.nMinute = systime.wMinute;
SrcTime.nSecond = systime.wSecond;
SrcTime.nMilli = systime.wMilliseconds;
SrcTime.nMicro = 0;
SrcTime.nNano = 0;
m_status = ConvertTimeToLongLong(SrcTime, m_liTime) ? valid : invalid;
}
else {
SetStatus(invalid);
}
return *this;
} // CHighTime::operator=()
const CHighTime& CHighTime::operator=(const time_t& timeSrc)
{
tm *pTimeSrc = localtime(&timeSrc);
if (pTimeSrc) {
_HighTimeFormat SrcTime;
SrcTime.nYear = pTimeSrc->tm_year+1900;
SrcTime.nMonth = pTimeSrc->tm_mon+1;
SrcTime.nDay = pTimeSrc->tm_mday;
SrcTime.nHour = pTimeSrc->tm_hour;
SrcTime.nMinute = pTimeSrc->tm_min;
SrcTime.nSecond = pTimeSrc->tm_sec;
SrcTime.nMilli = 0;
SrcTime.nMicro = 0;
SrcTime.nNano = 0;
m_status = ConvertTimeToLongLong(SrcTime, m_liTime) ? valid : invalid;
}
else {
// Local time must have failed (timsSrc before 1/1/70 12am)
SetStatus(invalid);
ASSERT(FALSE);
}
return *this;
} // CHighTime::operator=(time_t)
int CHighTime::SetDateTime(int nYear, int nMonth, int nDay,
int nHour, int nMinute, int nSecond,
int nMilli, int nMicro, int nNano)
// nMilli, nMicro & nHundredsNano default = 0
{
_HighTimeFormat SrcTime;
SrcTime.nYear = nYear;
SrcTime.nMonth = nMonth;
SrcTime.nDay = nDay;
SrcTime.nHour = nHour;
SrcTime.nMinute = nMinute;
SrcTime.nSecond = nSecond;
SrcTime.nMilli = nMilli;
SrcTime.nMicro = nMicro;
SrcTime.nNano = nNano;
return (m_status = ConvertTimeToLongLong(SrcTime, m_liTime) ? valid : invalid) == valid;
} // CHighTime::SetDateTime()
// HighTime helper function, static function
BOOL CHighTime::ConvertTimeToLongLong(const _HighTimeFormat &SrcTime,
LARGE_INTEGER &liDestTime)
{
LARGE_INTEGER nDate;
int iDays = SrcTime.nDay;
UINT nHour = SrcTime.nHour;
UINT nMinute = SrcTime.nMinute;
UINT nSecond = SrcTime.nSecond;
UINT nMilliSecond = SrcTime.nMilli;
UINT nMicroSecond = SrcTime.nMicro;
UINT nHundredsNano = (SrcTime.nNano +50) / 100;
// Validate year and month
if (SrcTime.nYear > 29000 || SrcTime.nYear < -29000 ||
SrcTime.nMonth < 1 || SrcTime.nMonth > 12)
return FALSE;
// Check for leap year
BOOL bIsLeapYear = ((SrcTime.nYear & 3) == 0) &&
((SrcTime.nYear % 100) != 0 || (SrcTime.nYear % 400) == 0);
/*int nDaysInMonth =
anMonthDayInYear[SrcTime.nMonth] - anMonthDayInYear[SrcTime.nMonth-1] +
((bIsLeapYear && SrcTime.nDay == 29 && SrcTime.nMonth == 2) ? 1 : 0);*/
// Adjust time and frac time
nMicroSecond += nHundredsNano / 10;
nHundredsNano %= 10;
nMilliSecond += nMicroSecond / 1000;
nMicroSecond %= 1000;
nSecond +=nMilliSecond / 1000;
nMilliSecond %= 1000;
nMinute += nSecond / 60;
nSecond %= 60;
nHour += nMinute / 60;
nMinute %= 60;
iDays += nHour / 24;
nHour %= 24;
//It is a valid date; make Jan 1, 1AD be 1
nDate.QuadPart = SrcTime.nYear*365L + SrcTime.nYear/4 - SrcTime.nYear/100 + SrcTime.nYear/400 +
anMonthDayInYear[SrcTime.nMonth-1] + iDays;
// If leap year and it's before March, subtract 1:
if (SrcTime.nMonth <= 2 && bIsLeapYear)
--nDate.QuadPart;
// Offset so that 01/01/1601 is 0
nDate.QuadPart -= 584754L;
// Change nDate to seconds
nDate.QuadPart *= 86400L;
nDate.QuadPart += (nHour * 3600L) + (nMinute * 60L) + nSecond;
// Change nDate to hundreds of nanoseconds
nDate.QuadPart *= 10000000L;
nDate.QuadPart += (nMilliSecond * 10000L) + (nMicroSecond * 10L) + nHundredsNano;
liDestTime = nDate;
return TRUE;
} // CHighTime::ConvertTimeToLongLong()
BOOL CHighTime::ConvertLongLongToTime(const LARGE_INTEGER &liSrcTime,
_HighTimeFormat &DestTime)
{
LARGE_INTEGER nTempTime;
long nDaysAbsolute; // Number of days since 1/1/0
long nSecsInDay; // Time in seconds since midnight
long nMinutesInDay; // Minutes in day
long n400Years; // Number of 400 year increments since 1/1/0
long n400Century; // Century within 400 year block (0,1,2 or 3)
long n4Years; // Number of 4 year increments since 1/1/0
long n4Day; // Day within 4 year block
// (0 is 1/1/yr1, 1460 is 12/31/yr4)
long n4Yr; // Year within 4 year block (0,1,2 or 3)
BOOL bLeap4 = TRUE; // TRUE if 4 year block includes leap year
long nHNanosThisDay;
long nMillisThisDay;
nTempTime = liSrcTime;
nHNanosThisDay = (long)(nTempTime.QuadPart % 10000000L);
nTempTime.QuadPart /= 10000000L;
nSecsInDay = (long)(nTempTime.QuadPart % 86400L);
nTempTime.QuadPart /= 86400L;
nDaysAbsolute = (long)(nTempTime.QuadPart);
nDaysAbsolute += 584754L; // Add days from 1/1/0 to 01/01/1601
// Calculate the day of week (sun=1, mon=2...)
// -1 because 1/1/0 is Sat. +1 because we want 1-based
DestTime.nDayOfWeek = (int)((nDaysAbsolute - 1) % 7L) + 1;
// Leap years every 4 yrs except centuries not multiples of 400.
n400Years = (long)(nDaysAbsolute / 146097L);
// Set nDaysAbsolute to day within 400-year block
nDaysAbsolute %= 146097L;
// -1 because first century has extra day
n400Century = (long)((nDaysAbsolute - 1) / 36524L);
// Non-leap century
if (n400Century != 0)
{
// Set nDaysAbsolute to day within century
nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;
// +1 because 1st 4 year increment has 1460 days
n4Years = (long)((nDaysAbsolute + 1) / 1461L);
if (n4Years != 0)
n4Day = (long)((nDaysAbsolute + 1) % 1461L);
else
{
bLeap4 = FALSE;
n4Day = (long)nDaysAbsolute;
}
}
else
{
// Leap century - not special case!
n4Years = (long)(nDaysAbsolute / 1461L);
n4Day = (long)(nDaysAbsolute % 1461L);
}
if (bLeap4)
{
// -1 because first year has 366 days
n4Yr = (n4Day - 1) / 365;
if (n4Yr != 0)
n4Day = (n4Day - 1) % 365;
}
else
{
n4Yr = n4Day / 365;
n4Day %= 365;
}
// n4Day is now 0-based day of year. Save 1-based day of year, year number
DestTime.nDayOfYear = (int)n4Day + 1;
DestTime.nYear = n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr;
// Handle leap year: before, on, and after Feb. 29.
if (n4Yr == 0 && bLeap4)
{
// Leap Year
if (n4Day == 59)
{
/* Feb. 29 */
DestTime.nMonth = 2;
DestTime.nDay = 29;
goto DoTime;
}
// Pretend it's not a leap year for month/day comp.
if (n4Day >= 60)
--n4Day;
}
// Make n4DaY a 1-based day of non-leap year and compute
// month/day for everything but Feb. 29.
++n4Day;
// Month number always >= n/32, so save some loop time */
for (DestTime.nMonth = (n4Day >> 5) + 1;
n4Day > anMonthDayInYear[DestTime.nMonth]; DestTime.nMonth++);
DestTime.nDay = (int)(n4Day - anMonthDayInYear[DestTime.nMonth-1]);
DoTime:
if (nSecsInDay == 0)
DestTime.nHour = DestTime.nMinute = DestTime.nSecond = 0;
else
{
DestTime.nSecond = (UINT)nSecsInDay % 60L;
nMinutesInDay = nSecsInDay / 60L;
DestTime.nMinute = (UINT)nMinutesInDay % 60;
DestTime.nHour = (UINT)nMinutesInDay / 60;
}
if (nHNanosThisDay == 0)
DestTime.nMilli = DestTime.nMicro = DestTime.nNano = 0;
else
{
DestTime.nNano = (UINT)((nHNanosThisDay % 10L) * 100L);
nMillisThisDay = nHNanosThisDay / 10L;
DestTime.nMicro = (UINT)nMillisThisDay % 1000;
DestTime.nMilli = (UINT)nMillisThisDay / 1000;
}
return TRUE;
} // CHighTime::ConvertLongLongToTime()
void CHighTime::ConvertToStandardFormat(_HighTimeFormat &tmTempHigh, tm &tmSrc)
{
// Convert internal tm to format expected by runtimes (sfrtime, etc)
tmSrc.tm_year = tmTempHigh.nYear-1900; // year is based on 1900
tmSrc.tm_mon = tmTempHigh.nMonth-1; // month of year is 0-based
tmSrc.tm_wday = tmTempHigh.nDayOfWeek-1; // day of week is 0-based
tmSrc.tm_yday = tmTempHigh.nDayOfYear-1; // day of year is 0-based
tmSrc.tm_mday = tmTempHigh.nDay;
tmSrc.tm_hour = tmTempHigh.nHour;
tmSrc.tm_min = tmTempHigh.nMinute;
tmSrc.tm_sec = tmTempHigh.nSecond;
tmSrc.tm_isdst = 0;
} // CHighTime::ConvertToStandardFormat()
int CHighTime::GetYear() const
{
_HighTimeFormat tmTemp;
if (GetStatus() == valid && ConvertLongLongToTime(m_liTime, tmTemp))
return tmTemp.nYear;
else
return HIGH_DATETIME_ERROR;
} // CHighTime::GetYear()
int CHighTime::GetMonth() const // month of year (1 = Jan)
{
_HighTimeFormat tmTemp;
if (GetStatus() == valid && ConvertLongLongToTime(m_liTime, tmTemp))
return tmTemp.nMonth;
else
return HIGH_DATETIME_ERROR;
} // CHighTime::GetMonth()
int CHighTime::GetDay() const // day of month (0-31)
{
_HighTimeFormat tmTemp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -