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

📄 goodtime.cpp

📁 这是VC++控制计算机时钟的一个例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "GoodTime.h"

/////////////////////////////////////////////////////////////////////////////
// CGoodTime - absolute time

CGoodTime::CGoodTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec,
	int nDST)
{
	struct tm atm;

#ifdef _DEBUG
   memset( &atm, 0xFF, sizeof(atm) );

   switch ( nMonth )
   {
      case 1:  // January
      case 3:  // March
      case 5:  // May
      case 7:  // July
      case 8:  // August
      case 10: // October
      case 12: // December
         ASSERT( nDay <= 31 );
         break;

      case 4:  // April
      case 6:  // June
      case 9:  // September
      case 11: // November
         ASSERT( nDay <= 30 );
         break;

      case 2:
         ASSERT( (nDay <= 28) || (IsLeapYear(nYear) && (nDay == 29)) );
         break;

      default: // Bad month
         ASSERT(FALSE);
   }
#endif

	atm.tm_sec = nSec;
	atm.tm_min = nMin;
	atm.tm_hour = nHour;
	ASSERT(nDay >= 1 && nDay <= 31);
	atm.tm_mday = nDay;
	ASSERT(nMonth >= 1 && nMonth <= 12);
	atm.tm_mon = nMonth - 1;        // tm_mon is 0 based
	ASSERT(nYear >= 1900);
	atm.tm_year = nYear - 1900;     // tm_year is 1900 based
   // Note: nDST < 0 we should adjust
 	atm.tm_isdst = nDST;
	atm.tm_isdst = nDST;
   // Set tm_yday and tm_wday
   SetDays( &atm );
	m_time = atm;
}

void CGoodTime::SetDays( tm *ptm )
{
   int   nDaysToMonth[12] = {
                            0,
                            31,
                            59, // Adjust for leap years later
                            90,
                            120,
                            151,
                            181,
                            212,
                            243,
                            273,
                            304,
                            334
                            };

   // The month should have been OK when we were called
   ASSERT( (ptm->tm_mon >= 0) && (ptm->tm_mon <= 11) );

   // Set the number of days since Jan 1
   ptm->tm_yday = nDaysToMonth[ptm->tm_mon] + ptm->tm_mday - 1;

   // Adjust for leap years
   if ( ( IsLeapYear( ptm->tm_year+1900 ) ) &&
        ( ptm->tm_mon > 1 ) )
   {
      ptm->tm_yday++;
   }

   // Calculate the number of days since AD 1
   long  nDayNum;
   int   nYear = ptm->tm_year + 1900;

   // Approximate the number of days since 1/1/1
   nDayNum = (nYear - 1) * 365;

   // Add days for the leap years
   nDayNum += (nYear - 1) / 4;

   // Subtract years which are divisible by 100
   nDayNum -= (nYear - 1) / 100;

   // But replace years which are divisible by 400
   nDayNum += (nYear - 1) / 400;

   // This class is 1900-based, but 1582 is algorithmically significant.
   ASSERT( nYear > 1582 );

   // But before 1582 all centuries were leap years. 
   // In 1582, Pope Gregory XIII mandated that October 4 would
   // be followed by October 15.  This accounts for those facts.
   nDayNum += 2;

   // Now add the days to this point this year
   nDayNum += ptm->tm_yday;

   // Finally, calculate the day of the week based on what we now know.
   ptm->tm_wday = (((nDayNum % 7) + 6) % 7);
}

CGoodTime::CGoodTime(WORD wDosDate, WORD wDosTime, int nDST)
{
	struct tm atm;
	atm.tm_sec = (wDosTime & ~0xFFE0) << 1;
	atm.tm_min = (wDosTime & ~0xF800) >> 5;
	atm.tm_hour = wDosTime >> 11;

	atm.tm_mday = wDosDate & ~0xFFE0;
	atm.tm_mon = ((wDosDate & ~0xFE00) >> 5) - 1;
	atm.tm_year = (wDosDate >> 9) + 80;
   // Note: nDST < 0 we should adjust
 	atm.tm_isdst = nDST;
   // Set tm_yday and tm_wday
   SetDays( &atm );
	m_time = atm;
}

CGoodTime::CGoodTime(const SYSTEMTIME& sysTime, int nDST)
{
	ASSERT(sysTime.wYear >= 1900);
	CGoodTime timeT(
		(int)sysTime.wYear, (int)sysTime.wMonth, (int)sysTime.wDay,
		(int)sysTime.wHour, (int)sysTime.wMinute, (int)sysTime.wSecond,
		nDST);
	*this = timeT;
}

CGoodTime::CGoodTime(const FILETIME& fileTime, int nDST)
{
	// first convert file time (UTC time) to local time
	FILETIME localTime;
	if (!FileTimeToLocalFileTime(&fileTime, &localTime))
	{
		memset( &m_time, 0, sizeof(m_time) );
		return;
	}

	// then convert that time to system time
	SYSTEMTIME sysTime;
	if (!FileTimeToSystemTime(&localTime, &sysTime))
	{
		memset( &m_time, 0, sizeof(m_time) );
		return;
	}

	// then convert the system time to a time_t (C-runtime local time)
	CGoodTime timeT(sysTime, nDST);
	*this = timeT;
}

CGoodTime PASCAL CGoodTime::GetCurrentTime()
// return the current system time
{
   SYSTEMTIME              curTime;

   // Find the current system time
   GetLocalTime( &curTime );

	return CGoodTime(curTime, _daylight);
}

static tm   s_tAdjusted;

