]> git.saurik.com Git - wxWidgets.git/blame - src/common/date.cpp
Attempt to implement a bunch of wx string.h equivalents.
[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
ce4169a4
RR
29#ifndef WX_PRECOMP
30 #include "wx/defs.h"
31#endif
c801d85f 32
9838df2c 33#if wxUSE_TIMEDATE
c801d85f
KB
34
35#include "wx/date.h"
1a5a8367 36#include <wx/intl.h>
c801d85f
KB
37
38#include <stdio.h>
39#include <string.h>
40#include <stdlib.h>
41
47d67540 42#if wxUSE_IOSTREAMH
c801d85f
KB
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
50920146
OK
53static const wxChar *dayname[] = {
54 _T("Sunday"), _T("Monday"), _T("Tuesday"), _T("Wednesday"),
55 _T("Thursday"), _T("Friday"), _T("Saturday")
1a5a8367 56};
c801d85f 57
50920146
OK
58static 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")
1a5a8367 61};
c801d85f
KB
62
63static int GauDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
64
65#if !USE_SHARED_LIBRARY
66IMPLEMENT_DYNAMIC_CLASS(wxDate, wxObject)
67#endif
68
c30aaf75
VZ
69 ////////////////////////////////////////////////////////////
70 // Constructors
71 ////////////////////////////////////////////////////////////
c801d85f
KB
72
73wxDate::wxDate()
74{
c30aaf75
VZ
75 DisplayFormat=wxMDY;
76 DisplayOptions='\0';
77 month = day = year = day_of_week = 0;
78 julian = 0;
c801d85f
KB
79}
80
debe6624 81wxDate::wxDate (long j) : julian(j)
c801d85f 82{
c30aaf75
VZ
83 DisplayFormat=wxMDY;
84 DisplayOptions='\0';
85 julian_to_mdy ();
c801d85f
KB
86}
87
debe6624 88wxDate::wxDate (int m, int d, int y) : month(m), day(d), year(y)
c801d85f 89{
c30aaf75
VZ
90 DisplayFormat=wxMDY;
91 DisplayOptions='\0';
92 mdy_to_julian ();
c801d85f
KB
93}
94
95wxDate::wxDate (const wxString& dat)
96{
c30aaf75
VZ
97 DisplayFormat=wxMDY;
98 DisplayOptions='\0';
50920146 99 if (wxStrcmp(dat, _T("TODAY")) == 0 || wxStrcmp(dat, _T("today")) == 0)
c30aaf75
VZ
100 {
101 // Sets the current date
102 Set();
103 }
104 else
105 {
50920146
OK
106 wxChar buf[100];
107 wxStrcpy(buf, WXSTRINGCAST dat);
c30aaf75 108
50920146
OK
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));
c30aaf75 113 }
c801d85f 114
c30aaf75 115 mdy_to_julian ();
c801d85f
KB
116}
117
118wxDate::wxDate (const wxDate &dt)
119{
c30aaf75
VZ
120 DisplayFormat=dt.DisplayFormat;
121 DisplayOptions=dt.DisplayOptions;
122 month = dt.month;
123 day = dt.day;
124 year = dt.year;
125 mdy_to_julian ();
c801d85f
KB
126}
127
128void wxDate::operator = (const wxDate &dt)
129{
c30aaf75
VZ
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
c801d85f
KB
136}
137
138void wxDate::operator = (const wxString& dat)
139{
c30aaf75
VZ
140 DisplayFormat=wxMDY;
141 DisplayOptions='\0';
50920146 142 if (wxStrcmp(dat, _T("TODAY")) == 0 || wxStrcmp(dat, _T("today")) == 0)
c30aaf75
VZ
143 {
144 // Sets the current date
145 Set();
146 }
147 else
148 {
50920146
OK
149 wxChar buf[100];
150 wxStrcpy(buf, WXSTRINGCAST dat);
c30aaf75 151
50920146
OK
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));
c30aaf75 156 }
c801d85f 157
c30aaf75 158 mdy_to_julian ();
c801d85f
KB
159}
160
161//////////////////////////////////////////////////////////////
162// Conversion operations
163//////////////////////////////////////////////////////////////
164
ce3ed50d 165#ifndef __SALFORDC__
c801d85f
KB
166wxDate::operator wxString( void )
167{
c30aaf75 168 return FormatDate();
c801d85f 169}
ce3ed50d 170#endif
c801d85f
KB
171
172//////////////////////////////////////////////////////////////
173// Date Arithmetic
174//////////////////////////////////////////////////////////////
175
debe6624 176wxDate wxDate::operator + (long i)
c801d85f 177{
c30aaf75
VZ
178 wxDate dp(julian + i);
179 return dp;
c801d85f
KB
180}
181
debe6624 182wxDate wxDate::operator + (int i)
c801d85f 183{
c30aaf75
VZ
184 wxDate dp(julian + (long)i);
185 return dp;
c801d85f
KB
186}
187
debe6624 188wxDate wxDate::operator - (long i)
c801d85f 189{
c30aaf75
VZ
190 wxDate dp(julian - i);
191 return dp;
c801d85f
KB
192}
193
debe6624 194wxDate wxDate::operator - (int i)
c801d85f 195{
c30aaf75
VZ
196 wxDate dp(julian - (long)i);
197 return dp;
c801d85f
KB
198}
199
200long wxDate::operator - (const wxDate &dt)
201{
c30aaf75 202 return ( julian - dt.julian );
c801d85f
KB
203}
204
debe6624 205wxDate &wxDate::operator += (long i)
c801d85f 206{
c30aaf75
VZ
207 julian += i;
208 julian_to_mdy();
209 return *this;
c801d85f
KB
210}
211
debe6624 212wxDate &wxDate::operator -= (long i)
c801d85f 213{
c30aaf75
VZ
214 julian -= i;
215 julian_to_mdy();
216 return *this;
c801d85f
KB
217}
218
219wxDate &wxDate::operator ++()
220{
c30aaf75 221 julian++;
c801d85f 222 julian_to_mdy();
c30aaf75 223 return *this;
c801d85f
KB
224}
225
226wxDate &wxDate::operator ++(int)
227{
c30aaf75 228 julian++;
c801d85f 229 julian_to_mdy();
c30aaf75 230 return *this;
c801d85f
KB
231}
232
233wxDate &wxDate::operator --()
234{
c30aaf75 235 julian--;
c801d85f 236 julian_to_mdy();
c30aaf75 237 return *this;
c801d85f
KB
238}
239
240wxDate &wxDate::operator --(int)
241{
c30aaf75 242 julian--;
c801d85f 243 julian_to_mdy();
c30aaf75 244 return *this;
c801d85f
KB
245}
246
247//////////////////////////////////////////////////////////////
248// Date comparison
249//////////////////////////////////////////////////////////////
250
a4abc0fc 251bool WXDLLEXPORT operator < (const wxDate &dt1, const wxDate &dt2)
c801d85f 252{
c30aaf75 253 return ( dt1.julian < dt2.julian );
c801d85f
KB
254}
255
a4abc0fc 256bool WXDLLEXPORT operator <= (const wxDate &dt1, const wxDate &dt2)
c801d85f 257{
c30aaf75 258 return ( (dt1.julian == dt2.julian) || (dt1.julian < dt2.julian) );
c801d85f
KB
259}
260
a4abc0fc 261bool WXDLLEXPORT operator > (const wxDate &dt1, const wxDate &dt2)
c801d85f 262{
c30aaf75 263 return ( dt1.julian > dt2.julian );
c801d85f
KB
264}
265
a4abc0fc 266bool WXDLLEXPORT operator >= (const wxDate &dt1, const wxDate &dt2)
c801d85f 267{
c30aaf75 268 return ( (dt1.julian == dt2.julian) || (dt1.julian > dt2.julian) );
c801d85f
KB
269}
270
a4abc0fc 271bool WXDLLEXPORT operator == (const wxDate &dt1, const wxDate &dt2)
c801d85f 272{
c30aaf75 273 return ( dt1.julian == dt2.julian );
c801d85f
KB
274}
275
a4abc0fc 276bool WXDLLEXPORT operator != (const wxDate &dt1, const wxDate &dt2)
c801d85f 277{
c30aaf75 278 return ( dt1.julian != dt2.julian );
c801d85f
KB
279}
280
281////////////////////////////////////////////////////////////////
282// Ostream operations
283////////////////////////////////////////////////////////////////
284
ba681060 285ostream WXDLLEXPORT & operator << (ostream &os, const wxDate &dt)
c801d85f 286{
00421206 287 return os << dt.FormatDate().mb_str();
c801d85f
KB
288}
289
290//////////////////////////////////////////////////////////////
291// Conversion routines
292//////////////////////////////////////////////////////////////
293
294void wxDate::julian_to_wday (void)
295{
dcb44466
JS
296 // Correction by Peter Stadel <peters@jetcity.com>
297 day_of_week = ((julian - 2) % 7L);
298/*
c30aaf75 299 day_of_week = (int) ((julian + 2) % 7 + 1);
dcb44466 300*/
c801d85f
KB
301}
302
303void wxDate::julian_to_mdy ()
304{
c30aaf75
VZ
305 long a,b,c,d,e,z,alpha;
306 z = julian+1;
307 // dealing with Gregorian calendar reform
c801d85f 308 if (z < 2299161L)
c30aaf75 309 a = z;
c801d85f 310 else {
c30aaf75
VZ
311 alpha = (long) ((z-1867216.25) / 36524.25);
312 a = z + 1 + alpha - alpha/4;
c801d85f 313 }
c30aaf75
VZ
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);
c801d85f
KB
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);
c30aaf75 321 julian_to_wday ();
c801d85f
KB
322}
323
324void wxDate::mdy_to_julian (void)
325{
c30aaf75
VZ
326 int a,b=0;
327 int work_month=month, work_day=day, work_year=year;
328 // correct for negative year
c801d85f 329 if (work_year < 0)
c30aaf75
VZ
330 work_year++;
331 if (work_month <= 2)
332 { work_year--; work_month +=12; }
c801d85f 333
c30aaf75
VZ
334 // deal with Gregorian calendar
335 if (work_year*10000. + work_month*100. + work_day >= 15821015.)
336 {
c801d85f 337 a = (int)(work_year/100.);
c30aaf75
VZ
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 ();
c801d85f
KB
343}
344
345////////////////////////////////////////////////////////////////
346// Format routine
347////////////////////////////////////////////////////////////////
348
debe6624 349wxString wxDate::FormatDate (int type) const
c801d85f 350{
c30aaf75
VZ
351 int actualType = type;
352 if (actualType == -1)
353 actualType = DisplayFormat;
c801d85f 354
50920146 355 wxChar buf[40];
c801d85f
KB
356
357 memset( buf, '\0', sizeof(buf) );
c30aaf75
VZ
358 switch ( actualType )
359 {
360 case wxDAY:
361 if ( (day_of_week < 1) || (day_of_week > 7) )
50920146 362 wxStrcpy(buf, _("invalid day"));
c30aaf75 363 else
50920146
OK
364 wxStrncpy( buf, wxGetTranslation(dayname[day_of_week-1]),
365 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
c30aaf75
VZ
366 return wxString(buf);
367
368 case wxMONTH:
369 if ( (month < 1) || (month > 12) )
50920146 370 wxStrcpy(buf, _("invalid month"));
c30aaf75 371 else
50920146
OK
372 wxStrncpy( buf, wxGetTranslation(mname[month-1]),
373 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
c30aaf75
VZ
374 return wxString(buf);
375
376 case wxFULL:
377 if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
378 (day_of_week > 7) )
379 {
50920146 380 wxStrcpy(buf, _("invalid date"));
c30aaf75
VZ
381 return wxString(buf);
382 }
50920146
OK
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) );
c30aaf75 390 if (year < 0)
50920146 391 wxStrcat(buf,_(" B.C."));
c30aaf75
VZ
392 return wxString(buf);
393
394 case wxEUROPEAN:
395 if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
396 (day_of_week > 7) )
397 {
50920146 398 wxStrcpy(buf, _("invalid date"));
c30aaf75
VZ
399 return wxString(buf);
400 }
50920146
OK
401 wxSprintf(buf,_T("%d "), day);
402 wxStrncat(buf, wxGetTranslation(mname[month-1]),
c30aaf75 403 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
50920146 404 wxSprintf( buf+wxStrlen(buf), _T(" %d"), abs(year) );
c30aaf75 405 if (year < 0)
50920146 406 wxStrcat(buf, _(" B.C."));
c30aaf75
VZ
407 return wxString(buf);
408
409 case wxMDY:
410 default:
411 if (day==0 || month==0 || year==0)
50920146 412 wxStrcpy(buf, _("invalid date"));
c30aaf75 413 else
50920146
OK
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)) );
c30aaf75
VZ
418 return wxString(buf);
419 }
50920146 420 return wxString(_T(""));
c801d85f
KB
421}
422
debe6624 423void wxDate::SetFormat( int format )
c801d85f 424{
c30aaf75 425 DisplayFormat = format;
c801d85f
KB
426}
427
debe6624 428int wxDate::SetOption( int option, bool action )
c801d85f 429{
c30aaf75
VZ
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;
c801d85f
KB
452}
453
454///////////////////////////////////////////////////////////////
455// Miscellaneous Routines
456///////////////////////////////////////////////////////////////
457
458long wxDate::GetJulianDate( void ) const
459{
c30aaf75 460 return julian;
c801d85f
KB
461}
462
463int wxDate::GetDayOfYear( void ) const
464{
c30aaf75 465 wxDate temp( 1, 1, year );
c801d85f 466
c30aaf75 467 return (int) (julian - temp.julian + 1);
c801d85f
KB
468}
469
470
471bool wxDate::IsLeapYear( void ) const
472{
c30aaf75
VZ
473 return ( (year >= 1582) ?
474 (year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ):
475 (year % 4 == 0) );
c801d85f
KB
476}
477
478// Version 4.0 Extension to Public Interface - CDP
479
480wxDate& wxDate::Set()
481{
c30aaf75 482 //#ifdef __WXMSW__
c801d85f
KB
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
c67daf87 493 time_t now = time((time_t *) NULL);
c801d85f
KB
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
505wxDate& wxDate::Set(
c30aaf75
VZ
506 int nMonth,
507 int nDay,
508 int nYear)
c801d85f
KB
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();
c30aaf75 516 return *this;
c801d85f
KB
517}
518
519wxDate &
520wxDate::Set(long j)
521{
c30aaf75 522 julian = j;
c801d85f 523
c30aaf75
VZ
524 julian_to_mdy();
525 return *this;
c801d85f
KB
526}
527
528
529int wxDate::GetDaysInMonth()
530{
531 return GauDays[month-1] + (month==2 && IsLeapYear());
532}
533
534int wxDate::GetFirstDayOfMonth() const
535{
536 return wxDate(month, 1, year).GetDayOfWeek();
537}
538
539int wxDate::GetDay() const
540{
541 return day;
542}
543
544int wxDate::GetDayOfWeek() const
545{
546 return day_of_week;
547}
548
549int wxDate::GetYear() const
550{
551 return year;
552}
553
554int wxDate::GetMonth() const
555{
556 return month;
557}
558
559wxDate& wxDate::AddWeeks(int nCount)
560{
561 Set(julian + (long)nCount*7);
562 return *this;
563}
564
565wxDate& wxDate::AddMonths(int nCount)
566{
567 month += nCount;
568
569 if (month < 1) {
570 month = 12;
571 year--;
c30aaf75 572 }
c801d85f
KB
573
574 if (month > 12) {
575 month = 1;
576 year++;
c30aaf75 577 }
c801d85f
KB
578 mdy_to_julian();
579 return *this;
580}
581
582wxDate& wxDate::AddYears(int nCount)
583{
584 year += nCount;
585 mdy_to_julian();
586 return *this;
587}
588
589int wxDate::GetWeekOfMonth()
590{
c30aaf75
VZ
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;
c801d85f
KB
595}
596
597int wxDate::GetWeekOfYear()
598{
599 wxDate doTemp(1, 1, year);
600 return (int)(((julian - doTemp.julian+1)/7) + 1);
601}
602
603wxDate wxDate::GetMonthStart()
604{
605 return(wxDate(month, 1, year));
606}
607
608wxDate wxDate::GetMonthEnd()
609{
610 return(wxDate(month+1, 1, year)-1);
611}
612
613wxDate wxDate::GetYearStart()
614{
615 return(wxDate(1, 1, year));
616}
617
618wxDate wxDate::GetYearEnd()
619{
620 return(wxDate(1, 1, year+1)-1);
621}
622
623wxString wxDate::GetMonthName()
624{
625 return(FormatDate(wxMONTH));
626}
627
628wxString wxDate::GetDayOfWeekName()
629{
630 return(FormatDate(wxDAY));
631}
632
633bool wxDate::IsBetween(const wxDate& first, const wxDate& second) const
634{
c30aaf75 635 return (julian >= first.julian && julian <= second.julian);
c801d85f
KB
636}
637
638// This function is from NIHCL
debe6624 639wxDate wxDate::Previous(int dayOfWeek) const
c801d85f 640{
c30aaf75
VZ
641 int this_day_Of_Week, desired_day_Of_Week;
642 long j;
c801d85f 643
c30aaf75
VZ
644 // Set the desired and current day of week to start at 0 (Monday)
645 // and end at 6 (Sunday).
c801d85f 646
c30aaf75
VZ
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;
c801d85f 650
c30aaf75
VZ
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).
c801d85f 654
c30aaf75
VZ
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);
c801d85f
KB
661}
662
663#endif