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