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