datetime.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,201 行 · 第 1/5 页
CPP
2,201 行
if ( *month == wxDateTime::Inv_Month )
{
if ( !tmNow )
tmNow = wxDateTime::GetTmNow();
*month = (wxDateTime::Month)tmNow->tm_mon;
}
}
// fll the struct tm with default values
static void InitTm(struct tm& tm)
{
// struct tm may have etxra fields (undocumented and with unportable
// names) which, nevertheless, must be set to 0
memset(&tm, 0, sizeof(struct tm));
tm.tm_mday = 1; // mday 0 is invalid
tm.tm_year = 76; // any valid year
tm.tm_isdst = -1; // auto determine
}
// parsing helpers
// ---------------
// return the month if the string is a month name or Inv_Month otherwise
static wxDateTime::Month GetMonthFromName(const wxString& name, int flags)
{
wxDateTime::Month mon;
for ( mon = wxDateTime::Jan; mon < wxDateTime::Inv_Month; wxNextMonth(mon) )
{
// case-insensitive comparison either one of or with both abbreviated
// and not versions
if ( flags & wxDateTime::Name_Full )
{
if ( name.CmpNoCase(wxDateTime::
GetMonthName(mon, wxDateTime::Name_Full)) == 0 )
{
break;
}
}
if ( flags & wxDateTime::Name_Abbr )
{
if ( name.CmpNoCase(wxDateTime::
GetMonthName(mon, wxDateTime::Name_Abbr)) == 0 )
{
break;
}
}
}
return mon;
}
// return the weekday if the string is a weekday name or Inv_WeekDay otherwise
static wxDateTime::WeekDay GetWeekDayFromName(const wxString& name, int flags)
{
wxDateTime::WeekDay wd;
for ( wd = wxDateTime::Sun; wd < wxDateTime::Inv_WeekDay; wxNextWDay(wd) )
{
// case-insensitive comparison either one of or with both abbreviated
// and not versions
if ( flags & wxDateTime::Name_Full )
{
if ( name.CmpNoCase(wxDateTime::
GetWeekDayName(wd, wxDateTime::Name_Full)) == 0 )
{
break;
}
}
if ( flags & wxDateTime::Name_Abbr )
{
if ( name.CmpNoCase(wxDateTime::
GetWeekDayName(wd, wxDateTime::Name_Abbr)) == 0 )
{
break;
}
}
}
return wd;
}
// scans all digits (but no more than len) and returns the resulting number
static bool GetNumericToken(size_t len, const wxChar*& p, unsigned long *number)
{
size_t n = 1;
wxString s;
while ( wxIsdigit(*p) )
{
s += *p++;
if ( len && ++n > len )
break;
}
return !s.empty() && s.ToULong(number);
}
// scans all alphabetic characters and returns the resulting string
static wxString GetAlphaToken(const wxChar*& p)
{
wxString s;
while ( wxIsalpha(*p) )
{
s += *p++;
}
return s;
}
// ============================================================================
// implementation of wxDateTime
// ============================================================================
// ----------------------------------------------------------------------------
// struct Tm
// ----------------------------------------------------------------------------
wxDateTime::Tm::Tm()
{
year = (wxDateTime_t)wxDateTime::Inv_Year;
mon = wxDateTime::Inv_Month;
mday = 0;
hour = min = sec = msec = 0;
wday = wxDateTime::Inv_WeekDay;
}
wxDateTime::Tm::Tm(const struct tm& tm, const TimeZone& tz)
: m_tz(tz)
{
msec = 0;
sec = (wxDateTime::wxDateTime_t)tm.tm_sec;
min = (wxDateTime::wxDateTime_t)tm.tm_min;
hour = (wxDateTime::wxDateTime_t)tm.tm_hour;
mday = (wxDateTime::wxDateTime_t)tm.tm_mday;
mon = (wxDateTime::Month)tm.tm_mon;
year = 1900 + tm.tm_year;
wday = (wxDateTime::wxDateTime_t)tm.tm_wday;
yday = (wxDateTime::wxDateTime_t)tm.tm_yday;
}
bool wxDateTime::Tm::IsValid() const
{
// we allow for the leap seconds, although we don't use them (yet)
return (year != wxDateTime::Inv_Year) && (mon != wxDateTime::Inv_Month) &&
(mday <= GetNumOfDaysInMonth(year, mon)) &&
(hour < 24) && (min < 60) && (sec < 62) && (msec < 1000);
}
void wxDateTime::Tm::ComputeWeekDay()
{
// compute the week day from day/month/year: we use the dumbest algorithm
// possible: just compute our JDN and then use the (simple to derive)
// formula: weekday = (JDN + 1.5) % 7
wday = (wxDateTime::wxDateTime_t)((wxDateTime::WeekDay)(GetTruncatedJDN(mday, mon, year) + 2) % 7);
}
void wxDateTime::Tm::AddMonths(int monDiff)
{
// normalize the months field
while ( monDiff < -mon )
{
year--;
monDiff += MONTHS_IN_YEAR;
}
while ( monDiff + mon >= MONTHS_IN_YEAR )
{
year++;
monDiff -= MONTHS_IN_YEAR;
}
mon = (wxDateTime::Month)(mon + monDiff);
wxASSERT_MSG( mon >= 0 && mon < MONTHS_IN_YEAR, _T("logic error") );
// NB: we don't check here that the resulting date is valid, this function
// is private and the caller must check it if needed
}
void wxDateTime::Tm::AddDays(int dayDiff)
{
// normalize the days field
while ( dayDiff + mday < 1 )
{
AddMonths(-1);
dayDiff += GetNumOfDaysInMonth(year, mon);
}
mday = (wxDateTime::wxDateTime_t)( mday + dayDiff );
while ( mday > GetNumOfDaysInMonth(year, mon) )
{
mday -= GetNumOfDaysInMonth(year, mon);
AddMonths(1);
}
wxASSERT_MSG( mday > 0 && mday <= GetNumOfDaysInMonth(year, mon),
_T("logic error") );
}
// ----------------------------------------------------------------------------
// class TimeZone
// ----------------------------------------------------------------------------
wxDateTime::TimeZone::TimeZone(wxDateTime::TZ tz)
{
switch ( tz )
{
case wxDateTime::Local:
// get the offset from C RTL: it returns the difference GMT-local
// while we want to have the offset _from_ GMT, hence the '-'
m_offset = -GetTimeZone();
break;
case wxDateTime::GMT_12:
case wxDateTime::GMT_11:
case wxDateTime::GMT_10:
case wxDateTime::GMT_9:
case wxDateTime::GMT_8:
case wxDateTime::GMT_7:
case wxDateTime::GMT_6:
case wxDateTime::GMT_5:
case wxDateTime::GMT_4:
case wxDateTime::GMT_3:
case wxDateTime::GMT_2:
case wxDateTime::GMT_1:
m_offset = -3600*(wxDateTime::GMT0 - tz);
break;
case wxDateTime::GMT0:
case wxDateTime::GMT1:
case wxDateTime::GMT2:
case wxDateTime::GMT3:
case wxDateTime::GMT4:
case wxDateTime::GMT5:
case wxDateTime::GMT6:
case wxDateTime::GMT7:
case wxDateTime::GMT8:
case wxDateTime::GMT9:
case wxDateTime::GMT10:
case wxDateTime::GMT11:
case wxDateTime::GMT12:
m_offset = 3600*(tz - wxDateTime::GMT0);
break;
case wxDateTime::A_CST:
// Central Standard Time in use in Australia = UTC + 9.5
m_offset = 60l*(9*MIN_PER_HOUR + MIN_PER_HOUR/2);
break;
default:
wxFAIL_MSG( _T("unknown time zone") );
}
}
// ----------------------------------------------------------------------------
// static functions
// ----------------------------------------------------------------------------
/* static */
bool wxDateTime::IsLeapYear(int year, wxDateTime::Calendar cal)
{
if ( year == Inv_Year )
year = GetCurrentYear();
if ( cal == Gregorian )
{
// in Gregorian calendar leap years are those divisible by 4 except
// those divisible by 100 unless they're also divisible by 400
// (in some countries, like Russia and Greece, additional corrections
// exist, but they won't manifest themselves until 2700)
return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
}
else if ( cal == Julian )
{
// in Julian calendar the rule is simpler
return year % 4 == 0;
}
else
{
wxFAIL_MSG(_T("unknown calendar"));
return false;
}
}
/* static */
int wxDateTime::GetCentury(int year)
{
return year > 0 ? year / 100 : year / 100 - 1;
}
/* static */
int wxDateTime::ConvertYearToBC(int year)
{
// year 0 is BC 1
return year > 0 ? year : year - 1;
}
/* static */
int wxDateTime::GetCurrentYear(wxDateTime::Calendar cal)
{
switch ( cal )
{
case Gregorian:
return Now().GetYear();
case Julian:
wxFAIL_MSG(_T("TODO"));
break;
default:
wxFAIL_MSG(_T("unsupported calendar"));
break;
}
return Inv_Year;
}
/* static */
wxDateTime::Month wxDateTime::GetCurrentMonth(wxDateTime::Calendar cal)
{
switch ( cal )
{
case Gregorian:
return Now().GetMonth();
case Julian:
wxFAIL_MSG(_T("TODO"));
break;
default:
wxFAIL_MSG(_T("unsupported calendar"));
break;
}
return Inv_Month;
}
/* static */
wxDateTime::wxDateTime_t wxDateTime::GetNumberOfDays(int year, Calendar cal)
{
if ( year == Inv_Year )
{
// take the current year if none given
year = GetCurrentYear();
}
switch ( cal )
{
case Gregorian:
case Julian:
return IsLeapYear(year) ? 366 : 365;
default:
wxFAIL_MSG(_T("unsupported calendar"));
break;
}
return 0;
}
/* static */
wxDateTime::wxDateTime_t wxDateTime::GetNumberOfDays(wxDateTime::Month month,
int year,
wxDateTime::Calendar cal)
{
wxCHECK_MSG( month < MONTHS_IN_YEAR, 0, _T("invalid month") );
if ( cal == Gregorian || cal == Julian )
{
if ( year == Inv_Year )
{
// take the current year if none given
year = GetCurrentYear();
}
return GetNumOfDaysInMonth(year, month);
}
else
{
wxFAIL_MSG(_T("unsupported calendar"));
return 0;
}
}
/* static */
wxString wxDateTime::GetMonthName(wxDateTime::Month month,
wxDateTime::NameFlags flags)
{
wxCHECK_MSG( month != Inv_Month, wxEmptyString, _T("invalid month") );
#ifndef __WXWINCE__
// notice that we must set all the fields to avoid confusing libc (GNU one
// gets confused to a crash if we don't do this)
tm tm;
InitTm(tm);
tm.tm_mon = month;
return CallStrftime(flags == Name_Abbr ? _T("%b") : _T("%B"), &tm);
#else
wxString ret;
switch(month)
{
case Jan:
ret = (flags == Name_Abbr ? wxT("Jan"): wxT("January"));
break;
case Feb:
ret = (flags == Name_Abbr ? wxT("Feb"): wxT("Febuary"));
break;
case Mar:
ret = (flags == Name_Abbr ? wxT("Mar"): wxT("March"));
break;
case Apr:
ret = (flags == Name_Abbr ? wxT("Apr"): wxT("April"));
break;
case May:
ret = (flags == Name_Abbr ? wxT("May"): wxT("May"));
break;
case Jun:
ret = (flags == Name_Abbr ? wxT("Jun"): wxT("June"));
break;
case Jul:
ret = (flags == Name_Abbr ? wxT("Jul"): wxT("July"));
break;
case Aug:
ret = (flags == Name_Abbr ? wxT("Aug"): wxT("August"));
break;
case Sep:
ret = (flags == Name_Abbr ? wxT("Sep"): wxT("September"));
break;
case Oct:
ret = (flags == Name_Abbr ? wxT("Oct"): wxT("October"));
break;
case Nov:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?