Files
wxWidgets/src/common/date.cpp
Robert Roebling 3883022093 Work on streams of all sorts. More to come.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2908 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1999-06-27 10:39:38 +00:00

661 lines
15 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: date.cpp
// Purpose: wxDate class
// Author:
// Originally inspired by Steve Marcus (CIS 72007,1233) 6/16/91
// Enhanced by Eric Simon (CIS 70540,1522) 6/29/91
// Further Enhanced by Chris Hill (CIS 72030,2606) 7/11/91
// Still Further Enhanced by Hill & Simon v3.10 8/05/91
// Version 4 by Charles D. Price 6/27/92
// Integrated into wxWindows by Julian Smart 9th July 1995
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) Julian Smart and Markus Holzem
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "date.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_TIMEDATE
#include "wx/date.h"
#include "wx/intl.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "wx/ioswrap.h"
#include <time.h>
#include <string.h>
#define ABBR_LENGTH 3
static const wxChar *dayname[] = {
_T("Sunday"), _T("Monday"), _T("Tuesday"), _T("Wednesday"),
_T("Thursday"), _T("Friday"), _T("Saturday")
};
static const wxChar *mname[] = {
_T("January"), _T("February"), _T("March"), _T("April"), _T("May"), _T("June"),
_T("July"), _T("August"), _T("September"), _T("October"), _T("November"), _T("December")
};
static int GauDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
#if !USE_SHARED_LIBRARY
IMPLEMENT_DYNAMIC_CLASS(wxDate, wxObject)
#endif
////////////////////////////////////////////////////////////
// Constructors
////////////////////////////////////////////////////////////
wxDate::wxDate()
{
DisplayFormat=wxMDY;
DisplayOptions='\0';
month = day = year = day_of_week = 0;
julian = 0;
}
wxDate::wxDate (long j) : julian(j)
{
DisplayFormat=wxMDY;
DisplayOptions='\0';
julian_to_mdy ();
}
wxDate::wxDate (int m, int d, int y) : month(m), day(d), year(y)
{
DisplayFormat=wxMDY;
DisplayOptions='\0';
mdy_to_julian ();
}
wxDate::wxDate (const wxString& dat)
{
DisplayFormat=wxMDY;
DisplayOptions='\0';
if (wxStrcmp(dat, _T("TODAY")) == 0 || wxStrcmp(dat, _T("today")) == 0)
{
// Sets the current date
Set();
}
else
{
wxChar buf[100];
wxStrcpy(buf, WXSTRINGCAST dat);
wxChar *save_ptr, *token = wxStrtok(buf,_T("/-"),&save_ptr);
month = wxAtoi(token);
day = wxAtoi(wxStrtok((wxChar *) NULL,_T("/-"),&save_ptr));
year = wxAtoi(wxStrtok((wxChar *) NULL,_T(" "),&save_ptr));
}
mdy_to_julian ();
}
wxDate::wxDate (const wxDate &dt)
{
DisplayFormat=dt.DisplayFormat;
DisplayOptions=dt.DisplayOptions;
month = dt.month;
day = dt.day;
year = dt.year;
mdy_to_julian ();
}
void wxDate::operator = (const wxDate &dt)
{
DisplayFormat=dt.DisplayFormat;
DisplayOptions=dt.DisplayOptions;
month = dt.month;
day = dt.day;
year = dt.year;
mdy_to_julian (); // wxUSE_TIMEDATE
}
void wxDate::operator = (const wxString& dat)
{
DisplayFormat=wxMDY;
DisplayOptions='\0';
if (wxStrcmp(dat, _T("TODAY")) == 0 || wxStrcmp(dat, _T("today")) == 0)
{
// Sets the current date
Set();
}
else
{
wxChar buf[100];
wxStrcpy(buf, WXSTRINGCAST dat);
wxChar *save_ptr, *token = wxStrtok(buf,_T("/-"),&save_ptr);
month = wxAtoi(token);
day = wxAtoi(wxStrtok((wxChar *) NULL,_T("/-"),&save_ptr));
year = wxAtoi(wxStrtok((wxChar *) NULL,_T(" "),&save_ptr));
}
mdy_to_julian ();
}
//////////////////////////////////////////////////////////////
// Conversion operations
//////////////////////////////////////////////////////////////
#ifndef __SALFORDC__
wxDate::operator wxString( void )
{
return FormatDate();
}
#endif
//////////////////////////////////////////////////////////////
// Date Arithmetic
//////////////////////////////////////////////////////////////
wxDate wxDate::operator + (long i)
{
wxDate dp(julian + i);
return dp;
}
wxDate wxDate::operator + (int i)
{
wxDate dp(julian + (long)i);
return dp;
}
wxDate wxDate::operator - (long i)
{
wxDate dp(julian - i);
return dp;
}
wxDate wxDate::operator - (int i)
{
wxDate dp(julian - (long)i);
return dp;
}
long wxDate::operator - (const wxDate &dt)
{
return ( julian - dt.julian );
}
wxDate &wxDate::operator += (long i)
{
julian += i;
julian_to_mdy();
return *this;
}
wxDate &wxDate::operator -= (long i)
{
julian -= i;
julian_to_mdy();
return *this;
}
wxDate &wxDate::operator ++()
{
julian++;
julian_to_mdy();
return *this;
}
wxDate &wxDate::operator ++(int)
{
julian++;
julian_to_mdy();
return *this;
}
wxDate &wxDate::operator --()
{
julian--;
julian_to_mdy();
return *this;
}
wxDate &wxDate::operator --(int)
{
julian--;
julian_to_mdy();
return *this;
}
//////////////////////////////////////////////////////////////
// Date comparison
//////////////////////////////////////////////////////////////
bool WXDLLEXPORT operator < (const wxDate &dt1, const wxDate &dt2)
{
return ( dt1.julian < dt2.julian );
}
bool WXDLLEXPORT operator <= (const wxDate &dt1, const wxDate &dt2)
{
return ( (dt1.julian == dt2.julian) || (dt1.julian < dt2.julian) );
}
bool WXDLLEXPORT operator > (const wxDate &dt1, const wxDate &dt2)
{
return ( dt1.julian > dt2.julian );
}
bool WXDLLEXPORT operator >= (const wxDate &dt1, const wxDate &dt2)
{
return ( (dt1.julian == dt2.julian) || (dt1.julian > dt2.julian) );
}
bool WXDLLEXPORT operator == (const wxDate &dt1, const wxDate &dt2)
{
return ( dt1.julian == dt2.julian );
}
bool WXDLLEXPORT operator != (const wxDate &dt1, const wxDate &dt2)
{
return ( dt1.julian != dt2.julian );
}
#if wxUSE_STD_IOSTREAM
////////////////////////////////////////////////////////////////
// Ostream operations
////////////////////////////////////////////////////////////////
ostream WXDLLEXPORT & operator << (ostream &os, const wxDate &dt)
{
return os << dt.FormatDate().mb_str();
}
#endif
//////////////////////////////////////////////////////////////
// Conversion routines
//////////////////////////////////////////////////////////////
void wxDate::julian_to_wday (void)
{
// Correction by Peter Stadel <peters@jetcity.com>
day_of_week = ((julian - 2) % 7L);
/*
day_of_week = (int) ((julian + 2) % 7 + 1);
*/
}
void wxDate::julian_to_mdy ()
{
long a,b,c,d,e,z,alpha;
z = julian+1;
// dealing with Gregorian calendar reform
if (z < 2299161L)
a = z;
else {
alpha = (long) ((z-1867216.25) / 36524.25);
a = z + 1 + alpha - alpha/4;
}
b = ( a > 1721423 ? a + 1524 : a + 1158 );
c = (long) ((b - 122.1) / 365.25);
d = (long) (365.25 * c);
e = (long) ((b - d) / 30.6001);
day = (int)(b - d - (long)(30.6001 * e));
month = (int)((e < 13.5) ? e - 1 : e - 13);
year = (int)((month > 2.5 ) ? (c - 4716) : c - 4715);
julian_to_wday ();
}
void wxDate::mdy_to_julian (void)
{
int a,b=0;
int work_month=month, work_day=day, work_year=year;
// correct for negative year
if (work_year < 0)
work_year++;
if (work_month <= 2)
{ work_year--; work_month +=12; }
// deal with Gregorian calendar
if (work_year*10000. + work_month*100. + work_day >= 15821015.)
{
a = (int)(work_year/100.);
b = 2 - a + a/4;
}
julian = (long) (365.25*work_year) +
(long) (30.6001 * (work_month+1)) + work_day + 1720994L + b;
julian_to_wday ();
}
////////////////////////////////////////////////////////////////
// Format routine
////////////////////////////////////////////////////////////////
wxString wxDate::FormatDate (int type) const
{
int actualType = type;
if (actualType == -1)
actualType = DisplayFormat;
wxChar buf[40];
memset( buf, '\0', sizeof(buf) );
switch ( actualType )
{
case wxDAY:
if ( (day_of_week < 1) || (day_of_week > 7) )
wxStrcpy(buf, _("invalid day"));
else
wxStrncpy( buf, wxGetTranslation(dayname[day_of_week-1]),
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
return wxString(buf);
case wxMONTH:
if ( (month < 1) || (month > 12) )
wxStrcpy(buf, _("invalid month"));
else
wxStrncpy( buf, wxGetTranslation(mname[month-1]),
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
return wxString(buf);
case wxFULL:
if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
(day_of_week > 7) )
{
wxStrcpy(buf, _("invalid date"));
return wxString(buf);
}
wxStrncpy( buf, wxGetTranslation(dayname[day_of_week-1]),
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
wxStrcat( buf, _T(", "));
wxStrncat( buf, wxGetTranslation(mname[month-1]),
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
wxStrcat( buf, _T(" "));
wxSprintf( buf+wxStrlen(buf), _T("%d, %d"), day, abs(year) );
if (year < 0)
wxStrcat(buf,_(" B.C."));
return wxString(buf);
case wxEUROPEAN:
if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
(day_of_week > 7) )
{
wxStrcpy(buf, _("invalid date"));
return wxString(buf);
}
wxSprintf(buf,_T("%d "), day);
wxStrncat(buf, wxGetTranslation(mname[month-1]),
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
wxSprintf( buf+wxStrlen(buf), _T(" %d"), abs(year) );
if (year < 0)
wxStrcat(buf, _(" B.C."));
return wxString(buf);
case wxMDY:
default:
if (day==0 || month==0 || year==0)
wxStrcpy(buf, _("invalid date"));
else
wxSprintf( buf+wxStrlen(buf), _T("%1d/%1d/%02d"), month, day,
(DisplayOptions & wxNO_CENTURY) && (abs(year) > 1899)
? (abs(year) - (abs(year) / 100 * 100))
: (abs(year)) );
return wxString(buf);
}
return wxString(_T(""));
}
void wxDate::SetFormat( int format )
{
DisplayFormat = format;
}
int wxDate::SetOption( int option, bool action )
{
switch ( option )
{
case wxNO_CENTURY:
if ( action )
DisplayOptions |= wxNO_CENTURY;
else
{
DisplayOptions &= (~wxNO_CENTURY);
}
return 1;
case wxDATE_ABBR:
if ( action )
DisplayOptions |= wxDATE_ABBR;
else
{
DisplayOptions &= (~wxDATE_ABBR);
}
return 1;
default:
return 0;
}
return 0;
}
///////////////////////////////////////////////////////////////
// Miscellaneous Routines
///////////////////////////////////////////////////////////////
long wxDate::GetJulianDate( void ) const
{
return julian;
}
int wxDate::GetDayOfYear( void ) const
{
wxDate temp( 1, 1, year );
return (int) (julian - temp.julian + 1);
}
bool wxDate::IsLeapYear( void ) const
{
return ( (year >= 1582) ?
(year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ):
(year % 4 == 0) );
}
// Version 4.0 Extension to Public Interface - CDP
wxDate& wxDate::Set()
{
//#ifdef __WXMSW__
#if 0
struct _dosdate_t sDate;
_dos_getdate(&sDate);
month = sDate.month;
day = sDate.day;
year = sDate.year;
mdy_to_julian();
#else
time_t now = time((time_t *) NULL);
struct tm *localTime = localtime(&now);
month = localTime->tm_mon + 1;
day = localTime->tm_mday;
year = localTime->tm_year + 1900;
mdy_to_julian ();
#endif
return *this;
}
wxDate& wxDate::Set(
int nMonth,
int nDay,
int nYear)
{
month = nMonth;
year = nYear < 0 ? 9999 : nYear;
year = nYear > 9999 ? 0 : nYear;
day = nDay < GetDaysInMonth() ? nDay : GetDaysInMonth();
mdy_to_julian();
return *this;
}
wxDate &
wxDate::Set(long j)
{
julian = j;
julian_to_mdy();
return *this;
}
int wxDate::GetDaysInMonth()
{
return GauDays[month-1] + (month==2 && IsLeapYear());
}
int wxDate::GetFirstDayOfMonth() const
{
return wxDate(month, 1, year).GetDayOfWeek();
}
int wxDate::GetDay() const
{
return day;
}
int wxDate::GetDayOfWeek() const
{
return day_of_week;
}
int wxDate::GetYear() const
{
return year;
}
int wxDate::GetMonth() const
{
return month;
}
wxDate& wxDate::AddWeeks(int nCount)
{
Set(julian + (long)nCount*7);
return *this;
}
wxDate& wxDate::AddMonths(int nCount)
{
month += nCount;
if (month < 1) {
month = 12;
year--;
}
if (month > 12) {
month = 1;
year++;
}
mdy_to_julian();
return *this;
}
wxDate& wxDate::AddYears(int nCount)
{
year += nCount;
mdy_to_julian();
return *this;
}
int wxDate::GetWeekOfMonth()
{
// Abs day includes the days from previous month that fills up
// the begin. of the week.
int nAbsDay = day + GetFirstDayOfMonth()-1;
return (nAbsDay-GetDayOfWeek())/7 + 1;
}
int wxDate::GetWeekOfYear()
{
wxDate doTemp(1, 1, year);
return (int)(((julian - doTemp.julian+1)/7) + 1);
}
wxDate wxDate::GetMonthStart()
{
return(wxDate(month, 1, year));
}
wxDate wxDate::GetMonthEnd()
{
return(wxDate(month+1, 1, year)-1);
}
wxDate wxDate::GetYearStart()
{
return(wxDate(1, 1, year));
}
wxDate wxDate::GetYearEnd()
{
return(wxDate(1, 1, year+1)-1);
}
wxString wxDate::GetMonthName()
{
return(FormatDate(wxMONTH));
}
wxString wxDate::GetDayOfWeekName()
{
return(FormatDate(wxDAY));
}
bool wxDate::IsBetween(const wxDate& first, const wxDate& second) const
{
return (julian >= first.julian && julian <= second.julian);
}
// This function is from NIHCL
wxDate wxDate::Previous(int dayOfWeek) const
{
int this_day_Of_Week, desired_day_Of_Week;
long j;
// Set the desired and current day of week to start at 0 (Monday)
// and end at 6 (Sunday).
desired_day_Of_Week = dayOfWeek - 1; // These functions return a value
this_day_Of_Week = GetDayOfWeek() - 1; // from 1-7. Subtract 1 for 0-6.
j = julian;
// Have to determine how many days difference from current day back to
// desired, if any. Special calculation under the 'if' statement to
// effect the wraparound counting from Monday (0) back to Sunday (6).
if (desired_day_Of_Week > this_day_Of_Week)
this_day_Of_Week += 7 - desired_day_Of_Week;
else
this_day_Of_Week -= desired_day_Of_Week;
j -= this_day_Of_Week; // Adjust j to set it at the desired day of week.
return wxDate(j);
}
#endif