]> git.saurik.com Git - wxWidgets.git/blob - src/common/date.cpp
Right-o, wxConv_local does cause some weird crashes, but things
[wxWidgets.git] / src / common / date.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: date.cpp
3 // Purpose: wxDate class
4 // Author:
5 // Originally inspired by Steve Marcus (CIS 72007,1233) 6/16/91
6 // Enhanced by Eric Simon (CIS 70540,1522) 6/29/91
7 // Further Enhanced by Chris Hill (CIS 72030,2606) 7/11/91
8 // Still Further Enhanced by Hill & Simon v3.10 8/05/91
9 // Version 4 by Charles D. Price 6/27/92
10 // Integrated into wxWindows by Julian Smart 9th July 1995
11 // Modified by:
12 // Created: 01/02/97
13 // RCS-ID: $Id$
14 // Copyright: (c) Julian Smart and Markus Holzem
15 // Licence: wxWindows licence
16 /////////////////////////////////////////////////////////////////////////////
17
18 #ifdef __GNUG__
19 #pragma implementation "date.h"
20 #endif
21
22 // For compilers that support precompilation, includes "wx.h".
23 #include "wx/wxprec.h"
24
25 #ifdef __BORLANDC__
26 #pragma hdrstop
27 #endif
28
29 #include "wx/setup.h"
30
31 #if wxUSE_TIMEDATE
32
33 #include "wx/date.h"
34 #include <wx/intl.h>
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39
40 #if wxUSE_IOSTREAMH
41 #include <iostream.h>
42 #else
43 #include <iostream>
44 #endif
45
46 #include <time.h>
47 #include <string.h>
48
49 #define ABBR_LENGTH 3
50
51 static const wxChar *dayname[] = {
52 _T("Sunday"), _T("Monday"), _T("Tuesday"), _T("Wednesday"),
53 _T("Thursday"), _T("Friday"), _T("Saturday")
54 };
55
56 static const wxChar *mname[] = {
57 _T("January"), _T("February"), _T("March"), _T("April"), _T("May"), _T("June"),
58 _T("July"), _T("August"), _T("September"), _T("October"), _T("November"), _T("December")
59 };
60
61 static int GauDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
62
63 #if !USE_SHARED_LIBRARY
64 IMPLEMENT_DYNAMIC_CLASS(wxDate, wxObject)
65 #endif
66
67 ////////////////////////////////////////////////////////////
68 // Constructors
69 ////////////////////////////////////////////////////////////
70
71 wxDate::wxDate()
72 {
73 DisplayFormat=wxMDY;
74 DisplayOptions='\0';
75 month = day = year = day_of_week = 0;
76 julian = 0;
77 }
78
79 wxDate::wxDate (long j) : julian(j)
80 {
81 DisplayFormat=wxMDY;
82 DisplayOptions='\0';
83 julian_to_mdy ();
84 }
85
86 wxDate::wxDate (int m, int d, int y) : month(m), day(d), year(y)
87 {
88 DisplayFormat=wxMDY;
89 DisplayOptions='\0';
90 mdy_to_julian ();
91 }
92
93 wxDate::wxDate (const wxString& dat)
94 {
95 DisplayFormat=wxMDY;
96 DisplayOptions='\0';
97 if (wxStrcmp(dat, _T("TODAY")) == 0 || wxStrcmp(dat, _T("today")) == 0)
98 {
99 // Sets the current date
100 Set();
101 }
102 else
103 {
104 wxChar buf[100];
105 wxStrcpy(buf, WXSTRINGCAST dat);
106
107 wxChar *save_ptr, *token = wxStrtok(buf,_T("/-"),&save_ptr);
108 month = wxAtoi(token);
109 day = wxAtoi(wxStrtok((wxChar *) NULL,_T("/-"),&save_ptr));
110 year = wxAtoi(wxStrtok((wxChar *) NULL,_T(" "),&save_ptr));
111 }
112
113 mdy_to_julian ();
114 }
115
116 wxDate::wxDate (const wxDate &dt)
117 {
118 DisplayFormat=dt.DisplayFormat;
119 DisplayOptions=dt.DisplayOptions;
120 month = dt.month;
121 day = dt.day;
122 year = dt.year;
123 mdy_to_julian ();
124 }
125
126 void wxDate::operator = (const wxDate &dt)
127 {
128 DisplayFormat=dt.DisplayFormat;
129 DisplayOptions=dt.DisplayOptions;
130 month = dt.month;
131 day = dt.day;
132 year = dt.year;
133 mdy_to_julian (); // wxUSE_TIMEDATE
134 }
135
136 void wxDate::operator = (const wxString& dat)
137 {
138 DisplayFormat=wxMDY;
139 DisplayOptions='\0';
140 if (wxStrcmp(dat, _T("TODAY")) == 0 || wxStrcmp(dat, _T("today")) == 0)
141 {
142 // Sets the current date
143 Set();
144 }
145 else
146 {
147 wxChar buf[100];
148 wxStrcpy(buf, WXSTRINGCAST dat);
149
150 wxChar *save_ptr, *token = wxStrtok(buf,_T("/-"),&save_ptr);
151 month = wxAtoi(token);
152 day = wxAtoi(wxStrtok((wxChar *) NULL,_T("/-"),&save_ptr));
153 year = wxAtoi(wxStrtok((wxChar *) NULL,_T(" "),&save_ptr));
154 }
155
156 mdy_to_julian ();
157 }
158
159 //////////////////////////////////////////////////////////////
160 // Conversion operations
161 //////////////////////////////////////////////////////////////
162
163 #ifndef __SALFORDC__
164 wxDate::operator wxString( void )
165 {
166 return FormatDate();
167 }
168 #endif
169
170 //////////////////////////////////////////////////////////////
171 // Date Arithmetic
172 //////////////////////////////////////////////////////////////
173
174 wxDate wxDate::operator + (long i)
175 {
176 wxDate dp(julian + i);
177 return dp;
178 }
179
180 wxDate wxDate::operator + (int i)
181 {
182 wxDate dp(julian + (long)i);
183 return dp;
184 }
185
186 wxDate wxDate::operator - (long i)
187 {
188 wxDate dp(julian - i);
189 return dp;
190 }
191
192 wxDate wxDate::operator - (int i)
193 {
194 wxDate dp(julian - (long)i);
195 return dp;
196 }
197
198 long wxDate::operator - (const wxDate &dt)
199 {
200 return ( julian - dt.julian );
201 }
202
203 wxDate &wxDate::operator += (long i)
204 {
205 julian += i;
206 julian_to_mdy();
207 return *this;
208 }
209
210 wxDate &wxDate::operator -= (long i)
211 {
212 julian -= i;
213 julian_to_mdy();
214 return *this;
215 }
216
217 wxDate &wxDate::operator ++()
218 {
219 julian++;
220 julian_to_mdy();
221 return *this;
222 }
223
224 wxDate &wxDate::operator ++(int)
225 {
226 julian++;
227 julian_to_mdy();
228 return *this;
229 }
230
231 wxDate &wxDate::operator --()
232 {
233 julian--;
234 julian_to_mdy();
235 return *this;
236 }
237
238 wxDate &wxDate::operator --(int)
239 {
240 julian--;
241 julian_to_mdy();
242 return *this;
243 }
244
245 //////////////////////////////////////////////////////////////
246 // Date comparison
247 //////////////////////////////////////////////////////////////
248
249 bool WXDLLEXPORT operator < (const wxDate &dt1, const wxDate &dt2)
250 {
251 return ( dt1.julian < dt2.julian );
252 }
253
254 bool WXDLLEXPORT operator <= (const wxDate &dt1, const wxDate &dt2)
255 {
256 return ( (dt1.julian == dt2.julian) || (dt1.julian < dt2.julian) );
257 }
258
259 bool WXDLLEXPORT operator > (const wxDate &dt1, const wxDate &dt2)
260 {
261 return ( dt1.julian > dt2.julian );
262 }
263
264 bool WXDLLEXPORT operator >= (const wxDate &dt1, const wxDate &dt2)
265 {
266 return ( (dt1.julian == dt2.julian) || (dt1.julian > dt2.julian) );
267 }
268
269 bool WXDLLEXPORT operator == (const wxDate &dt1, const wxDate &dt2)
270 {
271 return ( dt1.julian == dt2.julian );
272 }
273
274 bool WXDLLEXPORT operator != (const wxDate &dt1, const wxDate &dt2)
275 {
276 return ( dt1.julian != dt2.julian );
277 }
278
279 ////////////////////////////////////////////////////////////////
280 // Ostream operations
281 ////////////////////////////////////////////////////////////////
282
283 ostream WXDLLEXPORT & operator << (ostream &os, const wxDate &dt)
284 {
285 return os << (const wxChar *) dt.FormatDate();
286 }
287
288 //////////////////////////////////////////////////////////////
289 // Conversion routines
290 //////////////////////////////////////////////////////////////
291
292 void wxDate::julian_to_wday (void)
293 {
294 day_of_week = (int) ((julian + 2) % 7 + 1);
295 }
296
297 void wxDate::julian_to_mdy ()
298 {
299 long a,b,c,d,e,z,alpha;
300 z = julian+1;
301 // dealing with Gregorian calendar reform
302 if (z < 2299161L)
303 a = z;
304 else {
305 alpha = (long) ((z-1867216.25) / 36524.25);
306 a = z + 1 + alpha - alpha/4;
307 }
308 b = ( a > 1721423 ? a + 1524 : a + 1158 );
309 c = (long) ((b - 122.1) / 365.25);
310 d = (long) (365.25 * c);
311 e = (long) ((b - d) / 30.6001);
312 day = (int)(b - d - (long)(30.6001 * e));
313 month = (int)((e < 13.5) ? e - 1 : e - 13);
314 year = (int)((month > 2.5 ) ? (c - 4716) : c - 4715);
315 julian_to_wday ();
316 }
317
318 void wxDate::mdy_to_julian (void)
319 {
320 int a,b=0;
321 int work_month=month, work_day=day, work_year=year;
322 // correct for negative year
323 if (work_year < 0)
324 work_year++;
325 if (work_month <= 2)
326 { work_year--; work_month +=12; }
327
328 // deal with Gregorian calendar
329 if (work_year*10000. + work_month*100. + work_day >= 15821015.)
330 {
331 a = (int)(work_year/100.);
332 b = 2 - a + a/4;
333 }
334 julian = (long) (365.25*work_year) +
335 (long) (30.6001 * (work_month+1)) + work_day + 1720994L + b;
336 julian_to_wday ();
337 }
338
339 ////////////////////////////////////////////////////////////////
340 // Format routine
341 ////////////////////////////////////////////////////////////////
342
343 wxString wxDate::FormatDate (int type) const
344 {
345 int actualType = type;
346 if (actualType == -1)
347 actualType = DisplayFormat;
348
349 wxChar buf[40];
350
351 memset( buf, '\0', sizeof(buf) );
352 switch ( actualType )
353 {
354 case wxDAY:
355 if ( (day_of_week < 1) || (day_of_week > 7) )
356 wxStrcpy(buf, _("invalid day"));
357 else
358 wxStrncpy( buf, wxGetTranslation(dayname[day_of_week-1]),
359 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
360 return wxString(buf);
361
362 case wxMONTH:
363 if ( (month < 1) || (month > 12) )
364 wxStrcpy(buf, _("invalid month"));
365 else
366 wxStrncpy( buf, wxGetTranslation(mname[month-1]),
367 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
368 return wxString(buf);
369
370 case wxFULL:
371 if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
372 (day_of_week > 7) )
373 {
374 wxStrcpy(buf, _("invalid date"));
375 return wxString(buf);
376 }
377 wxStrncpy( buf, wxGetTranslation(dayname[day_of_week-1]),
378 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
379 wxStrcat( buf, _T(", "));
380 wxStrncat( buf, wxGetTranslation(mname[month-1]),
381 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
382 wxStrcat( buf, _T(" "));
383 wxSprintf( buf+wxStrlen(buf), _T("%d, %d"), day, abs(year) );
384 if (year < 0)
385 wxStrcat(buf,_(" B.C."));
386 return wxString(buf);
387
388 case wxEUROPEAN:
389 if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
390 (day_of_week > 7) )
391 {
392 wxStrcpy(buf, _("invalid date"));
393 return wxString(buf);
394 }
395 wxSprintf(buf,_T("%d "), day);
396 wxStrncat(buf, wxGetTranslation(mname[month-1]),
397 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
398 wxSprintf( buf+wxStrlen(buf), _T(" %d"), abs(year) );
399 if (year < 0)
400 wxStrcat(buf, _(" B.C."));
401 return wxString(buf);
402
403 case wxMDY:
404 default:
405 if (day==0 || month==0 || year==0)
406 wxStrcpy(buf, _("invalid date"));
407 else
408 wxSprintf( buf+wxStrlen(buf), _T("%1d/%1d/%02d"), month, day,
409 (DisplayOptions & wxNO_CENTURY) && (abs(year) > 1899)
410 ? (abs(year) - (abs(year) / 100 * 100))
411 : (abs(year)) );
412 return wxString(buf);
413 }
414 return wxString(_T(""));
415 }
416
417 void wxDate::SetFormat( int format )
418 {
419 DisplayFormat = format;
420 }
421
422 int wxDate::SetOption( int option, bool action )
423 {
424 switch ( option )
425 {
426 case wxNO_CENTURY:
427 if ( action )
428 DisplayOptions |= wxNO_CENTURY;
429 else
430 {
431 DisplayOptions &= (~wxNO_CENTURY);
432 }
433 return 1;
434 case wxDATE_ABBR:
435 if ( action )
436 DisplayOptions |= wxDATE_ABBR;
437 else
438 {
439 DisplayOptions &= (~wxDATE_ABBR);
440 }
441 return 1;
442 default:
443 return 0;
444 }
445 return 0;
446 }
447
448 ///////////////////////////////////////////////////////////////
449 // Miscellaneous Routines
450 ///////////////////////////////////////////////////////////////
451
452 long wxDate::GetJulianDate( void ) const
453 {
454 return julian;
455 }
456
457 int wxDate::GetDayOfYear( void ) const
458 {
459 wxDate temp( 1, 1, year );
460
461 return (int) (julian - temp.julian + 1);
462 }
463
464
465 bool wxDate::IsLeapYear( void ) const
466 {
467 return ( (year >= 1582) ?
468 (year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ):
469 (year % 4 == 0) );
470 }
471
472 // Version 4.0 Extension to Public Interface - CDP
473
474 wxDate& wxDate::Set()
475 {
476 //#ifdef __WXMSW__
477 #if 0
478 struct _dosdate_t sDate;
479 _dos_getdate(&sDate);
480
481 month = sDate.month;
482 day = sDate.day;
483 year = sDate.year;
484
485 mdy_to_julian();
486 #else
487 time_t now = time((time_t *) NULL);
488 struct tm *localTime = localtime(&now);
489
490 month = localTime->tm_mon + 1;
491 day = localTime->tm_mday;
492 year = localTime->tm_year + 1900;
493
494 mdy_to_julian ();
495 #endif
496 return *this;
497 }
498
499 wxDate& wxDate::Set(
500 int nMonth,
501 int nDay,
502 int nYear)
503 {
504 month = nMonth;
505 year = nYear < 0 ? 9999 : nYear;
506 year = nYear > 9999 ? 0 : nYear;
507 day = nDay < GetDaysInMonth() ? nDay : GetDaysInMonth();
508
509 mdy_to_julian();
510 return *this;
511 }
512
513 wxDate &
514 wxDate::Set(long j)
515 {
516 julian = j;
517
518 julian_to_mdy();
519 return *this;
520 }
521
522
523 int wxDate::GetDaysInMonth()
524 {
525 return GauDays[month-1] + (month==2 && IsLeapYear());
526 }
527
528 int wxDate::GetFirstDayOfMonth() const
529 {
530 return wxDate(month, 1, year).GetDayOfWeek();
531 }
532
533 int wxDate::GetDay() const
534 {
535 return day;
536 }
537
538 int wxDate::GetDayOfWeek() const
539 {
540 return day_of_week;
541 }
542
543 int wxDate::GetYear() const
544 {
545 return year;
546 }
547
548 int wxDate::GetMonth() const
549 {
550 return month;
551 }
552
553 wxDate& wxDate::AddWeeks(int nCount)
554 {
555 Set(julian + (long)nCount*7);
556 return *this;
557 }
558
559 wxDate& wxDate::AddMonths(int nCount)
560 {
561 month += nCount;
562
563 if (month < 1) {
564 month = 12;
565 year--;
566 }
567
568 if (month > 12) {
569 month = 1;
570 year++;
571 }
572 mdy_to_julian();
573 return *this;
574 }
575
576 wxDate& wxDate::AddYears(int nCount)
577 {
578 year += nCount;
579 mdy_to_julian();
580 return *this;
581 }
582
583 int wxDate::GetWeekOfMonth()
584 {
585 // Abs day includes the days from previous month that fills up
586 // the begin. of the week.
587 int nAbsDay = day + GetFirstDayOfMonth()-1;
588 return (nAbsDay-GetDayOfWeek())/7 + 1;
589 }
590
591 int wxDate::GetWeekOfYear()
592 {
593 wxDate doTemp(1, 1, year);
594 return (int)(((julian - doTemp.julian+1)/7) + 1);
595 }
596
597 wxDate wxDate::GetMonthStart()
598 {
599 return(wxDate(month, 1, year));
600 }
601
602 wxDate wxDate::GetMonthEnd()
603 {
604 return(wxDate(month+1, 1, year)-1);
605 }
606
607 wxDate wxDate::GetYearStart()
608 {
609 return(wxDate(1, 1, year));
610 }
611
612 wxDate wxDate::GetYearEnd()
613 {
614 return(wxDate(1, 1, year+1)-1);
615 }
616
617 wxString wxDate::GetMonthName()
618 {
619 return(FormatDate(wxMONTH));
620 }
621
622 wxString wxDate::GetDayOfWeekName()
623 {
624 return(FormatDate(wxDAY));
625 }
626
627 bool wxDate::IsBetween(const wxDate& first, const wxDate& second) const
628 {
629 return (julian >= first.julian && julian <= second.julian);
630 }
631
632 // This function is from NIHCL
633 wxDate wxDate::Previous(int dayOfWeek) const
634 {
635 int this_day_Of_Week, desired_day_Of_Week;
636 long j;
637
638 // Set the desired and current day of week to start at 0 (Monday)
639 // and end at 6 (Sunday).
640
641 desired_day_Of_Week = dayOfWeek - 1; // These functions return a value
642 this_day_Of_Week = GetDayOfWeek() - 1; // from 1-7. Subtract 1 for 0-6.
643 j = julian;
644
645 // Have to determine how many days difference from current day back to
646 // desired, if any. Special calculation under the 'if' statement to
647 // effect the wraparound counting from Monday (0) back to Sunday (6).
648
649 if (desired_day_Of_Week > this_day_Of_Week)
650 this_day_Of_Week += 7 - desired_day_Of_Week;
651 else
652 this_day_Of_Week -= desired_day_Of_Week;
653 j -= this_day_Of_Week; // Adjust j to set it at the desired day of week.
654 return wxDate(j);
655 }
656
657 #endif