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