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