]> git.saurik.com Git - wxWidgets.git/blame - src/common/date.cpp
vsprintf() is ANSI so there is normally no need to test for it
[wxWidgets.git] / src / common / date.cpp
CommitLineData
c801d85f
KB
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
47d67540 31#if wxUSE_TIMEDATE
c801d85f
KB
32
33#include "wx/date.h"
1a5a8367 34#include <wx/intl.h>
c801d85f
KB
35
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39
47d67540 40#if wxUSE_IOSTREAMH
c801d85f
KB
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
1a5a8367
DP
51static const char *dayname[] = {
52 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
53};
c801d85f 54
1a5a8367
DP
55static const char *mname[] = {
56 "January", "February", "March", "April", "May", "June", "July", "August",
57 "September", "October", "November", "December"
58};
c801d85f
KB
59
60static int GauDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
61
62#if !USE_SHARED_LIBRARY
63IMPLEMENT_DYNAMIC_CLASS(wxDate, wxObject)
64#endif
65
66////////////////////////////////////////////////////////////
67// Constructors
68////////////////////////////////////////////////////////////
69
70wxDate::wxDate()
71{
72 DisplayFormat=wxMDY;
73 DisplayOptions='\0';
74 month = day = year = day_of_week = 0;
75 julian = 0;
76}
77
debe6624 78wxDate::wxDate (long j) : julian(j)
c801d85f
KB
79{
80 DisplayFormat=wxMDY;
81 DisplayOptions='\0';
82 julian_to_mdy ();
83}
84
debe6624 85wxDate::wxDate (int m, int d, int y) : month(m), day(d), year(y)
c801d85f
KB
86{
87 DisplayFormat=wxMDY;
88 DisplayOptions='\0';
89 mdy_to_julian ();
90}
91
92wxDate::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);
c67daf87
UR
108 day = atoi(strtok((char *) NULL,"/-"));
109 year = atoi(strtok((char *) NULL," "));
c801d85f
KB
110 }
111
112 mdy_to_julian ();
113}
114
115wxDate::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
125void 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
135void 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);
c67daf87
UR
151 day = atoi(strtok((char *) NULL,"/-"));
152 year = atoi(strtok((char *) NULL," "));
c801d85f
KB
153 }
154
155 mdy_to_julian ();
156}
157
158//////////////////////////////////////////////////////////////
159// Conversion operations
160//////////////////////////////////////////////////////////////
161
162wxDate::operator wxString( void )
163{
164 return FormatDate();
165}
166
167//////////////////////////////////////////////////////////////
168// Date Arithmetic
169//////////////////////////////////////////////////////////////
170
debe6624 171wxDate wxDate::operator + (long i)
c801d85f
KB
172{
173 wxDate dp(julian + i);
174 return dp;
175}
176
debe6624 177wxDate wxDate::operator + (int i)
c801d85f
KB
178{
179 wxDate dp(julian + (long)i);
180 return dp;
181}
182
debe6624 183wxDate wxDate::operator - (long i)
c801d85f
KB
184{
185 wxDate dp(julian - i);
186 return dp;
187}
188
debe6624 189wxDate wxDate::operator - (int i)
c801d85f
KB
190{
191 wxDate dp(julian - (long)i);
192 return dp;
193}
194
195long wxDate::operator - (const wxDate &dt)
196{
197 return ( julian - dt.julian );
198}
199
debe6624 200wxDate &wxDate::operator += (long i)
c801d85f
KB
201{
202 julian += i;
203 julian_to_mdy();
204 return *this;
205}
206
debe6624 207wxDate &wxDate::operator -= (long i)
c801d85f
KB
208{
209 julian -= i;
210 julian_to_mdy();
211 return *this;
212}
213
214wxDate &wxDate::operator ++()
215{
216 julian++;
217 julian_to_mdy();
218 return *this;
219}
220
221wxDate &wxDate::operator ++(int)
222{
223 julian++;
224 julian_to_mdy();
225 return *this;
226}
227
228wxDate &wxDate::operator --()
229{
230 julian--;
231 julian_to_mdy();
232 return *this;
233}
234
235wxDate &wxDate::operator --(int)
236{
237 julian--;
238 julian_to_mdy();
239 return *this;
240}
241
242//////////////////////////////////////////////////////////////
243// Date comparison
244//////////////////////////////////////////////////////////////
245
246bool operator < (const wxDate &dt1, const wxDate &dt2)
247{
248 return ( dt1.julian < dt2.julian );
249}
250
251bool operator <= (const wxDate &dt1, const wxDate &dt2)
252{
253 return ( (dt1.julian == dt2.julian) || (dt1.julian < dt2.julian) );
254}
255
256bool operator > (const wxDate &dt1, const wxDate &dt2)
257{
258 return ( dt1.julian > dt2.julian );
259}
260
261bool operator >= (const wxDate &dt1, const wxDate &dt2)
262{
263 return ( (dt1.julian == dt2.julian) || (dt1.julian > dt2.julian) );
264}
265
266bool operator == (const wxDate &dt1, const wxDate &dt2)
267{
268 return ( dt1.julian == dt2.julian );
269}
270
271bool operator != (const wxDate &dt1, const wxDate &dt2)
272{
273 return ( dt1.julian != dt2.julian );
274}
275
276////////////////////////////////////////////////////////////////
277// Ostream operations
278////////////////////////////////////////////////////////////////
279
280ostream &operator << (ostream &os, const wxDate &dt)
281{
282 return os << (const char *) dt.FormatDate();
283}
284
285//////////////////////////////////////////////////////////////
286// Conversion routines
287//////////////////////////////////////////////////////////////
288
289void wxDate::julian_to_wday (void)
290{
291 day_of_week = (int) ((julian + 2) % 7 + 1);
292}
293
294void 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
315void 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
debe6624 340wxString wxDate::FormatDate (int type) const
c801d85f
KB
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) )
1a5a8367 353 strcpy(buf, _("invalid day"));
c801d85f 354 else
1a5a8367 355 strncpy( buf, _(dayname[day_of_week-1]),
c801d85f
KB
356 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
357 return wxString(buf);
358
359 case wxMONTH:
360 if ( (month < 1) || (month > 12) )
1a5a8367 361 strcpy(buf, _("invalid month"));
c801d85f 362 else
1a5a8367 363 strncpy( buf, _(mname[month-1]),
c801d85f
KB
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 {
1a5a8367 371 strcpy(buf, _("invalid date"));
c801d85f
KB
372 return wxString(buf);
373 }
1a5a8367 374 strncpy( buf, _(dayname[day_of_week-1]),
c801d85f
KB
375 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
376 strcat( buf, ", ");
1a5a8367 377 strncat( buf, _(mname[month-1]),
c801d85f
KB
378 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
379 strcat( buf, " ");
380 sprintf( buf+strlen(buf), "%d, %d", day, abs(year) );
381 if (year < 0)
1a5a8367 382 strcat(buf,_(" B.C."));
c801d85f
KB
383 return wxString(buf);
384
385 case wxEUROPEAN:
386 if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
387 (day_of_week > 7) )
388 {
1a5a8367 389 strcpy(buf, _("invalid date"));
c801d85f
KB
390 return wxString(buf);
391 }
392 sprintf(buf,"%d ", day);
1a5a8367 393 strncat(buf, _(mname[month-1]),
c801d85f
KB
394 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
395 sprintf( buf+strlen(buf), " %d", abs(year) );
396 if (year < 0)
1a5a8367 397 strcat(buf, _(" B.C."));
c801d85f
KB
398 return wxString(buf);
399
400 case wxMDY:
401 default:
402 if (day==0 || month==0 || year==0)
1a5a8367 403 strcpy(buf, _("invalid date"));
c801d85f
KB
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
debe6624 414void wxDate::SetFormat( int format )
c801d85f
KB
415{
416 DisplayFormat = format;
417}
418
debe6624 419int wxDate::SetOption( int option, bool action )
c801d85f
KB
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
449long wxDate::GetJulianDate( void ) const
450{
451 return julian;
452}
453
454int wxDate::GetDayOfYear( void ) const
455{
456 wxDate temp( 1, 1, year );
457
458 return (int) (julian - temp.julian + 1);
459}
460
461
462bool 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
471wxDate& wxDate::Set()
472{
2049ba38 473//#ifdef __WXMSW__
c801d85f
KB
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
c67daf87 484 time_t now = time((time_t *) NULL);
c801d85f
KB
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
496wxDate& 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
510wxDate &
511wxDate::Set(long j)
512{
513 julian = j;
514
515 julian_to_mdy();
516 return *this;
517}
518
519
520int wxDate::GetDaysInMonth()
521{
522 return GauDays[month-1] + (month==2 && IsLeapYear());
523}
524
525int wxDate::GetFirstDayOfMonth() const
526{
527 return wxDate(month, 1, year).GetDayOfWeek();
528}
529
530int wxDate::GetDay() const
531{
532 return day;
533}
534
535int wxDate::GetDayOfWeek() const
536{
537 return day_of_week;
538}
539
540int wxDate::GetYear() const
541{
542 return year;
543}
544
545int wxDate::GetMonth() const
546{
547 return month;
548}
549
550wxDate& wxDate::AddWeeks(int nCount)
551{
552 Set(julian + (long)nCount*7);
553 return *this;
554}
555
556wxDate& 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
573wxDate& wxDate::AddYears(int nCount)
574{
575 year += nCount;
576 mdy_to_julian();
577 return *this;
578}
579
580int 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
588int wxDate::GetWeekOfYear()
589{
590 wxDate doTemp(1, 1, year);
591 return (int)(((julian - doTemp.julian+1)/7) + 1);
592}
593
594wxDate wxDate::GetMonthStart()
595{
596 return(wxDate(month, 1, year));
597}
598
599wxDate wxDate::GetMonthEnd()
600{
601 return(wxDate(month+1, 1, year)-1);
602}
603
604wxDate wxDate::GetYearStart()
605{
606 return(wxDate(1, 1, year));
607}
608
609wxDate wxDate::GetYearEnd()
610{
611 return(wxDate(1, 1, year+1)-1);
612}
613
614wxString wxDate::GetMonthName()
615{
616 return(FormatDate(wxMONTH));
617}
618
619wxString wxDate::GetDayOfWeekName()
620{
621 return(FormatDate(wxDAY));
622}
623
624bool 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
debe6624 630wxDate wxDate::Previous(int dayOfWeek) const
c801d85f
KB
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