datetime.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,201 行 · 第 1/5 页
CPP
2,201 行
ret = (flags == Name_Abbr ? wxT("Nov"): wxT("November"));
break;
case Dec:
ret = (flags == Name_Abbr ? wxT("Dec"): wxT("December"));
break;
}
return ret;
#endif
}
/* static */
wxString wxDateTime::GetWeekDayName(wxDateTime::WeekDay wday,
wxDateTime::NameFlags flags)
{
wxCHECK_MSG( wday != Inv_WeekDay, wxEmptyString, _T("invalid weekday") );
#ifndef __WXWINCE__
// take some arbitrary Sunday (but notice that the day should be such that
// after adding wday to it below we still have a valid date, e.g. don't
// take 28 here!)
tm tm;
InitTm(tm);
tm.tm_mday = 21;
tm.tm_mon = Nov;
tm.tm_year = 99;
// and offset it by the number of days needed to get the correct wday
tm.tm_mday += wday;
// call mktime() to normalize it...
(void)mktime(&tm);
// ... and call strftime()
return CallStrftime(flags == Name_Abbr ? _T("%a") : _T("%A"), &tm);
#else
wxString ret;
switch(wday)
{
case Sun:
ret = (flags == Name_Abbr ? wxT("Sun") : wxT("Sunday"));
break;
case Mon:
ret = (flags == Name_Abbr ? wxT("Mon") : wxT("Monday"));
break;
case Tue:
ret = (flags == Name_Abbr ? wxT("Tue") : wxT("Tuesday"));
break;
case Wed:
ret = (flags == Name_Abbr ? wxT("Wed") : wxT("Wednesday"));
break;
case Thu:
ret = (flags == Name_Abbr ? wxT("Thu") : wxT("Thursday"));
break;
case Fri:
ret = (flags == Name_Abbr ? wxT("Fri") : wxT("Friday"));
break;
case Sat:
ret = (flags == Name_Abbr ? wxT("Sat") : wxT("Saturday"));
break;
}
return ret;
#endif
}
/* static */
void wxDateTime::GetAmPmStrings(wxString *am, wxString *pm)
{
tm tm;
InitTm(tm);
wxChar buffer[64];
// @Note: Do not call 'CallStrftime' here! CallStrftime checks the return code
// and causes an assertion failed if the buffer is to small (which is good) - OR -
// if strftime does not return anything because the format string is invalid - OR -
// if there are no 'am' / 'pm' tokens defined for the current locale (which is not good).
// wxDateTime::ParseTime will try several different formats to parse the time.
// As a result, GetAmPmStrings might get called, even if the current locale
// does not define any 'am' / 'pm' tokens. In this case, wxStrftime would
// assert, even though it is a perfectly legal use.
if ( am )
{
if (wxStrftime(buffer, sizeof(buffer)/sizeof(wxChar), _T("%p"), &tm) > 0)
*am = wxString(buffer);
else
*am = wxString();
}
if ( pm )
{
tm.tm_hour = 13;
if (wxStrftime(buffer, sizeof(buffer)/sizeof(wxChar), _T("%p"), &tm) > 0)
*pm = wxString(buffer);
else
*pm = wxString();
}
}
// ----------------------------------------------------------------------------
// Country stuff: date calculations depend on the country (DST, work days,
// ...), so we need to know which rules to follow.
// ----------------------------------------------------------------------------
/* static */
wxDateTime::Country wxDateTime::GetCountry()
{
// TODO use LOCALE_ICOUNTRY setting under Win32
#ifndef __WXWINCE__
if ( ms_country == Country_Unknown )
{
// try to guess from the time zone name
time_t t = time(NULL);
struct tm *tm = localtime(&t);
wxString tz = CallStrftime(_T("%Z"), tm);
if ( tz == _T("WET") || tz == _T("WEST") )
{
ms_country = UK;
}
else if ( tz == _T("CET") || tz == _T("CEST") )
{
ms_country = Country_EEC;
}
else if ( tz == _T("MSK") || tz == _T("MSD") )
{
ms_country = Russia;
}
else if ( tz == _T("AST") || tz == _T("ADT") ||
tz == _T("EST") || tz == _T("EDT") ||
tz == _T("CST") || tz == _T("CDT") ||
tz == _T("MST") || tz == _T("MDT") ||
tz == _T("PST") || tz == _T("PDT") )
{
ms_country = USA;
}
else
{
// well, choose a default one
ms_country = USA;
}
}
#else
ms_country = USA;
#endif
return ms_country;
}
/* static */
void wxDateTime::SetCountry(wxDateTime::Country country)
{
ms_country = country;
}
/* static */
bool wxDateTime::IsWestEuropeanCountry(Country country)
{
if ( country == Country_Default )
{
country = GetCountry();
}
return (Country_WesternEurope_Start <= country) &&
(country <= Country_WesternEurope_End);
}
// ----------------------------------------------------------------------------
// DST calculations: we use 3 different rules for the West European countries,
// USA and for the rest of the world. This is undoubtedly false for many
// countries, but I lack the necessary info (and the time to gather it),
// please add the other rules here!
// ----------------------------------------------------------------------------
/* static */
bool wxDateTime::IsDSTApplicable(int year, Country country)
{
if ( year == Inv_Year )
{
// take the current year if none given
year = GetCurrentYear();
}
if ( country == Country_Default )
{
country = GetCountry();
}
switch ( country )
{
case USA:
case UK:
// DST was first observed in the US and UK during WWI, reused
// during WWII and used again since 1966
return year >= 1966 ||
(year >= 1942 && year <= 1945) ||
(year == 1918 || year == 1919);
default:
// assume that it started after WWII
return year > 1950;
}
}
/* static */
wxDateTime wxDateTime::GetBeginDST(int year, Country country)
{
if ( year == Inv_Year )
{
// take the current year if none given
year = GetCurrentYear();
}
if ( country == Country_Default )
{
country = GetCountry();
}
if ( !IsDSTApplicable(year, country) )
{
return wxInvalidDateTime;
}
wxDateTime dt;
if ( IsWestEuropeanCountry(country) || (country == Russia) )
{
// DST begins at 1 a.m. GMT on the last Sunday of March
if ( !dt.SetToLastWeekDay(Sun, Mar, year) )
{
// weird...
wxFAIL_MSG( _T("no last Sunday in March?") );
}
dt += wxTimeSpan::Hours(1);
// disable DST tests because it could result in an infinite recursion!
dt.MakeGMT(true);
}
else switch ( country )
{
case USA:
switch ( year )
{
case 1918:
case 1919:
// don't know for sure - assume it was in effect all year
case 1943:
case 1944:
case 1945:
dt.Set(1, Jan, year);
break;
case 1942:
// DST was installed Feb 2, 1942 by the Congress
dt.Set(2, Feb, year);
break;
// Oil embargo changed the DST period in the US
case 1974:
dt.Set(6, Jan, 1974);
break;
case 1975:
dt.Set(23, Feb, 1975);
break;
default:
// before 1986, DST begun on the last Sunday of April, but
// in 1986 Reagan changed it to begin at 2 a.m. of the
// first Sunday in April
if ( year < 1986 )
{
if ( !dt.SetToLastWeekDay(Sun, Apr, year) )
{
// weird...
wxFAIL_MSG( _T("no first Sunday in April?") );
}
}
else
{
if ( !dt.SetToWeekDay(Sun, 1, Apr, year) )
{
// weird...
wxFAIL_MSG( _T("no first Sunday in April?") );
}
}
dt += wxTimeSpan::Hours(2);
// TODO what about timezone??
}
break;
default:
// assume Mar 30 as the start of the DST for the rest of the world
// - totally bogus, of course
dt.Set(30, Mar, year);
}
return dt;
}
/* static */
wxDateTime wxDateTime::GetEndDST(int year, Country country)
{
if ( year == Inv_Year )
{
// take the current year if none given
year = GetCurrentYear();
}
if ( country == Country_Default )
{
country = GetCountry();
}
if ( !IsDSTApplicable(year, country) )
{
return wxInvalidDateTime;
}
wxDateTime dt;
if ( IsWestEuropeanCountry(country) || (country == Russia) )
{
// DST ends at 1 a.m. GMT on the last Sunday of October
if ( !dt.SetToLastWeekDay(Sun, Oct, year) )
{
// weirder and weirder...
wxFAIL_MSG( _T("no last Sunday in October?") );
}
dt += wxTimeSpan::Hours(1);
// disable DST tests because it could result in an infinite recursion!
dt.MakeGMT(true);
}
else switch ( country )
{
case USA:
switch ( year )
{
case 1918:
case 1919:
// don't know for sure - assume it was in effect all year
case 1943:
case 1944:
dt.Set(31, Dec, year);
break;
case 1945:
// the time was reset after the end of the WWII
dt.Set(30, Sep, year);
break;
default:
// DST ends at 2 a.m. on the last Sunday of October
if ( !dt.SetToLastWeekDay(Sun, Oct, year) )
{
// weirder and weirder...
wxFAIL_MSG( _T("no last Sunday in October?") );
}
dt += wxTimeSpan::Hours(2);
// TODO what about timezone??
}
break;
default:
// assume October 26th as the end of the DST - totally bogus too
dt.Set(26, Oct, year);
}
return dt;
}
// ----------------------------------------------------------------------------
// constructors and assignment operators
// ----------------------------------------------------------------------------
// return the current time with ms precision
/* static */ wxDateTime wxDateTime::UNow()
{
return wxDateTime(wxGetLocalTimeMillis());
}
// the values in the tm structure contain the local time
wxDateTime& wxDateTime::Set(const struct tm& tm)
{
struct tm tm2(tm);
time_t timet = mktime(&tm2);
if ( timet == (time_t)-1 )
{
// mktime() rather unintuitively fails for Jan 1, 1970 if the hour is
// less than timezone - try to make it work for this case
if ( tm2.tm_year == 70 && tm2.tm_mon == 0 && tm2.tm_mday == 1 )
{
return Set((time_t)(
GetTimeZone() +
tm2.tm_hour * MIN_PER_HOUR * SEC_PER_MIN +
tm2.tm_min * SEC_PER_MIN +
tm2.tm_sec));
}
wxFAIL_MSG( _T("mktime() failed") );
*this = wxInvalidDateTime;
return *this;
}
else
{
return Set(timet);
}
}
wxDateTime& wxDateTime::Set(wxDateTime_t hour,
wxDateTime_t minute,
wxDateTime_t second,
wxDateTime_t millisec)
{
// we allow seconds to be 61 to account for the leap seconds, even if we
// don't use them really
wxDATETIME_CHECK( hour < 24 &&
second < 62 &&
minute < 60 &&
millisec < 1000,
_T("Invalid time in wxDateTime::Set()") );
// get the current date from system
struct tm *tm = GetTmNow();
wxDATETIME_CHECK( tm, _T("localtime() failed") );
// make a copy so it isn't clobbered by the call to mktime() below
struct tm tm1(*tm);
// adjust the time
tm1.tm_hour = hour;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?