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