]> git.saurik.com Git - wxWidgets.git/blame - src/common/date.cpp
another (last?) FreeBSD thread compilation fix
[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
11// Modified by:
12// Created: 01/02/97
13// RCS-ID: $Id$
14// Copyright: (c) Julian Smart and Markus Holzem
15// Licence: wxWindows licence
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
1a5a8367
DP
51static const char *dayname[] = {
52 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
53};
c801d85f 54
1a5a8367
DP
55static const char *mname[] = {
56 "January", "February", "March", "April", "May", "June", "July", "August",
57 "September", "October", "November", "December"
58};
c801d85f
KB
59
60static int GauDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
61
62#if !USE_SHARED_LIBRARY
63IMPLEMENT_DYNAMIC_CLASS(wxDate, wxObject)
64#endif
65
66////////////////////////////////////////////////////////////
67// Constructors
68////////////////////////////////////////////////////////////
69
70wxDate::wxDate()
71{
72 DisplayFormat=wxMDY;
73 DisplayOptions='\0';
74 month = day = year = day_of_week = 0;
75 julian = 0;
76}
77
debe6624 78wxDate::wxDate (long j) : julian(j)
c801d85f
KB
79{
80 DisplayFormat=wxMDY;
81 DisplayOptions='\0';
82 julian_to_mdy ();
83}
84
debe6624 85wxDate::wxDate (int m, int d, int y) : month(m), day(d), year(y)
c801d85f
KB
86{
87 DisplayFormat=wxMDY;
88 DisplayOptions='\0';
89 mdy_to_julian ();
90}
91
92wxDate::wxDate (const wxString& dat)
93{
94 DisplayFormat=wxMDY;
95 DisplayOptions='\0';
96 if (strcmp(dat, "TODAY") == 0 || strcmp(dat, "today") == 0)
97 {
98 // Sets the current date
99 Set();
100 }
101 else
102 {
103 char buf[100];
104 strcpy(buf, (char *) (const char *)dat);
105
106 char *token = strtok(buf,"/-");
107 month = atoi(token);
c67daf87
UR
108 day = atoi(strtok((char *) NULL,"/-"));
109 year = atoi(strtok((char *) NULL," "));
c801d85f
KB
110 }
111
112 mdy_to_julian ();
113}
114
115wxDate::wxDate (const wxDate &dt)
116{
117 DisplayFormat=dt.DisplayFormat;
118 DisplayOptions=dt.DisplayOptions;
119 month = dt.month;
120 day = dt.day;
121 year = dt.year;
122 mdy_to_julian ();
123}
124
125void wxDate::operator = (const wxDate &dt)
126{
127 DisplayFormat=dt.DisplayFormat;
128 DisplayOptions=dt.DisplayOptions;
129 month = dt.month;
130 day = dt.day;
131 year = dt.year;
132 mdy_to_julian ();
133}
134
135void wxDate::operator = (const wxString& dat)
136{
137 DisplayFormat=wxMDY;
138 DisplayOptions='\0';
139 if (strcmp(dat, "TODAY") == 0 || strcmp(dat, "today") == 0)
140 {
141 // Sets the current date
142 Set();
143 }
144 else
145 {
146 char buf[100];
147 strcpy(buf, (char *)(const char *)dat);
148
149 char *token = strtok(buf,"/-");
150 month = atoi(token);
c67daf87
UR
151 day = atoi(strtok((char *) NULL,"/-"));
152 year = atoi(strtok((char *) NULL," "));
c801d85f
KB
153 }
154
155 mdy_to_julian ();
156}
157
158//////////////////////////////////////////////////////////////
159// Conversion operations
160//////////////////////////////////////////////////////////////
161
ce3ed50d 162#ifndef __SALFORDC__
c801d85f
KB
163wxDate::operator wxString( void )
164{
165 return FormatDate();
166}
ce3ed50d 167#endif
c801d85f
KB
168
169//////////////////////////////////////////////////////////////
170// Date Arithmetic
171//////////////////////////////////////////////////////////////
172
debe6624 173wxDate wxDate::operator + (long i)
c801d85f
KB
174{
175 wxDate dp(julian + i);
176 return dp;
177}
178
debe6624 179wxDate wxDate::operator + (int i)
c801d85f
KB
180{
181 wxDate dp(julian + (long)i);
182 return dp;
183}
184
debe6624 185wxDate wxDate::operator - (long i)
c801d85f
KB
186{
187 wxDate dp(julian - i);
188 return dp;
189}
190
debe6624 191wxDate wxDate::operator - (int i)
c801d85f
KB
192{
193 wxDate dp(julian - (long)i);
194 return dp;
195}
196
197long wxDate::operator - (const wxDate &dt)
198{
199 return ( julian - dt.julian );
200}
201
debe6624 202wxDate &wxDate::operator += (long i)
c801d85f
KB
203{
204 julian += i;
205 julian_to_mdy();
206 return *this;
207}
208
debe6624 209wxDate &wxDate::operator -= (long i)
c801d85f
KB
210{
211 julian -= i;
212 julian_to_mdy();
213 return *this;
214}
215
216wxDate &wxDate::operator ++()
217{
218 julian++;
219 julian_to_mdy();
220 return *this;
221}
222
223wxDate &wxDate::operator ++(int)
224{
225 julian++;
226 julian_to_mdy();
227 return *this;
228}
229
230wxDate &wxDate::operator --()
231{
232 julian--;
233 julian_to_mdy();
234 return *this;
235}
236
237wxDate &wxDate::operator --(int)
238{
239 julian--;
240 julian_to_mdy();
241 return *this;
242}
243
244//////////////////////////////////////////////////////////////
245// Date comparison
246//////////////////////////////////////////////////////////////
247
a4abc0fc 248bool WXDLLEXPORT operator < (const wxDate &dt1, const wxDate &dt2)
c801d85f
KB
249{
250 return ( dt1.julian < dt2.julian );
251}
252
a4abc0fc 253bool WXDLLEXPORT operator <= (const wxDate &dt1, const wxDate &dt2)
c801d85f
KB
254{
255 return ( (dt1.julian == dt2.julian) || (dt1.julian < dt2.julian) );
256}
257
a4abc0fc 258bool WXDLLEXPORT operator > (const wxDate &dt1, const wxDate &dt2)
c801d85f
KB
259{
260 return ( dt1.julian > dt2.julian );
261}
262
a4abc0fc 263bool WXDLLEXPORT operator >= (const wxDate &dt1, const wxDate &dt2)
c801d85f
KB
264{
265 return ( (dt1.julian == dt2.julian) || (dt1.julian > dt2.julian) );
266}
267
a4abc0fc 268bool WXDLLEXPORT operator == (const wxDate &dt1, const wxDate &dt2)
c801d85f
KB
269{
270 return ( dt1.julian == dt2.julian );
271}
272
a4abc0fc 273bool WXDLLEXPORT operator != (const wxDate &dt1, const wxDate &dt2)
c801d85f
KB
274{
275 return ( dt1.julian != dt2.julian );
276}
277
278////////////////////////////////////////////////////////////////
279// Ostream operations
280////////////////////////////////////////////////////////////////
281
ba681060 282ostream WXDLLEXPORT & operator << (ostream &os, const wxDate &dt)
c801d85f
KB
283{
284 return os << (const char *) dt.FormatDate();
285}
286
287//////////////////////////////////////////////////////////////
288// Conversion routines
289//////////////////////////////////////////////////////////////
290
291void wxDate::julian_to_wday (void)
292{
293 day_of_week = (int) ((julian + 2) % 7 + 1);
294}
295
296void wxDate::julian_to_mdy ()
297{
298 long a,b,c,d,e,z,alpha;
299 z = julian+1;
300 // dealing with Gregorian calendar reform
301 if (z < 2299161L)
302 a = z;
303 else {
304 alpha = (long) ((z-1867216.25) / 36524.25);
305 a = z + 1 + alpha - alpha/4;
306 }
307 b = ( a > 1721423 ? a + 1524 : a + 1158 );
308 c = (long) ((b - 122.1) / 365.25);
309 d = (long) (365.25 * c);
310 e = (long) ((b - d) / 30.6001);
311 day = (int)(b - d - (long)(30.6001 * e));
312 month = (int)((e < 13.5) ? e - 1 : e - 13);
313 year = (int)((month > 2.5 ) ? (c - 4716) : c - 4715);
314 julian_to_wday ();
315}
316
317void wxDate::mdy_to_julian (void)
318{
319 int a,b=0;
320 int work_month=month, work_day=day, work_year=year;
321 // correct for negative year
322 if (work_year < 0)
323 work_year++;
324 if (work_month <= 2)
325 { work_year--; work_month +=12; }
326
327 // deal with Gregorian calendar
328 if (work_year*10000. + work_month*100. + work_day >= 15821015.)
329 {
330 a = (int)(work_year/100.);
331 b = 2 - a + a/4;
332 }
333 julian = (long) (365.25*work_year) +
334 (long) (30.6001 * (work_month+1)) + work_day + 1720994L + b;
335 julian_to_wday ();
336}
337
338////////////////////////////////////////////////////////////////
339// Format routine
340////////////////////////////////////////////////////////////////
341
debe6624 342wxString wxDate::FormatDate (int type) const
c801d85f
KB
343{
344 int actualType = type;
345 if (actualType == -1)
346 actualType = DisplayFormat;
347
348 char buf[40];
349
350 memset( buf, '\0', sizeof(buf) );
351 switch ( actualType )
352 {
353 case wxDAY:
354 if ( (day_of_week < 1) || (day_of_week > 7) )
1a5a8367 355 strcpy(buf, _("invalid day"));
c801d85f 356 else
1a5a8367 357 strncpy( buf, _(dayname[day_of_week-1]),
c801d85f
KB
358 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
359 return wxString(buf);
360
361 case wxMONTH:
362 if ( (month < 1) || (month > 12) )
1a5a8367 363 strcpy(buf, _("invalid month"));
c801d85f 364 else
1a5a8367 365 strncpy( buf, _(mname[month-1]),
c801d85f
KB
366 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
367 return wxString(buf);
368
369 case wxFULL:
370 if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
371 (day_of_week > 7) )
372 {
1a5a8367 373 strcpy(buf, _("invalid date"));
c801d85f
KB
374 return wxString(buf);
375 }
1a5a8367 376 strncpy( buf, _(dayname[day_of_week-1]),
c801d85f
KB
377 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
378 strcat( buf, ", ");
1a5a8367 379 strncat( buf, _(mname[month-1]),
c801d85f
KB
380 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
381 strcat( buf, " ");
382 sprintf( buf+strlen(buf), "%d, %d", day, abs(year) );
383 if (year < 0)
1a5a8367 384 strcat(buf,_(" B.C."));
c801d85f
KB
385 return wxString(buf);
386
387 case wxEUROPEAN:
388 if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
389 (day_of_week > 7) )
390 {
1a5a8367 391 strcpy(buf, _("invalid date"));
c801d85f
KB
392 return wxString(buf);
393 }
394 sprintf(buf,"%d ", day);
1a5a8367 395 strncat(buf, _(mname[month-1]),
c801d85f
KB
396 (DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
397 sprintf( buf+strlen(buf), " %d", abs(year) );
398 if (year < 0)
1a5a8367 399 strcat(buf, _(" B.C."));
c801d85f
KB
400 return wxString(buf);
401
402 case wxMDY:
403 default:
404 if (day==0 || month==0 || year==0)
1a5a8367 405 strcpy(buf, _("invalid date"));
c801d85f
KB
406 else
407 sprintf( buf+strlen(buf), "%1d/%1d/%02d", month, day,
408 (DisplayOptions & wxNO_CENTURY) && (abs(year) > 1899)
409 ? (abs(year) - (abs(year) / 100 * 100))
410 : (abs(year)) );
411 return wxString(buf);
412 }
413 return wxString("");
414}
415
debe6624 416void wxDate::SetFormat( int format )
c801d85f
KB
417{
418 DisplayFormat = format;
419}
420
debe6624 421int wxDate::SetOption( int option, bool action )
c801d85f
KB
422{
423 switch ( option )
424 {
425 case wxNO_CENTURY:
426 if ( action )
427 DisplayOptions |= wxNO_CENTURY;
428 else
429 {
430 DisplayOptions &= (~wxNO_CENTURY);
431 }
432 return 1;
433 case wxDATE_ABBR:
434 if ( action )
435 DisplayOptions |= wxDATE_ABBR;
436 else
437 {
438 DisplayOptions &= (~wxDATE_ABBR);
439 }
440 return 1;
441 default:
442 return 0;
443 }
444 return 0;
445}
446
447///////////////////////////////////////////////////////////////
448// Miscellaneous Routines
449///////////////////////////////////////////////////////////////
450
451long wxDate::GetJulianDate( void ) const
452{
453 return julian;
454}
455
456int wxDate::GetDayOfYear( void ) const
457{
458 wxDate temp( 1, 1, year );
459
460 return (int) (julian - temp.julian + 1);
461}
462
463
464bool wxDate::IsLeapYear( void ) const
465{
466 return ( (year >= 1582) ?
467 (year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ):
468 (year % 4 == 0) );
469}
470
471// Version 4.0 Extension to Public Interface - CDP
472
473wxDate& wxDate::Set()
474{
2049ba38 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(
499 int nMonth,
500 int nDay,
501 int nYear)
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();
509 return *this;
510}
511
512wxDate &
513wxDate::Set(long j)
514{
515 julian = j;
516
517 julian_to_mdy();
518 return *this;
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--;
565 }
566
567 if (month > 12) {
568 month = 1;
569 year++;
570 }
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{
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;
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{
628 return (julian >= first.julian && julian <= second.julian);
629}
630
631// This function is from NIHCL
debe6624 632wxDate wxDate::Previous(int dayOfWeek) const
c801d85f
KB
633{
634 int this_day_Of_Week, desired_day_Of_Week;
635 long j;
636
637// Set the desired and current day of week to start at 0 (Monday)
638// and end at 6 (Sunday).
639
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;
643
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).
647
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);
654}
655
656#endif