1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: implementation of time/date related classes
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "datetime.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
32 #include "wx/string.h"
37 #define wxDEFINE_TIME_CONSTANTS
39 #include "wx/datetime.h"
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 // the number of days in month in Julian/Gregorian calendar: the first line is
46 // for normal years, the second one is for the leap ones
47 static wxDateTime::wxDateTime_t gs_daysInMonth
[2][12] =
49 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
50 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 static wxString
CallStrftime(const wxChar
*format
, const tm
* tm
)
60 if ( !wxStrftime(buf
, WXSIZEOF(buf
), format
, tm
) )
62 // is ti really possible that 1024 is too short?
63 wxFAIL_MSG(_T("strftime() failed"));
69 // ============================================================================
70 // implementation of wxDateTime
71 // ============================================================================
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 wxDateTime::Country
wxDateTime::ms_country
= wxDateTime::Country_Unknown
;
78 wxDateTime
wxDateTime::ms_InvDateTime
;
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
86 year
= (wxDateTime_t
)wxDateTime::Inv_Year
;
87 mon
= wxDateTime::Inv_Month
;
90 wday
= wxDateTime::Inv_WeekDay
;
93 wxDateTime::Tm::Tm(const struct tm
& tm
)
100 year
= 1900 + tm
.tm_year
;
105 bool wxDateTime::Tm::IsValid() const
107 // we allow for the leap seconds, although we don't use them (yet)
108 return (year
!= wxDateTime::Inv_Year
) && (mon
< 12) &&
109 (mday
< gs_daysInMonth
[IsLeapYear(year
)][mon
]) &&
110 (hour
< 24) && (min
< 60) && (sec
< 62);
113 void wxDateTime::Tm::ComputeWeekDay()
115 wxFAIL_MSG(_T("TODO"));
118 // ----------------------------------------------------------------------------
120 // ----------------------------------------------------------------------------
123 bool wxDateTime::IsLeapYear(int year
, wxDateTime::Calendar cal
)
125 if ( cal
== Gregorian
)
127 // in Gregorian calendar leap years are those divisible by 4 except
128 // those divisible by 100 unless they're also divisible by 400
129 // (in some countries, like Russia and Greece, additional corrections
130 // exist, but they won't manifest themselves until 2700)
131 return (year
% 4 == 0) && ((year
% 100 != 0) || (year
% 400 == 0));
133 else if ( cal
== Julian
)
135 // in Julian calendar the rule is simpler
136 return year
% 4 == 0;
140 wxFAIL_MSG(_T("unknown calendar"));
147 void wxDateTime::SetCountry(wxDateTime::Country country
)
149 ms_country
= country
;
153 int wxDateTime::ConvertYearToBC(int year
)
156 return year
> 0 ? year
: year
- 1;
160 int wxDateTime::GetCurrentYear(wxDateTime::Calendar cal
)
165 return Now().GetYear();
168 wxFAIL_MSG(_T("TODO"));
172 wxFAIL_MSG(_T("unsupported calendar"));
180 wxDateTime::Month
wxDateTime::GetCurrentMonth(wxDateTime::Calendar cal
)
185 return Now().GetMonth();
189 wxFAIL_MSG(_T("TODO"));
193 wxFAIL_MSG(_T("unsupported calendar"));
201 wxDateTime::wxDateTime_t
wxDateTime::GetNumberOfDays(wxDateTime::Month month
,
203 wxDateTime::Calendar cal
)
205 wxCHECK_MSG( month
< 12, 0, _T("invalid month") );
207 if ( cal
== Gregorian
|| cal
== Julian
)
209 if ( year
== Inv_Year
)
211 // take the current year if none given
212 year
= GetCurrentYear();
215 return gs_daysInMonth
[IsLeapYear(year
)][month
];
219 wxFAIL_MSG(_T("unsupported calendar"));
226 wxString
wxDateTime::GetMonthName(wxDateTime::Month month
, bool abbr
)
228 wxCHECK_MSG( month
!= Inv_Month
, _T(""), _T("invalid month") );
230 tm tm
= { 0, 0, 0, 1, month
, 76 }; // any year will do
232 return CallStrftime(abbr
? _T("%b") : _T("%B"), &tm
);
236 wxString
wxDateTime::GetWeekDayName(wxDateTime::WeekDay wday
, bool abbr
)
238 wxCHECK_MSG( wday
!= Inv_WeekDay
, _T(""), _T("invalid weekday") );
240 // take some arbitrary Sunday
241 tm tm
= { 0, 0, 0, 28, Nov
, 99 };
243 // and offset it by the number of days needed to get
246 return CallStrftime(abbr
? _T("%a") : _T("%A"), &tm
);
249 // ----------------------------------------------------------------------------
250 // constructors and assignment operators
251 // ----------------------------------------------------------------------------
253 wxDateTime
& wxDateTime::Set(const struct tm
& tm1
)
255 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
258 time_t timet
= mktime(&tm2
);
259 if ( timet
== (time_t)(-1) )
261 wxFAIL_MSG(_T("Invalid time"));
263 return ms_InvDateTime
;
271 wxDateTime
& wxDateTime::Set(wxDateTime_t hour
,
274 wxDateTime_t millisec
)
276 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
278 // we allow seconds to be 61 to account for the leap seconds, even if we
279 // don't use them really
280 wxCHECK_MSG( hour
< 24 && second
< 62 && minute
< 60 && millisec
< 1000,
282 _T("Invalid time in wxDateTime::Set()") );
284 // get the current date from system
285 time_t timet
= GetTimeNow();
286 struct tm
*tm
= localtime(&timet
);
295 // and finally adjust milliseconds
296 return SetMillisecond(millisec
);
299 wxDateTime
& wxDateTime::Set(wxDateTime_t day
,
305 wxDateTime_t millisec
)
307 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
309 wxCHECK_MSG( hour
< 24 && second
< 62 && minute
< 60 && millisec
< 1000,
311 _T("Invalid time in wxDateTime::Set()") );
313 if ( year
== Inv_Year
)
314 year
= GetCurrentYear();
315 if ( month
== Inv_Month
)
316 month
= GetCurrentMonth();
318 wxCHECK_MSG( day
< GetNumberOfDays(month
, year
), ms_InvDateTime
,
319 _T("Invalid date in wxDateTime::Set()") );
321 // the range of time_t type (inclusive)
322 static const int yearMinInRange
= 1970;
323 static const int yearMaxInRange
= 2037;
325 // test only the year instead of testing for the exact end of the Unix
326 // time_t range - it doesn't bring anything to do more precise checks
327 if ( year
>= yearMaxInRange
&& year
<= yearMaxInRange
)
329 // use the standard library version if the date is in range - this is
330 // probably more efficient than our code
332 tm
.tm_year
= year
- 1900;
341 // and finally adjust milliseconds
342 return SetMillisecond(millisec
);
346 // do time calculations ourselves: we want to calculate the number of
347 // milliseconds between the given date and the epoch (necessarily
349 wxFAIL_MSG(_T("TODO"));
355 // ----------------------------------------------------------------------------
356 // time_t <-> broken down time conversions
357 // ----------------------------------------------------------------------------
359 wxDateTime::Tm
wxDateTime::GetTm() const
361 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
363 time_t time
= GetTicks();
364 if ( time
!= (time_t)-1 )
366 // use C RTL functions
367 tm
*tm
= localtime(&time
);
369 // should never happen
370 wxCHECK_MSG( tm
, Tm(), _T("localtime() failed") );
376 wxFAIL_MSG(_T("TODO"));
382 wxDateTime
& wxDateTime::SetYear(int year
)
384 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
393 wxDateTime
& wxDateTime::SetMonth(Month month
)
395 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
404 wxDateTime
& wxDateTime::SetDay(wxDateTime_t mday
)
406 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
415 wxDateTime
& wxDateTime::SetHour(wxDateTime_t hour
)
417 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
426 wxDateTime
& wxDateTime::SetMinute(wxDateTime_t min
)
428 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
437 wxDateTime
& wxDateTime::SetSecond(wxDateTime_t sec
)
439 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
448 wxDateTime
& wxDateTime::SetMillisecond(wxDateTime_t millisecond
)
450 wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") );
452 // we don't need to use GetTm() for this one
453 m_time
-= m_time
% 1000l;
454 m_time
+= millisecond
;
459 // ----------------------------------------------------------------------------
460 // wxDateTime arithmetics
461 // ----------------------------------------------------------------------------
463 wxDateTime
& wxDateTime::Add(const wxDateSpan
& diff
)
467 tm
.year
+= diff
.GetYears();
468 tm
.mon
+= diff
.GetMonths();
469 tm
.mday
+= diff
.GetTotalDays();
476 // ----------------------------------------------------------------------------
477 // wxDateTime to/from text representations
478 // ----------------------------------------------------------------------------
480 wxString
wxDateTime::Format(const wxChar
*format
) const
482 time_t time
= GetTicks();
483 if ( time
!= (time_t)-1 )
486 tm
*tm
= localtime(&time
);
488 // should never happen
489 wxCHECK_MSG( tm
, _T(""), _T("localtime() failed") );
491 return CallStrftime(format
, tm
);
495 wxFAIL_MSG(_T("TODO"));