📄 datetimeformat.cpp
字号:
// DateTimeFormat.cpp: implementation of the CDateTimeFormat class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "NumericFormat.h"
#include "DateTimeFormat.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// Verifies will fail if the needed buffer size is too large
#define MAX_TIME_BUFFER_SIZE 128 // matches that in timecore.cpp
#define MIN_DATE (-657434L) // about year 100
#define MAX_DATE 2958465L // about year 9999
// Half a second, expressed in days
#define HALF_SECOND (1.0/172800.0)
BOOL CDateTimeFormat::m_bStaticInit = FALSE;
CString CDateTimeFormat::m_strMonAbbr [13],
CDateTimeFormat::m_strMonFull [13],
CDateTimeFormat::m_strDayAbbr [7],
CDateTimeFormat::m_strDayFull [7],
CDateTimeFormat::m_strAMPM [2];
int CDateTimeFormat::m_nMonthDays [13] =
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDateTimeFormat::CDateTimeFormat()
{
ClearCounters();
m_szRes[0] = 0;
m_pszBuf = m_szRes;
if(!m_bStaticInit)
StaticInit();
}
CDateTimeFormat::~CDateTimeFormat()
{
}
// CDateTimeFormat::StaticInit
//
// Initializes the static variables once
//
void CDateTimeFormat::StaticInit()
{
TCHAR szFmt[128];
int i;
LCTYPE lcDayAbbr[] = { LOCALE_SABBREVDAYNAME7, // Sunday
LOCALE_SABBREVDAYNAME1, // Monday
LOCALE_SABBREVDAYNAME2, // Tuesday
LOCALE_SABBREVDAYNAME3, // Wednesday
LOCALE_SABBREVDAYNAME4, // Thursday
LOCALE_SABBREVDAYNAME5, // Friday
LOCALE_SABBREVDAYNAME6 }; // Saturday
LCTYPE lcDayFull[] = { LOCALE_SDAYNAME7,
LOCALE_SDAYNAME1,
LOCALE_SDAYNAME2,
LOCALE_SDAYNAME3,
LOCALE_SDAYNAME4,
LOCALE_SDAYNAME5,
LOCALE_SDAYNAME6 };
LCTYPE lcMonAbbr[] = { LOCALE_SABBREVMONTHNAME1,
LOCALE_SABBREVMONTHNAME2,
LOCALE_SABBREVMONTHNAME3,
LOCALE_SABBREVMONTHNAME4,
LOCALE_SABBREVMONTHNAME5,
LOCALE_SABBREVMONTHNAME6,
LOCALE_SABBREVMONTHNAME7,
LOCALE_SABBREVMONTHNAME8,
LOCALE_SABBREVMONTHNAME9,
LOCALE_SABBREVMONTHNAME10,
LOCALE_SABBREVMONTHNAME11,
LOCALE_SABBREVMONTHNAME12,
LOCALE_SABBREVMONTHNAME13 };
LCTYPE lcMonFull[] = { LOCALE_SMONTHNAME1,
LOCALE_SMONTHNAME2,
LOCALE_SMONTHNAME3,
LOCALE_SMONTHNAME4,
LOCALE_SMONTHNAME5,
LOCALE_SMONTHNAME6,
LOCALE_SMONTHNAME7,
LOCALE_SMONTHNAME8,
LOCALE_SMONTHNAME9,
LOCALE_SMONTHNAME10,
LOCALE_SMONTHNAME11,
LOCALE_SMONTHNAME12,
LOCALE_SMONTHNAME13 };
//
// Initialize the day names
//
for(i = 0; i < 7; ++i)
{
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, lcDayAbbr[i], szFmt, 127);
m_strDayAbbr[i] = szFmt;
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, lcDayFull[i], szFmt, 127);
m_strDayFull[i] = szFmt;
}
//
// Initialize the month names
//
for(i = 0; i < 13; i++)
{
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, lcMonAbbr[i], szFmt, 127);
m_strMonAbbr[i] = szFmt;
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, lcMonFull[i], szFmt, 127);
m_strMonFull[i] = szFmt;
}
//
// Initialize the AM/PM inidcators
//
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_S1159, szFmt, 127);
m_strAMPM[0] = szFmt;
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_S2359, szFmt, 127);
m_strAMPM[1] = szFmt;
m_bStaticInit = TRUE;
}
// CDateTimeFormat::ClearCounters
//
// Clears all the scanner's counters
//
void CDateTimeFormat::ClearCounters()
{
m_nd =
m_nM =
m_ny =
m_nw =
m_nq =
m_ng =
m_nh =
m_nH =
m_nm =
m_ns =
m_nt = 0;
}
// CDateTimeFormat::SetDateTime
//
// Sets the date and time values
// This code was adapted from Microsoft's
//
BOOL CDateTimeFormat::SetDateTime(const COleDateTime &odt)
{
long nDays; // Number of days since Dec. 30, 1899
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
double dblDate = odt.m_dt; // tempory serial date
/*
m_nYear = odt.GetYear();
m_nMonth = odt.GetMonth();
m_nDay = odt.GetDay();
m_nHour = odt.GetHour();
m_nMinute = odt.GetMinute();
m_nSecond = odt.GetSecond();
*/
//
// The legal range does not actually span year 0 to 9999.
//
if(odt.m_dt > MAX_DATE || odt.m_dt < MIN_DATE) // about year 100 to about 9999
return FALSE;
//
// If a valid date, then this conversion should not overflow
//
nDays = (long)dblDate;
//
// Round to the second
//
dblDate += ((odt.m_dt > 0.0) ? HALF_SECOND : -HALF_SECOND);
nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899
dblDate = fabs(dblDate);
nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.);
//
// Calculate the day of week (sun=1, mon=2...)
// -1 because 1/1/0 is Sat. +1 because we want 1-based
//
m_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
//
m_nDayOfYear = (int)n4Day + 1;
m_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 */
m_nMonth = 2;
m_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(m_nMonth = (n4Day >> 5) + 1;
n4Day > m_nMonthDays[m_nMonth]; ++m_nMonth);
m_nDay = (int)(n4Day - m_nMonthDays[m_nMonth-1]);
DoTime:
if(nSecsInDay == 0)
m_nHour = m_nMinute = m_nSecond = 0;
else
{
m_nSecond = (int)nSecsInDay % 60L;
nMinutesInDay = nSecsInDay / 60L;
m_nMinute = (int)nMinutesInDay % 60;
m_nHour = (int)nMinutesInDay / 60;
}
return TRUE;
}
// CDateTimeFormat::SetDateTime
//
// Sets the date and time values
//
void CDateTimeFormat::SetDateTime(const CTime &t)
{
m_nYear = t.GetYear();
m_nMonth = t.GetMonth();
m_nDay = t.GetDay();
m_nHour = t.GetHour();
m_nMinute = t.GetMinute();
m_nSecond = t.GetSecond();
}
#ifdef __oledb_h__
// CDateTimeFormat::SetDateTime
//
// Sets the time from a DBTIMESTAMP pointer
//
void CDateTimeFormat::SetDateTime(const DBTIMESTAMP &DbTs)
{
m_nYear = DbTs.year;
m_nMonth = DbTs.month;
m_nDay = DbTs.day;
m_nHour = DbTs.hour;
m_nMinute = DbTs.minute;
m_nSecond = DbTs.second;
}
#endif
// CDateTimeFormat::GetDayOfYear
//
// Returns the number of days in a year
//
int CDateTimeFormat::GetDayOfYear(int y, int m, int d)
{
int nDays[] = {31,28,31,30,31,30,31,31,30,31,30,31},
nTot = 0,
i;
//
// Loop through all the previous months.
// m_nMonth is in the 1-12 range
//
for(i = 0; i < m - 2; ++i)
nTot += nDays[i];
nTot += d;
if(IsLeapYear(y))
++nTot;
return nTot;
}
// CDateTimeFormat::GetDayOfWeek
//
// Calculate the day of week
//
int CDateTimeFormat::GetDayOfWeek(int y, int m, int d)
{
int nTot,
y1 = y - 1;
nTot = GetDayOfYear(y,m,d) + y1 + y1 / 4 - y1 / 100 + y1 / 400;
return nTot % 7;
}
// CDateTimeFormat::FormatDay
//
// Formats a day
//
void CDateTimeFormat::FormatDay()
{
TCHAR szFmt[8];
int n;
switch(m_nd)
{
case 1:
_tcscat(m_pszBuf, Format(m_nDay, szFmt, 8));
break;
case 2:
_tcscat(m_pszBuf, Format(m_nDay, szFmt, 8, 2));
break;
case 3:
n = GetDayOfWeek(m_nYear, m_nMonth, m_nDay);
_tcscat(m_pszBuf, m_strDayAbbr[n]);
break;
case 4:
n = GetDayOfWeek(m_nYear, m_nMonth, m_nDay);
_tcscat(m_pszBuf, m_strDayFull[n]);
break;
default:
_tcscat(m_pszBuf, _T("???"));
};
}
// CDateTimeFormat::FormatWeek
//
// Formats a week number
//
void CDateTimeFormat::FormatWeek()
{
TCHAR szFmt[8];
int nDayOfYear = GetDayOfYear(m_nYear, m_nMonth, m_nDay),
nDoy1 = GetDayOfYear(m_nYear, 1, 1),
nWeek;
nWeek = (nDayOfYear + nDoy1) / 7 + 1;
switch(m_nw)
{
case 1:
_tcscat(m_pszBuf, Format(nWeek, szFmt, 8));
break;
case 2:
_tcscat(m_pszBuf, Format(nWeek, szFmt, 8, 2));
break;
default:
_tcscat(m_pszBuf, _T("???"));
}
}
// CDateTimeFormat::FormatMonth
//
// Formats a month
//
void CDateTimeFormat::FormatMonth()
{
TCHAR szFmt[8];
switch(m_nM)
{
case 1:
_tcscat(m_pszBuf, Format(m_nMonth, szFmt, 8));
break;
case 2:
_tcscat(m_pszBuf, Format(m_nMonth, szFmt, 8, 2));
break;
case 3:
_tcscat(m_pszBuf, m_strMonAbbr[m_nMonth-1]);
break;
case 4:
_tcscat(m_pszBuf, m_strMonFull[m_nMonth-1]);
break;
default:
_tcscat(m_pszBuf, _T("???"));
}
}
// CDateTimeFormat::FormatQuarter
//
// Formats a quarter number
//
void CDateTimeFormat::FormatQuarter()
{
TCHAR szFmt[8];
switch(m_nq)
{
case 1:
_tcscat(m_pszBuf, Format((m_nMonth - 1) / 3 + 1, szFmt, 8));
break;
default:
_tcscat(m_pszBuf, _T("???"));
}
}
// CDateTimeFormat::FormatYear
//
// Formats a year
//
void CDateTimeFormat::FormatYear()
{
TCHAR szFmt[8];
switch(m_ny)
{
case 1:
_tcscat(m_pszBuf, Format(m_nYear, szFmt, 8));
break;
case 2:
_tcscat(m_pszBuf, Format(m_nYear % 100, szFmt, 8, 2));
break;
case 4:
_tcscat(m_pszBuf, Format(m_nYear, szFmt, 8, 4));
break;
default:
_tcscat(m_pszBuf, _T("???"));
};
}
// CDateTimeFormat::FormatHour
//
// Formats an hour
//
void CDateTimeFormat::FormatHour()
{
TCHAR szFmt[8];
int nHour = m_nHour;
int nDig;
//
// Check if we are formatting for a 12-hour clock
//
if(m_nh)
{
if(nHour > 12)
nHour -= 12;
nDig = m_nh;
}
else
nDig = m_nH;
switch(nDig)
{
case 1:
_tcscat(m_pszBuf, Format(nHour, szFmt, 8));
break;
case 2:
_tcscat(m_pszBuf, Format(nHour, szFmt, 8, 2));
break;
default:
_tcscat(m_pszBuf, _T("???"));
}
}
// CDateTimeFormat::FormatAMPM
//
// Inserts the AM / PM symbols
//
void CDateTimeFormat::FormatAMPM()
{
if(m_nt > 0 && m_nt < 3)
_tcscat(m_pszBuf, m_strAMPM[m_nHour < 12 ? 0 : 1]);
else
_tcscat(m_pszBuf, _T("???"));
}
// CDateTimeFormat::FormatSection
//
// Come here whenever a section is ready to be formatted
//
void CDateTimeFormat::FormatSection()
{
CString str;
if(m_nd)
{
FormatDay();
}
else if(m_nM)
{
FormatMonth();
}
else if(m_ny)
{
FormatYear();
}
else if(m_nq)
{
FormatQuarter();
}
else if(m_nw)
{
FormatWeek();
}
else if(m_ng)
{
// Not yet implemented
}
else if(m_nh || m_nH)
{
FormatHour();
}
else if(m_nm)
{
TCHAR szFmt[8];
_tcscat(m_pszBuf, Format(m_nMinute, szFmt, 8, m_nm == 1 ? 0 : 2));
}
else if(m_ns)
{
TCHAR szFmt[8];
_tcscat(m_pszBuf, Format(m_nSecond, szFmt, 8, m_ns == 1 ? 0 : 2));
}
else if(m_nt)
{
FormatAMPM();
}
else
_tcscat(m_pszBuf, _T("???") );
ClearCounters();
}
// CDateTimeFormat::SetFormat
//
// Set and scan the format string
// Generates the result string
//
void CDateTimeFormat::SetFormat(LPCTSTR pszFormat)
{
LPCTSTR p;
TCHAR c = 0;
BOOL fFmt = FALSE, // Formatting
fLit = FALSE; // Literal characters
TCHAR szChar[2] = {0, 0},
szLit[128] = {0};
TCHAR* pLit = szLit;
m_pszBuf[0] = 0; // Clear the string the C way
ClearCounters(); // Clear the internal counters
for(p = pszFormat; *p; p++)
{
//
// Scanning formats?
//
if(fFmt)
{
if(*p != c) // Did the format char changed?
{
if(szLit[0])
{
*pLit = 0;
wcscat(m_pszBuf, szLit);
pLit = szLit;
*pLit = 0;
}
FormatSection(); // So format the section,
fFmt = FALSE; // and say we are not formatting
}
}
c = *p;
//
// What literal mode?
//
if(!fLit)
{
//
// Not in literal mode
//
switch(c)
{
case _T('d'): m_nd++; fFmt = TRUE; break;
case _T('M'): m_nM++; fFmt = TRUE; break;
case _T('y'): m_ny++; fFmt = TRUE; break;
case _T('g'): m_ng++; fFmt = TRUE; break;
case _T('h'): m_nh++; fFmt = TRUE; break;
case _T('H'): m_nH++; fFmt = TRUE; break;
case _T('m'): m_nm++; fFmt = TRUE; break;
case _T('s'): m_ns++; fFmt = TRUE; break;
case _T('t'): m_nt++; fFmt = TRUE; break;
case _T('w'): m_nw++; fFmt = TRUE; break;
case _T('q'): m_nq++; fFmt = TRUE; break;
case _T('\''): fLit = TRUE; break;
default:
*pLit++ = c;
break;
}
}
else
{
//
// In literal mode
//
if(c == _T('\''))
{
fLit = FALSE; // Terminate the literal mode
*pLit = 0; // Terminate the literal string
wcscat(m_pszBuf, szLit); // Append the literal string
pLit = szLit; // Reinitialize the literal string
*pLit = 0;
}
else
*pLit++ = c; // Copy character to literal string
}
}
//
// Last check for a pending format
//
if(fFmt)
{
if(*szLit)
{
*pLit = 0;
wcscat(m_pszBuf, szLit);
}
FormatSection();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -