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:
parent
dca69d5bb2
commit
6619955e72
1 changed files with 105 additions and 4 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue