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