struct tm* CGoodTime::GetGmtTm(struct tm* ptm) const
{
   // Start with local time
   memcpy( &s_tAdjusted, &m_time, sizeof(m_time) );

   // _timezone has the number of seconds different from local time to UCT
   long  lAdjusted = s_tAdjusted.tm_sec + _timezone;

   // Adjust the time.
   if ( lAdjusted < 60 )
   {
      // This is probably no time zone change, but play it safe
      s_tAdjusted.tm_sec = lAdjusted;
   }
   else
   {
      // Store the seconds
      s_tAdjusted.tm_sec = (lAdjusted % 60);

      // move to minutes
      lAdjusted /= 60;
      lAdjusted += s_tAdjusted.tm_min;

      // Look deeper
      if ( lAdjusted < 60 )
      {
         s_tAdjusted.tm_min = lAdjusted;
      }
      else
      {
         // Store the minutes
         s_tAdjusted.tm_min = (lAdjusted % 60);

         // move to hours
         lAdjusted /= 60;
         lAdjusted += s_tAdjusted.tm_hour;

         if ( lAdjusted < 24 )
         {
            // Change the hours
            s_tAdjusted.tm_hour = lAdjusted;
         }
         else
         {
            // Store the seconds
            s_tAdjusted.tm_hour = (lAdjusted % 24);
   
            // move to days
            lAdjusted /= 24;

            // We shouldn't change more than a day either way.
            ASSERT( ( lAdjusted < 2 ) && ( lAdjusted > -2 ) );

            // Adjust the day of the week and the day of the year
            s_tAdjusted.tm_yday += lAdjusted;
            if ( (s_tAdjusted.tm_wday + lAdjusted) >= 0)
            {
               s_tAdjusted.tm_wday += lAdjusted;
               s_tAdjusted.tm_wday %= 7;
            }
            else
            {
               s_tAdjusted.tm_wday = 7 + (s_tAdjusted.tm_wday + lAdjusted);
            }
            // Going from Jan 1 back and Dec 31 forward is handled below

            // What we just did should assure this
            ASSERT( (s_tAdjusted.tm_wday >= 0) && (s_tAdjusted.tm_wday <= 6) );

            // Add the current count
            lAdjusted += s_tAdjusted.tm_mday;

            // Find out how many days in the current month
            //    and the previous month
            int   nMaxDay;
            int   nMaxDayPrev;

            switch ( s_tAdjusted.tm_mon )
            {
               case 0:  // January
               case 7:  // August
                  nMaxDay = 31;
                  nMaxDayPrev = 31;
                  break;

               case 4:  // May
               case 6:  // July
               case 9:  // October
               case 11: // December
                  nMaxDay = 31;
                  nMaxDayPrev = 30;
                  break;

               case 2:  // March
                  nMaxDay = 31;
                  if ( IsLeapYear( s_tAdjusted.tm_year + 1900 ) )
                  {
                     nMaxDayPrev = 29;
                  }
                  else
                  {
                     nMaxDayPrev = 28;
                  }
                  break;
                  

               case 3:  // April
               case 5:  // June
               case 8:  // September
               case 10: // November
                  nMaxDay = 30;
                  nMaxDayPrev = 31;
                  break;

               case 1:  // February made me shiver...
                  if ( IsLeapYear( s_tAdjusted.tm_year + 1900 ) )
                  {
                     nMaxDay = 29;
                  }
                  else
                  {
                     nMaxDay = 28;
                  }
                  nMaxDayPrev = 31;
   		        default: // Bad month 
			      nMaxDay = 0; 
 			      nMaxDayPrev = 0; 
                  break;
            }

            // Remember, we were about to replace the day of the month
            if ( lAdjusted < 1 ) 
            {
               s_tAdjusted.tm_mday = nMaxDayPrev;
               if ( s_tAdjusted.tm_mon == 0 )
               {
                  s_tAdjusted.tm_mon = 11;
                  s_tAdjusted.tm_year--;
                  s_tAdjusted.tm_yday = 365 + (IsLeapYear(s_tAdjusted.tm_year+1900)?1:0);
               }
               else
               {
                  s_tAdjusted.tm_mon++;
               }
            }
            else if ( lAdjusted > nMaxDay ) 
            {
               s_tAdjusted.tm_mday = 1;
               if ( s_tAdjusted.tm_mon < 11 )
               {
                  s_tAdjusted.tm_mon++;
               }
               else
               {
                  s_tAdjusted.tm_mon = 0;
                  s_tAdjusted.tm_year++;
                  s_tAdjusted.tm_yday = 0;
               }
            }
            else
            {
               s_tAdjusted.tm_mday = lAdjusted;
            }
         }
      }
   }

   if ( ptm != NULL )
   {
      *ptm = s_tAdjusted;
   }

   return &s_tAdjusted;
}

BOOL CGoodTime::IsLeapYear( int nYear )
{
   // This will work for years before 1900, but it won't
   //   work for tm_years which are 1900-based so that
   //   2000 is represented as 100. 
   ASSERT( nYear > 1900 );

   if ( (nYear % 4) != 0 )
   {
      // Years not divisible by four are not leap years
      return FALSE;
   }
   else
   {
      // Years divisible by 4 are leap years
      // Unless they are also divisible by 100
      // and not divisible by 400.
      // Pope Gregory XIII didn't like programmers.

      if ( (nYear % 100) != 0 )
      {
         return TRUE;
      }
      else
      {
         if ( (nYear % 400) != 0 )
         {
            return FALSE;
         }
         else
         {
            return TRUE;
         }
      }
   }
}

static tm s_time;

struct tm* CGoodTime::GetLocalTm(struct tm* ptm) const
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -