diff options
Diffstat (limited to 'src/core/xbdate.cpp')
-rwxr-xr-x | src/core/xbdate.cpp | 341 |
1 files changed, 203 insertions, 138 deletions
diff --git a/src/core/xbdate.cpp b/src/core/xbdate.cpp index ba0fdf1..54834ac 100755 --- a/src/core/xbdate.cpp +++ b/src/core/xbdate.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -25,22 +25,36 @@ int xbDate::iAggregatedDaysInMonths[2][13]; //! @brief Constructor. xbDate::xbDate() { - Sysdate(); + sDate8.Set( "" ); SetDateTables(); } /*************************************************************************/ //! @brief Constructor. /*! + \param iInitOpt - Constructor to use to initialize date static variables + Called by the main xbXbase::xbXBase constructor +*/ + +xbDate::xbDate( xbUInt16 ) { + + SetDateTables(); + Sysdate(); +} +/*************************************************************************/ +//! @brief Constructor. +/*! \param sDate8In - Input date. */ xbDate::xbDate( const xbString & sDate8In ) { + if( DateIsValid( sDate8In )) sDate8.Set( sDate8In ); else - Sysdate(); - SetDateTables(); + sDate8.Set( "" ); + + // SetDateTables(); } /*************************************************************************/ @@ -53,8 +67,9 @@ xbDate::xbDate( const char * sDate8In ) { if( DateIsValid( sDate8In )) sDate8.Set( sDate8In ); else - Sysdate(); - SetDateTables(); + sDate8.Set( "" ); + + // SetDateTables(); } /*************************************************************************/ @@ -63,7 +78,7 @@ xbDate::xbDate( const char * sDate8In ) { \param lJulDate - Input julian date. */ xbDate::xbDate( xbInt32 lJulDate ) { - SetDateTables(); + // SetDateTables(); JulToDate8( lJulDate ); } @@ -81,68 +96,76 @@ void xbDate::operator=( const xbDate & dt ){ /*************************************************************************/ //! @brief operator += /*! - This routine adds lDays to the date + This routine adds lDays to the date if the date is not null. \param lDays - Number of days to add to the date. */ void xbDate::operator+=( xbInt32 lDays ){ - JulToDate8( JulianDays() + lDays ); + if( !IsNull() ) + JulToDate8( JulianDays() + lDays ); } /*************************************************************************/ //! @brief operator -= /*! - This routine subtracts lDays from the date. + This routine subtracts lDays from the date if the date is not null. \param lDays - Number of days to subtract from the date. */ void xbDate::operator-=( xbInt32 lDays ){ - JulToDate8( JulianDays() - lDays ); + if( !IsNull() ) + JulToDate8( JulianDays() - lDays ); } /*************************************************************************/ //! @brief operator ++ /*! - This routine adds one day to the date field. + This routine adds one day to the date field if the date is not null. */ void xbDate::operator++(xbInt32){ - *this+=1; + if( !IsNull() ) + *this+=1; } /*************************************************************************/ //! @brief operator -- /*! - This routine subtracts one day from the date field. + This routine subtracts one day from the date field if the date is not null. */ void xbDate::operator--(xbInt32){ - *this-=1; - return; + if( !IsNull()) + *this-=1; } /*************************************************************************/ //! @brief operator - /*! This routine subtracts one date from another date returning the difference. - \param dt - Date to subtract. - \returns Number of days + \param dt - Date to subtract + \returns Number of days difference or zero if one of the dates is null. */ xbInt32 xbDate::operator-( const xbDate &dt ) const{ - return JulianDays() - dt.JulianDays(); + if( !IsNull() && !dt.IsNull() ) + return JulianDays() - dt.JulianDays(); + else + return 0; } /*************************************************************************/ //! @brief operator + /*! - This routine adds additional days to a date field. + This routine adds additional days to a valid date field. \param lCount - Number of days to add. \returns New date in CCYYMMDD format. */ const char *xbDate::operator+( xbInt32 lCount ){ - JulToDate8( JulianDays() + lCount ); + if( !IsNull() ) + JulToDate8( JulianDays() + lCount ); return sDate8.Str(); } /*************************************************************************/ //! @brief operator - /*! - This routine subtracts days from a date field. + This routine subtracts days from a valid date field. \param lCount - Number of days to subtract. \returns New date in CCYYMMDD format. */ const char *xbDate::operator-( xbInt32 lCount ){ - JulToDate8( JulianDays() - lCount ); + if( !IsNull() ) + JulToDate8( JulianDays() - lCount ); return sDate8; } /*************************************************************************/ @@ -232,13 +255,14 @@ xbBool xbDate::operator>=( const xbDate &dt ) const { /*! This routine calculates a century for a given year. It uses an 80/20 rolling date window to calculate the century. - + \param iCalcYear - Two digit year to calculate a century for. \returns Century calculated for the two digit year. */ xbInt16 xbDate::CalcRollingCenturyForYear( xbInt16 iCalcYear ) const { xbDate d; + d.Sysdate(); xbInt16 iThisYear = d.YearOf(); xbInt16 iThisCentury = d.CenturyOf(); iThisYear -= (iThisCentury * 100); @@ -254,14 +278,18 @@ xbInt16 xbDate::CalcRollingCenturyForYear( xbInt16 iCalcYear ) const { /*************************************************************************/ //! @brief Get century for date. /*! - \returns This routine returns the century from the date. + \returns the century from the valid date.\ or 0 for a null date. */ xbInt16 xbDate::CenturyOf() const { - char Century[3]; - Century[0] = sDate8[1]; - Century[1] = sDate8[2]; - Century[2] = 0x00; - return( atoi( Century )); + if( !IsNull() ){ + char Century[3]; + Century[0] = sDate8[1]; + Century[1] = sDate8[2]; + Century[2] = 0x00; + return( atoi( Century )); + } else { + return 0; + } } /*************************************************************************/ //! @brief Get the day of the week. @@ -271,22 +299,24 @@ xbInt16 xbDate::CenturyOf() const { */ xbInt16 xbDate::CharDayOf( xbString &sOutCharDay ) { - struct tm tblock; - char buf[25]; - - tblock.tm_year = YearOf() - 1900; - tblock.tm_mon = MonthOf() - 1; - tblock.tm_mday = DayOf( XB_FMT_MONTH ); - tblock.tm_hour = 0; - tblock.tm_min = 0; - tblock.tm_sec = 1; - tblock.tm_isdst = -1; - if( mktime( &tblock ) == -1 ){ - sOutCharDay = "" ; - return XB_INVALID_DATE; - } else { - strftime( buf, 25, "%A", &tblock ); - sOutCharDay = buf; + if( !IsNull()){ + struct tm tblock; + char buf[25]; + + tblock.tm_year = YearOf() - 1900; + tblock.tm_mon = MonthOf() - 1; + tblock.tm_mday = DayOf( XB_FMT_MONTH ); + tblock.tm_hour = 0; + tblock.tm_min = 0; + tblock.tm_sec = 1; + tblock.tm_isdst = -1; + if( mktime( &tblock ) == -1 ){ + sOutCharDay = "" ; + return XB_INVALID_DATE; + } else { + strftime( buf, 25, "%A", &tblock ); + sOutCharDay = buf; + } } return XB_NO_ERROR;; } @@ -297,21 +327,24 @@ xbInt16 xbDate::CharDayOf( xbString &sOutCharDay ) { \returns XB_INVALID_DATE<br>XB_NO_ERROR */ xbInt16 xbDate::CharMonthOf( xbString &sOutCharMonth ) { - struct tm tblock; - char buf[25]; - tblock.tm_year = YearOf() - 1900; - tblock.tm_mon = MonthOf() - 1; - tblock.tm_mday = DayOf( XB_FMT_MONTH ); - tblock.tm_hour = 0; - tblock.tm_min = 0; - tblock.tm_sec = 1; - tblock.tm_isdst = -1; - if( mktime( &tblock ) == -1 ){ - sOutCharMonth = ""; - return XB_INVALID_DATE; - } else { - strftime( buf, 25, "%B", &tblock ); - sOutCharMonth = buf; + + if( !IsNull()){ + struct tm tblock; + char buf[25]; + tblock.tm_year = YearOf() - 1900; + tblock.tm_mon = MonthOf() - 1; + tblock.tm_mday = DayOf( XB_FMT_MONTH ); + tblock.tm_hour = 0; + tblock.tm_min = 0; + tblock.tm_sec = 1; + tblock.tm_isdst = -1; + if( mktime( &tblock ) == -1 ){ + sOutCharMonth = ""; + return XB_INVALID_DATE; + } else { + strftime( buf, 25, "%B", &tblock ); + sOutCharMonth = buf; + } } return XB_NO_ERROR; } @@ -387,45 +420,48 @@ xbBool xbDate::DateIsValid( const xbString &sDateIn ) const { xbInt16 xbDate::DayOf( xbInt16 iFormat ) const { - xbInt16 iOutDay = 0; - char sDay[3]; - xbInt16 iDay, iMonth, iYear, iDay2; - - // check for valid format switch - if( iFormat!=XB_FMT_WEEK && iFormat!=XB_FMT_MONTH && iFormat!=XB_FMT_YEAR ) - return XB_INVALID_OPTION; - - if( iFormat == XB_FMT_WEEK ){ - //DayOf( XB_FMT_MONTH, iDay ); - iDay = DayOf( XB_FMT_MONTH ); - iMonth = MonthOf(); - iYear = YearOf(); - - // The following formula uses Zeller's Congruence to determine the day of the week - if( iMonth > 2 ) // init to February - iMonth -= 2; - else { - iMonth += 10; - iYear--; - } - iDay2 = ((13 * iMonth - 1) / 5) + iDay + ( iYear % 100 ) + - (( iYear % 100 ) / 4) + ((iYear /100 ) / 4 ) - 2 * - ( iYear / 100 ) + 77 ; + if( !IsNull()){ + xbInt16 iOutDay = 0; + char sDay[3]; + xbInt16 iDay, iMonth, iYear, iDay2; + + // check for valid format switch + if( iFormat!=XB_FMT_WEEK && iFormat!=XB_FMT_MONTH && iFormat!=XB_FMT_YEAR ) + return XB_INVALID_OPTION; + + if( iFormat == XB_FMT_WEEK ){ + //DayOf( XB_FMT_MONTH, iDay ); + iDay = DayOf( XB_FMT_MONTH ); + iMonth = MonthOf(); + iYear = YearOf(); + + // The following formula uses Zeller's Congruence to determine the day of the week + if( iMonth > 2 ) // init to February + iMonth -= 2; + else { + iMonth += 10; + iYear--; + } + iDay2 = ((13 * iMonth - 1) / 5) + iDay + ( iYear % 100 ) + + (( iYear % 100 ) / 4) + ((iYear /100 ) / 4 ) - 2 * + ( iYear / 100 ) + 77 ; - iOutDay = iDay2 - 7 * ( iDay2 / 7 ); - iOutDay == 6 ? iOutDay = 0 : iOutDay++; - } - else if( iFormat == XB_FMT_MONTH ){ - sDay[0] = sDate8[7]; - sDay[1] = sDate8[8]; - sDay[2] = 0x00; - iOutDay = atoi( sDay ); + iOutDay = iDay2 - 7 * ( iDay2 / 7 ); + iOutDay == 6 ? iOutDay = 0 : iOutDay++; + } + else if( iFormat == XB_FMT_MONTH ){ + sDay[0] = sDate8[7]; + sDay[1] = sDate8[8]; + sDay[2] = 0x00; + iOutDay = atoi( sDay ); + } else { + iOutDay = iAggregatedDaysInMonths[IsLeapYear()][MonthOf()-1] + DayOf( XB_FMT_MONTH ); + } + return iOutDay; } else { - iOutDay = iAggregatedDaysInMonths[IsLeapYear()][MonthOf()-1] + DayOf( XB_FMT_MONTH ); + return 0; } - return iOutDay; } - /*************************************************************************/ #ifdef XB_DEBUG_SUPPORT //! @brief Dump date information to stdout. @@ -466,7 +502,6 @@ void xbDate::DumpDateTables(){ */ xbInt16 xbDate::CTOD( const xbString &sCtodInDate ){ - if( sCtodInDate[1] != ' ' && ( sCtodInDate[3] == '\\' || sCtodInDate[3] == '/') ){ char yy[3]; yy[0] = sCtodInDate[7]; @@ -518,6 +553,9 @@ xbInt16 xbDate::FormatDate( const xbString &sFmtIn, xbString &sOutFmtDate ){ xbString sWrkFmt; sOutFmtDate = ""; + if( IsNull()) + return XB_NO_ERROR; + /* use format for this specific string if available, else use default format */ if( strlen( sFmtIn ) > 0 ) sWrkFmt = sFmtIn; @@ -600,6 +638,8 @@ const char * xbDate::Str() const{ \returns xbTrue - Is leapyear.<br> xbFalse - Not a leap year. */ xbBool xbDate::IsLeapYear() const { + if( IsNull() ) + return xbFalse; xbInt16 iYear = YearOf(); if(( iYear % 4 == 0 && iYear % 100 != 0 ) || iYear % 400 == 0 ) return xbTrue; @@ -619,15 +659,30 @@ xbBool xbDate::IsLeapYear( xbInt16 iYear ) const { return xbFalse; } /*************************************************************************/ +//! @brief Determine if date is null date +/*! + \returns xbTrue - If null date.<br> xbFalse - Not a null date. +*/ +xbBool xbDate::IsNull() const { + if( sDate8.Len() < 8 ) + return xbTrue; + else + return xbFalse; +} +/*************************************************************************/ //! @brief Calculate julian days for a given date. /*! \returns The number of days since 01/01/0001 + JUL_OFFSET. */ xbInt32 xbDate::JulianDays() const{ - xbInt32 ly = YearOf() - 1; - xbInt32 lDays = ly * 365L + ly / 4L - ly / 100L + ly / 400L; - lDays += DayOf( XB_FMT_YEAR ); - return lDays + JUL_OFFSET; + if( !IsNull()){ + xbInt32 ly = YearOf() - 1; + xbInt32 lDays = ly * 365L + ly / 4L - ly / 100L + ly / 400L; + lDays += DayOf( XB_FMT_YEAR ); + return lDays + JUL_OFFSET; + } else { + return 0; + } } /*************************************************************************/ //! @brief Convert the number of julian days to gregorian date. @@ -637,24 +692,23 @@ xbInt32 xbDate::JulianDays() const{ */ xbInt16 xbDate::JulToDate8( xbInt32 lJulDays ) { - lJulDays -= JUL_OFFSET; - // calculate the year - xbInt16 iYear = (xbInt16)(lJulDays / 365.24 ); - lJulDays -= (iYear * 365L) + (iYear / 4L) - (iYear / 100L) + (iYear / 400L); - iYear++; - while( lJulDays <= 0 ){ - iYear--; - lJulDays += (365L + IsLeapYear( iYear )); - } - // this for loop calculates the month by comparing the number of days remaining to one of the tables - xbInt16 iIsLeap = IsLeapYear(iYear); - xbInt16 iMonth = 1; - while( ((xbInt16) lJulDays > iAggregatedDaysInMonths[iIsLeap][iMonth]) && (iMonth < 12) ) - iMonth++; - - lJulDays -= iAggregatedDaysInMonths[iIsLeap][iMonth-1]; - sDate8.Sprintf( "%04d%02d%02ld", iYear, iMonth, lJulDays ); - return XB_NO_ERROR; + lJulDays -= JUL_OFFSET; + // calculate the year + xbInt16 iYear = (xbInt16)(lJulDays / 365.24 ); + lJulDays -= (iYear * 365L) + (iYear / 4L) - (iYear / 100L) + (iYear / 400L); + iYear++; + while( lJulDays <= 0 ){ + iYear--; + lJulDays += (365L + IsLeapYear( iYear )); + } + // this for loop calculates the month by comparing the number of days remaining to one of the tables + xbInt16 iIsLeap = IsLeapYear(iYear); + xbInt16 iMonth = 1; + while( ((xbInt16) lJulDays > iAggregatedDaysInMonths[iIsLeap][iMonth]) && (iMonth < 12) ) + iMonth++; + lJulDays -= iAggregatedDaysInMonths[iIsLeap][iMonth-1]; + sDate8.Sprintf( "%04d%02d%02ld", iYear, iMonth, lJulDays ); + return XB_NO_ERROR; } /*************************************************************************/ //! @brief Set the date to the last day of month for a given date. @@ -663,7 +717,8 @@ xbInt16 xbDate::JulToDate8( xbInt32 lJulDays ) \returns XB_NO_ERROR */ xbInt16 xbDate::LastDayOfMonth(){ - sDate8.Sprintf( "%4.4d%2.2d%2.2d", YearOf(), MonthOf(), iDaysInMonths[IsLeapYear()][MonthOf()]); + if( !IsNull()) + sDate8.Sprintf( "%4.4d%2.2d%2.2d", YearOf(), MonthOf(), iDaysInMonths[IsLeapYear()][MonthOf()]); return XB_NO_ERROR; }; /*************************************************************************/ @@ -672,27 +727,33 @@ xbInt16 xbDate::LastDayOfMonth(){ \returns The month of the date. */ xbInt16 xbDate::MonthOf() const { - xbInt16 iOutMonth; - char month[3]; - month[0] = sDate8[5]; - month[1] = sDate8[6]; - month[2] = 0x00; - iOutMonth = atoi( month ); - return iOutMonth; + if( !IsNull()){ + xbInt16 iOutMonth; + char month[3]; + month[0] = sDate8[5]; + month[1] = sDate8[6]; + month[2] = 0x00; + iOutMonth = atoi( month ); + return iOutMonth; + } else { + return 0; + } } /*************************************************************************/ //! @brief Set the date. /*! \param sDateIn - Input date. - \returns XB_NO_ERROR<br>XB_INVALID_DATE + \returns XB_NO_ERROR */ xbInt16 xbDate::Set( const xbString & sDateIn ){ + if( DateIsValid( sDateIn )){ sDate8 = sDateIn; - return XB_NO_ERROR; + } else { + sDate8 = ""; // set to null date if invalid date } - return XB_INVALID_DATE; + return XB_NO_ERROR; } /*************************************************************************/ //! @brief This routine sets up static data tables on startup. @@ -790,13 +851,17 @@ xbInt16 xbDate::Sysdate(){ \returns The year of the date. */ xbInt16 xbDate::YearOf() const { - char year[5]; - year[0] = sDate8[1]; - year[1] = sDate8[2]; - year[2] = sDate8[3]; - year[3] = sDate8[4]; - year[4] = 0x00; - xbInt16 iOutYear = atoi( year ); - return iOutYear; + if( !IsNull()){ + char year[5]; + year[0] = sDate8[1]; + year[1] = sDate8[2]; + year[2] = sDate8[3]; + year[3] = sDate8[4]; + year[4] = 0x00; + xbInt16 iOutYear = atoi( year ); + return iOutYear; + } else { + return 0; + } }; } /* namespace */
\ No newline at end of file |