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