introduced Date::IsValidDate() and Date::Normalize()

+ IsValidDate() checks only day and month regarding the year, not Gregorian
  cut-off date as now does IsValidAndGregorian().
+ Normalize() carries over invalid day and month values to next months and
  years.
* All methods that return or internally use a day count now internally
  normalize the date values, without modifying the actual Date instance. So,
  if the date is not valid you may get unexpected results.
  * Previously, a date with month>12 would had accessed the days-of-month
    array out of bounds on all such methods. So you would had gotten
    unexpected results anyway..
  * Affected methods are:
    GetDayOfYear()
    GetWeekOfYear()
    GetDaysInMonth()
    static DateToDays()
This commit is contained in:
Eike Rathke 2011-11-30 02:05:23 +01:00
parent dca69d5bb2
commit 6619955e72

View file

@ -60,6 +60,8 @@ inline sal_Bool ImpIsLeapYear( sal_uInt16 nYear )
// -----------------------------------------------------------------------
// All callers must have sanitized or normalized month and year values!
inline sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear )
{
if ( nMonth != 2 )
@ -79,6 +81,8 @@ long Date::DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
{
long nDays;
Normalize( nDay, nMonth, nYear);
nDays = ((sal_uIntPtr)nYear-1) * 365;
nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400);
for( sal_uInt16 i = 1; i < nMonth; i++ )
@ -203,9 +207,13 @@ DayOfWeek Date::GetDayOfWeek() const
sal_uInt16 Date::GetDayOfYear() const
{
sal_uInt16 nDay = GetDay();
for( sal_uInt16 i = 1; i < GetMonth(); i++ )
nDay = nDay + ::DaysInMonth( i, GetYear() ); // += yields a warning on MSVC, so don't use it
sal_uInt16 nDay = GetDay();
sal_uInt16 nMonth = GetMonth();
sal_uInt16 nYear = GetYear();
Normalize( nDay, nMonth, nYear);
for( sal_uInt16 i = 1; i < nMonth; i++ )
nDay = nDay + ::DaysInMonth( i, nYear ); // += yields a warning on MSVC, so don't use it
return nDay;
}
@ -305,7 +313,12 @@ sal_uInt16 Date::GetWeekOfYear( DayOfWeek eStartDay,
sal_uInt16 Date::GetDaysInMonth() const
{
return DaysInMonth( GetMonth(), GetYear() );
sal_uInt16 nDay = GetDay();
sal_uInt16 nMonth = GetMonth();
sal_uInt16 nYear = GetYear();
Normalize( nDay, nMonth, nYear);
return DaysInMonth( nMonth, nYear );
}
// -----------------------------------------------------------------------
@ -343,6 +356,94 @@ sal_Bool Date::IsValidAndGregorian() const
// -----------------------------------------------------------------------
bool Date::IsValidDate() const
{
return IsValidDate( GetDay(), GetMonth(), GetYear());
}
// -----------------------------------------------------------------------
//static
bool Date::IsValidDate( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
{
if ( !nMonth || (nMonth > 12) )
return false;
if ( !nDay || (nDay > DaysInMonth( nMonth, nYear )) )
return false;
return true;
}
// -----------------------------------------------------------------------
bool Date::Normalize()
{
sal_uInt16 nDay = GetDay();
sal_uInt16 nMonth = GetMonth();
sal_uInt16 nYear = GetYear();
if (!Normalize( nDay, nMonth, nYear))
return false;
SetDay( nDay);
SetMonth( nMonth);
SetYear( nYear);
return true;
}
// -----------------------------------------------------------------------
//static
bool Date::Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_uInt16 & rYear )
{
if (IsValidDate( rDay, rMonth, rYear))
return false;
if (rMonth > 12)
{
rYear += rMonth / 12;
rMonth = rMonth % 12;
}
if (!rMonth)
{
if (!rYear)
{
rYear = 0;
rMonth = 1;
if (rDay > 31)
rDay -= 31;
else
rDay = 1;
}
else
{
--rYear;
rMonth = 12;
}
}
sal_uInt16 nDays;
while (rDay > (nDays = DaysInMonth( rMonth, rYear)))
{
rDay -= nDays;
if (rMonth < 12)
++rMonth;
else
{
++rYear;
rMonth = 1;
}
}
if (rYear > 9999)
{
rDay = 31;
rMonth = 12;
rYear = 9999;
}
return true;
}
// -----------------------------------------------------------------------
Date& Date::operator +=( long nDays )
{
sal_uInt16 nDay;