summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2011-11-30 02:05:23 +0100
committerEike Rathke <erack@redhat.com>2011-11-30 02:05:23 +0100
commit6619955e72c1c2f29a32e82478d19147c0d7610a (patch)
treecc4e45e240718901d7be246f51c8e4e6dda1892b /tools
parentdca69d5bb2d0e542de26624dd9f71fb87e1533f2 (diff)
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()
Diffstat (limited to 'tools')
-rw-r--r--tools/source/datetime/tdate.cxx109
1 files changed, 105 insertions, 4 deletions
diff --git a/tools/source/datetime/tdate.cxx b/tools/source/datetime/tdate.cxx
index 06b0bc4d1346..5deef5250b24 100644
--- a/tools/source/datetime/tdate.cxx
+++ b/tools/source/datetime/tdate.cxx
@@ -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;