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