⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hightime.cpp

📁 high time source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////////
//
// 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 + -