diff options
author | Eike Rathke <erack@redhat.com> | 2016-07-08 17:08:47 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2016-07-08 20:41:02 +0000 |
commit | 6d4f2dcc7cbba771e9d9b00de50368db4a88ef1b (patch) | |
tree | 0301896941b955ffa79ef3e96b874ebdad78662c | |
parent | 06287b9c348281612854d67c4eb2e7a38dc722ca (diff) |
Resolves: tdf#100452 class Date full (BCE,CE) proleptic Gregorian calendar
... implementing signed years with year 0 gap.
Date(31,12,-1) last day BCE
Date(1,1,1) first day CE
New class Date member functions:
* AddYears(sal_Int16) to be used instead of
aDate.SetYear(aDate.GetYear()+sal_Int16) to handle year 0 gap.
* convenience GetNextYear() to be used insted of GetYear()+1
* convenience GetPrevYear() to be used insted of GetYear()-1
* AddMonths(sal_Int32)
* operator=(const css::util::Date&)
New class DateTime member functions:
* operator=(const css::util::DateTime&)
Made some conversion ctors explicit, specifically Date(sal_Int32)
Adapted hopefully all places that used a sal_uInt16 year to use
sal_Int16 where appropriate.
Eliminated some quirks in date handling found on the fly.
Added era handling to i18npool icu calendar setting interface, which
missing was responsible for 0001-01-01 entered in Calc being set as
-0001-01-01, hence subtracting one day resulted in -0002-12-31.
Change-Id: I77b39fba9599ebd5067d7864f6c9ebe01f6f578f
Reviewed-on: https://gerrit.libreoffice.org/27049
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins <ci@libreoffice.org>
49 files changed, 523 insertions, 232 deletions
diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx index 296af1514bcd..2abca341ca68 100644 --- a/basic/source/runtime/methods.cxx +++ b/basic/source/runtime/methods.cxx @@ -4858,7 +4858,7 @@ sal_Int16 implGetDateYear( double aDate ) long nDays = (long) aDate; nDays -= 2; // standardize: 1.1.1900 => 0.0 aRefDate += nDays; - sal_Int16 nRet = (sal_Int16)( aRefDate.GetYear() ); + sal_Int16 nRet = aRefDate.GetYear(); return nRet; } @@ -4917,7 +4917,7 @@ bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, double& { nYearAdj = ( ( nMonth -12 ) / 12 ); } - aCurDate.SetYear( aCurDate.GetYear() + nYearAdj ); + aCurDate.AddYears( nYearAdj ); } // adjust day value, diff --git a/chart2/source/tools/NumberFormatterWrapper.cxx b/chart2/source/tools/NumberFormatterWrapper.cxx index 52c6a5250a55..1151aa4aeaab 100644 --- a/chart2/source/tools/NumberFormatterWrapper.cxx +++ b/chart2/source/tools/NumberFormatterWrapper.cxx @@ -98,7 +98,8 @@ OUString NumberFormatterWrapper::getFormattedString( sal_Int32 nNumberFormatKey, return aText; } // i99104 handle null date correctly - sal_uInt16 nYear = 1899,nDay = 30,nMonth = 12; + sal_Int16 nYear = 1899; + sal_uInt16 nDay = 30,nMonth = 12; if ( m_aNullDate.hasValue() ) { Date* pDate = m_pNumberFormatter->GetNullDate(); diff --git a/chart2/source/view/axes/DateHelper.cxx b/chart2/source/view/axes/DateHelper.cxx index d8c872711c51..42a77cd045ec 100644 --- a/chart2/source/view/axes/DateHelper.cxx +++ b/chart2/source/view/axes/DateHelper.cxx @@ -37,27 +37,17 @@ bool DateHelper::IsInSameMonth( const Date& rD1, const Date& rD2 ) && (rD1.GetMonth() == rD2.GetMonth()); } -Date DateHelper::GetDateSomeMonthsAway( const Date& rD, long nMonthDistance ) +Date DateHelper::GetDateSomeMonthsAway( const Date& rD, sal_Int32 nMonthDistance ) { Date aRet(rD); - long nMonth = rD.GetMonth()+nMonthDistance; - long nNewMonth = nMonth%12; - long nNewYear = rD.GetYear() + nMonth/12; - if( nMonth <= 0 || !nNewMonth ) - nNewYear--; - if( nNewMonth <= 0 ) - nNewMonth += 12; - aRet.SetMonth( sal_uInt16(nNewMonth) ); - aRet.SetYear( sal_uInt16(nNewYear) ); - aRet.Normalize(); + aRet.AddMonths( nMonthDistance ); return aRet; } -Date DateHelper::GetDateSomeYearsAway( const Date& rD, long nYearDistance ) +Date DateHelper::GetDateSomeYearsAway( const Date& rD, sal_Int32 nYearDistance ) { Date aRet(rD); - aRet.SetYear( static_cast<sal_uInt16>(rD.GetYear()+nYearDistance) ); - aRet.Normalize(); + aRet.AddYears( static_cast<sal_Int16>(nYearDistance) ); return aRet; } diff --git a/chart2/source/view/inc/DateHelper.hxx b/chart2/source/view/inc/DateHelper.hxx index 3142e90c9f1d..099985533853 100644 --- a/chart2/source/view/inc/DateHelper.hxx +++ b/chart2/source/view/inc/DateHelper.hxx @@ -31,8 +31,8 @@ public: static bool IsInSameYear( const Date& rD1, const Date& rD2 ); static bool IsInSameMonth( const Date& rD1, const Date& rD2 ); - static Date GetDateSomeMonthsAway( const Date& rD, long nMonthDistance ); - static Date GetDateSomeYearsAway( const Date& rD, long nYearDistance ); + static Date GetDateSomeMonthsAway( const Date& rD, sal_Int32 nMonthDistance ); + static Date GetDateSomeYearsAway( const Date& rD, sal_Int32 nYearDistance ); static bool IsLessThanOneMonthAway( const Date& rD1, const Date& rD2 ); static bool IsLessThanOneYearAway( const Date& rD1, const Date& rD2 ); diff --git a/connectivity/source/drivers/dbase/DTable.cxx b/connectivity/source/drivers/dbase/DTable.cxx index 52215a4eef80..4c39e43e6d22 100644 --- a/connectivity/source/drivers/dbase/DTable.cxx +++ b/connectivity/source/drivers/dbase/DTable.cxx @@ -1218,7 +1218,7 @@ bool ODbaseTable::CreateFile(const INetURLObject& aFile, bool& bCreateMemo) m_pFileStream->Seek(0L); (*m_pFileStream).WriteUChar( nDbaseType ); // dBase format - (*m_pFileStream).WriteUChar( aDate.GetYear() % 100 ); // current date + (*m_pFileStream).WriteUChar( aDate.GetYearUnsigned() % 100 ); // current date (*m_pFileStream).WriteUChar( aDate.GetMonth() ); diff --git a/editeng/source/items/flditem.cxx b/editeng/source/items/flditem.cxx index 4f2c03e4b23e..11309d4a0521 100644 --- a/editeng/source/items/flditem.cxx +++ b/editeng/source/items/flditem.cxx @@ -396,7 +396,7 @@ void SvxDateField::Load( SvPersistStream & rStm ) { sal_uInt16 nType, nFormat; - rStm.ReadUInt32( nFixDate ); + rStm.ReadInt32( nFixDate ); rStm.ReadUInt16( nType ); rStm.ReadUInt16( nFormat ); @@ -407,7 +407,7 @@ void SvxDateField::Load( SvPersistStream & rStm ) void SvxDateField::Save( SvPersistStream & rStm ) { - rStm.WriteUInt32( nFixDate ); + rStm.WriteInt32( nFixDate ); rStm.WriteUInt16( eType ); rStm.WriteUInt16( eFormat ); } diff --git a/editeng/source/uno/unofield.cxx b/editeng/source/uno/unofield.cxx index 6a26bcddf741..5a0dddd48186 100644 --- a/editeng/source/uno/unofield.cxx +++ b/editeng/source/uno/unofield.cxx @@ -176,7 +176,7 @@ static SvxFileFormat setFileNameDisplayFormat( sal_Int16 nFormat ) } } -static util::DateTime getDate( sal_uLong nDate ) +static util::DateTime getDate( sal_Int32 nDate ) { util::DateTime aDate; memset( &aDate, 0, sizeof( util::DateTime ) ); diff --git a/i18npool/inc/calendar_gregorian.hxx b/i18npool/inc/calendar_gregorian.hxx index 4f333815a918..4a16c00c3eb6 100644 --- a/i18npool/inc/calendar_gregorian.hxx +++ b/i18npool/inc/calendar_gregorian.hxx @@ -116,9 +116,9 @@ private: /** Submit fieldSetValue array according to fieldSet. */ void submitFields() throw(css::uno::RuntimeException); - /** Submit fieldSetValue array according to fieldSet, plus YMDhms if >=0, + /** Submit fieldSetValue array according to fieldSet, plus EYMDhms if >=0, plus zone and DST if != 0 */ - void submitValues( sal_Int32 nYear, sal_Int32 nMonth, sal_Int32 nDay, sal_Int32 nHour, sal_Int32 nMinute, sal_Int32 nSecond, sal_Int32 nMilliSecond, sal_Int32 nZone, sal_Int32 nDST) throw(css::uno::RuntimeException); + void submitValues( sal_Int32 nEra, sal_Int32 nYear, sal_Int32 nMonth, sal_Int32 nDay, sal_Int32 nHour, sal_Int32 nMinute, sal_Int32 nSecond, sal_Int32 nMilliSecond, sal_Int32 nZone, sal_Int32 nDST) throw(css::uno::RuntimeException); /** Set fields internally. */ void setValue() throw(css::uno::RuntimeException); /** Obtain combined field values for timezone offset (minutes+secondmillis) diff --git a/i18npool/source/calendar/calendar_gregorian.cxx b/i18npool/source/calendar/calendar_gregorian.cxx index fc470e109e8e..275b24dff0ed 100644 --- a/i18npool/source/calendar/calendar_gregorian.cxx +++ b/i18npool/source/calendar/calendar_gregorian.cxx @@ -491,12 +491,14 @@ void Calendar_gregorian::submitFields() throw(css::uno::RuntimeException) body->set( fieldNameConverter( CalendarFieldIndex::DST_OFFSET), nDSTOffset); } -void Calendar_gregorian::submitValues( sal_Int32 nYear, +void Calendar_gregorian::submitValues( sal_Int32 nEra, sal_Int32 nYear, sal_Int32 nMonth, sal_Int32 nDay, sal_Int32 nHour, sal_Int32 nMinute, sal_Int32 nSecond, sal_Int32 nMilliSecond, sal_Int32 nZone, sal_Int32 nDST ) throw(css::uno::RuntimeException) { submitFields(); + if (nEra >= 0) + body->set( UCAL_ERA, nEra); if (nYear >= 0) body->set( UCAL_YEAR, nYear); if (nMonth >= 0) @@ -567,12 +569,18 @@ void Calendar_gregorian::setValue() throw(RuntimeException) bool bNeedZone = !(fieldSet & (1 << CalendarFieldIndex::ZONE_OFFSET)); bool bNeedDST = !(fieldSet & (1 << CalendarFieldIndex::DST_OFFSET)); - sal_Int32 nZone1, nDST1, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone0, nDST0; + sal_Int32 nZone1, nDST1, nEra, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone0, nDST0; nZone1 = nDST1 = nZone0 = nDST0 = 0; - nYear = nMonth = nDay = nHour = nMinute = nSecond = nMilliSecond = -1; + nEra = nYear = nMonth = nDay = nHour = nMinute = nSecond = nMilliSecond = -1; if ( bNeedZone || bNeedDST ) { UErrorCode status; + if ( !(fieldSet & (1 << CalendarFieldIndex::ERA)) ) + { + nEra = body->get( UCAL_ERA, status = U_ZERO_ERROR); + if ( !U_SUCCESS(status) ) + nEra = -1; + } if ( !(fieldSet & (1 << CalendarFieldIndex::YEAR)) ) { nYear = body->get( UCAL_YEAR, status = U_ZERO_ERROR); @@ -629,7 +637,7 @@ void Calendar_gregorian::setValue() throw(RuntimeException) } // Submit values to obtain a time zone and DST corresponding to the date/time. - submitValues( nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone0, nDST0); + submitValues( nEra, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone0, nDST0); DUMP_ICU_CAL_MSG(("%s\n","setValue() in bNeedZone||bNeedDST after submitValues()")); DUMP_I18N_CAL_MSG(("%s\n","setValue() in bNeedZone||bNeedDST after submitValues()")); @@ -680,7 +688,7 @@ void Calendar_gregorian::setValue() throw(RuntimeException) lcl_setCombinedOffsetFieldValues( nDST2, fieldSetValue, fieldValue, CalendarFieldIndex::DST_OFFSET, CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS); - submitValues( nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone2, nDST2); + submitValues( nEra, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone2, nDST2); DUMP_ICU_CAL_MSG(("%s\n","setValue() after Zone/DST glitch resubmit")); DUMP_I18N_CAL_MSG(("%s\n","setValue() after Zone/DST glitch resubmit")); @@ -726,7 +734,7 @@ void Calendar_gregorian::setValue() throw(RuntimeException) } if (bResubmit) { - submitValues( nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone3, nDST3); + submitValues( nEra, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone3, nDST3); DUMP_ICU_CAL_MSG(("%s\n","setValue() after Zone/DST glitch 2nd resubmit")); DUMP_I18N_CAL_MSG(("%s\n","setValue() after Zone/DST glitch 2nd resubmit")); } diff --git a/include/editeng/flditem.hxx b/include/editeng/flditem.hxx index 649167a20118..fd01faed6d83 100644 --- a/include/editeng/flditem.hxx +++ b/include/editeng/flditem.hxx @@ -106,7 +106,7 @@ enum SvxDateFormat { SVXDATEFORMAT_APPDEFAULT = 0, // Set as in App class EDITENG_DLLPUBLIC SvxDateField : public SvxFieldData { - sal_uInt32 nFixDate; + sal_Int32 nFixDate; SvxDateType eType; SvxDateFormat eFormat; @@ -118,7 +118,7 @@ public: SvxDateType eType = SVXDATETYPE_VAR, SvxDateFormat eFormat = SVXDATEFORMAT_STDSMALL ); - sal_uInt32 GetFixDate() const { return nFixDate; } + sal_Int32 GetFixDate() const { return nFixDate; } void SetFixDate( const Date& rDate ) { nFixDate = rDate.GetDate(); } SvxDateType GetType() const { return eType; } diff --git a/include/svl/zforlist.hxx b/include/svl/zforlist.hxx index de78ae51b484..e28b4aeb2cfd 100644 --- a/include/svl/zforlist.hxx +++ b/include/svl/zforlist.hxx @@ -333,7 +333,7 @@ public: /// Change language/country, also input and format scanner void ChangeIntl( LanguageType eLnge ); /// Change the reference null date - void ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear); + void ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear); /// Change standard precision void ChangeStandardPrec(short nPrec); /// Set zero value suppression diff --git a/include/svtools/calendar.hxx b/include/svtools/calendar.hxx index 144f78250821..3814d11a702b 100644 --- a/include/svtools/calendar.hxx +++ b/include/svtools/calendar.hxx @@ -146,7 +146,7 @@ calls or by ending a selection. #define DIB_BOLD ((sal_uInt16)0x0001) -typedef std::set<sal_uInt32> IntDateSet; +typedef std::set<sal_Int32> IntDateSet; class SVT_DLLPUBLIC Calendar : public Control @@ -188,8 +188,8 @@ private: long mnDayHeight; long mnWeekWidth; WinBits mnWinStyle; - sal_uInt16 mnFirstYear; - sal_uInt16 mnLastYear; + sal_Int16 mnFirstYear; + sal_Int16 mnLastYear; bool mbCalc:1, mbFormat:1, mbDrag:1, @@ -224,9 +224,9 @@ private: SVT_DLLPRIVATE sal_uInt16 ImplHitTest( const Point& rPos, Date& rDate ) const; SVT_DLLPRIVATE void ImplDrawSpin(vcl::RenderContext& rRenderContext); SVT_DLLPRIVATE void ImplDrawDate(vcl::RenderContext& rRenderContext, long nX, long nY, - sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear, + sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear, DayOfWeek eDayOfWeek, - bool bOther, sal_uLong nToday); + bool bOther, sal_Int32 nToday); SVT_DLLPRIVATE void ImplDraw(vcl::RenderContext& rRenderContext); SVT_DLLPRIVATE void ImplUpdateDate( const Date& rDate ); SVT_DLLPRIVATE void ImplUpdateSelection( IntDateSet* pOld ); diff --git a/include/tools/date.hxx b/include/tools/date.hxx index 1dfb13098028..bab1efd833f8 100644 --- a/include/tools/date.hxx +++ b/include/tools/date.hxx @@ -27,15 +27,32 @@ enum DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }; -// TODO FIXME: make it handle signed year? +/** Represents a date in the proleptic Gregorian calendar. + + Largest representable date is 32767-12-31 = 327671231 + + Smallest representable date is -32768-01-01 = -327680101 + + Due to possible conversions to css::util::Date, which has a short + Year member variable, these limits are fix. + + Year value 0 is unused. The year before year 1 CE is year 1 BCE, which is + the traditional proleptic Gregorian calendar. + + This is not how ISO 8601:2000 defines things (but ISO 8601:1998 Draft + Revision did), but it enables class Date to be used for writing XML files + as XML Schema Part 2 in D.3.2 No Year Zero says + "The year "0000" is an illegal year value.", see + https://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#noYearZero + and furthermore the note for 3.2.7 dateTime + https://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#dateTime + + */ class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Date { private: - sal_uInt32 nDate; - void setDateFromDMY( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) - { nDate = ( sal_uInt32( nDay % 100 ) ) + - ( ( sal_uInt32( nMonth % 100 ) ) * 100 ) + - ( ( sal_uInt32( nYear % 10000 ) ) * 10000); } + sal_Int32 mnDate; + void setDateFromDMY( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ); public: enum DateInitSystem @@ -43,37 +60,61 @@ public: SYSTEM }; - // TODO temporary until all uses are inspected and resolved enum DateInitEmpty { EMPTY }; - Date( DateInitEmpty) - { nDate = 0; } - Date( DateInitSystem ); - Date( sal_uInt32 _nDate ) { Date::nDate = _nDate; } - Date( const Date& rDate ) - { nDate = rDate.nDate; } - Date( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) + explicit Date( DateInitEmpty ) : mnDate(0) {} + explicit Date( DateInitSystem ); + explicit Date( sal_Int32 nDate ) : mnDate(nDate) {} + Date( const Date& rDate ) : mnDate(rDate.mnDate) {} + Date( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ) { setDateFromDMY(nDay, nMonth, nYear); } - Date( const css::util::Date& _rDate ) + Date( const css::util::Date& rUDate ) { - SAL_WARN_IF(_rDate.Year < 0, "tools.datetime", "Negative year in css::util::Date to ::Date conversion"); - setDateFromDMY(_rDate.Day, _rDate.Month, _rDate.Year); + setDateFromDMY(rUDate.Day, rUDate.Month, rUDate.Year); } Date( const css::util::DateTime& _rDateTime ); - void SetDate( sal_uInt32 nNewDate ) { nDate = nNewDate; } - sal_uInt32 GetDate() const { return nDate; } + void SetDate( sal_Int32 nNewDate ); + sal_Int32 GetDate() const { return mnDate; } + /** Type safe access for values that are guaranteed to be unsigned, like Date::SYSTEM. */ + sal_uInt32 GetDateUnsigned() const { return static_cast<sal_uInt32>(mnDate < 0 ? -mnDate : mnDate); } css::util::Date GetUNODate() const { return css::util::Date(GetDay(), GetMonth(), GetYear()); } void SetDay( sal_uInt16 nNewDay ); void SetMonth( sal_uInt16 nNewMonth ); - void SetYear( sal_uInt16 nNewYear ); - sal_uInt16 GetDay() const { return (sal_uInt16)(nDate % 100); } - sal_uInt16 GetMonth() const { return (sal_uInt16)((nDate / 100) % 100); } - sal_uInt16 GetYear() const { return (sal_uInt16)(nDate / 10000); } + void SetYear( sal_Int16 nNewYear ); + sal_uInt16 GetDay() const + { + return mnDate < 0 ? + static_cast<sal_uInt16>(-mnDate % 100) : + static_cast<sal_uInt16>( mnDate % 100); + } + sal_uInt16 GetMonth() const + { + return mnDate < 0 ? + static_cast<sal_uInt16>((-mnDate / 100) % 100) : + static_cast<sal_uInt16>(( mnDate / 100) % 100); + } + sal_Int16 GetYear() const { return static_cast<sal_Int16>(mnDate / 10000); } + /** Type safe access for values that are guaranteed to be unsigned, like Date::SYSTEM. */ + sal_uInt16 GetYearUnsigned() const { return static_cast<sal_uInt16>((mnDate < 0 ? -mnDate : mnDate) / 10000); } + sal_Int16 GetNextYear() const { sal_Int16 nY = GetYear(); return nY == -1 ? 1 : nY + 1; } + sal_Int16 GetPrevYear() const { sal_Int16 nY = GetYear(); return nY == 1 ? -1 : nY - 1; } + + /** Add years skipping year 0 and truncating at limits. If the original + date was on Feb-29 and the resulting date is not a leap year, the + result is adjusted to Feb-28. + */ + void AddYears( sal_Int16 nAddYears ); + + /** Add months skipping year 0 and truncating at limits. If the original + date was on Feb-29 or day 31 and the resulting date is not a leap year + or a month with less days, the result is adjusted to Feb-28 or day 30. + */ + void AddMonths( sal_Int32 nAddMonths ); /** Obtain the day of the week for the date. @@ -146,24 +187,26 @@ public: bool Normalize(); bool IsBetween( const Date& rFrom, const Date& rTo ) const - { return ((nDate >= rFrom.nDate) && - (nDate <= rTo.nDate)); } + { return ((mnDate >= rFrom.mnDate) && + (mnDate <= rTo.mnDate)); } bool operator ==( const Date& rDate ) const - { return (nDate == rDate.nDate); } + { return (mnDate == rDate.mnDate); } bool operator !=( const Date& rDate ) const - { return (nDate != rDate.nDate); } + { return (mnDate != rDate.mnDate); } bool operator >( const Date& rDate ) const - { return (nDate > rDate.nDate); } + { return (mnDate > rDate.mnDate); } bool operator <( const Date& rDate ) const - { return (nDate < rDate.nDate); } + { return (mnDate < rDate.mnDate); } bool operator >=( const Date& rDate ) const - { return (nDate >= rDate.nDate); } + { return (mnDate >= rDate.mnDate); } bool operator <=( const Date& rDate ) const - { return (nDate <= rDate.nDate); } + { return (mnDate <= rDate.mnDate); } Date& operator =( const Date& rDate ) - { nDate = rDate.nDate; return *this; } + { mnDate = rDate.mnDate; return *this; } + Date& operator =( const css::util::Date& rUDate ) + { setDateFromDMY( rUDate.Day, rUDate.Month, rUDate.Year); return *this; } Date& operator +=( long nDays ); Date& operator -=( long nDays ); Date& operator ++(); @@ -178,14 +221,14 @@ public: Internally sanitizes nMonth to values 1 <= nMonth <= 12, does not normalize values. */ - static sal_uInt16 GetDaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ); + static sal_uInt16 GetDaysInMonth( sal_uInt16 nMonth, sal_Int16 nYear ); /// Internally normalizes values. - static long DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ); + static long DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ); /// Semantically identical to IsValidDate() member method. - static bool IsValidDate( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ); + static bool IsValidDate( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ); /// Semantically identical to Normalize() member method. - static bool Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_uInt16 & rYear ); + static bool Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_Int16 & rYear ); private: /// An accelerated form of DateToDays on this date diff --git a/include/tools/datetime.hxx b/include/tools/datetime.hxx index 66826dff58e1..9e1f5f3fe6ea 100644 --- a/include/tools/datetime.hxx +++ b/include/tools/datetime.hxx @@ -34,14 +34,13 @@ public: SYSTEM }; - // TODO temporary until all uses are inspected and resolved enum DateTimeInitEmpty { EMPTY }; - DateTime( DateTimeInitEmpty ) : Date( Date::EMPTY ), Time( Time::EMPTY ) {} - DateTime( DateTimeInitSystem ) : Date( Date::SYSTEM ), Time( Time::SYSTEM ) {} + explicit DateTime( DateTimeInitEmpty ) : Date( Date::EMPTY ), Time( Time::EMPTY ) {} + explicit DateTime( DateTimeInitSystem ) : Date( Date::SYSTEM ), Time( Time::SYSTEM ) {} DateTime( const DateTime& rDateTime ) : Date( rDateTime ), Time( rDateTime ) {} DateTime( const Date& rDate ) : Date( rDate ), Time(0) {} @@ -103,6 +102,7 @@ public: { return (const Date&) rDateTime - rDate; } DateTime& operator =( const DateTime& rDateTime ); + DateTime& operator =( const css::util::DateTime& rUDateTime ); void GetWin32FileDateTime( sal_uInt32 & rLower, sal_uInt32 & rUpper ); static DateTime CreateFromWin32FileDateTime( sal_uInt32 rLower, sal_uInt32 rUpper ); diff --git a/include/vcl/field.hxx b/include/vcl/field.hxx index d07624e8a92c..d277a0a55b59 100644 --- a/include/vcl/field.hxx +++ b/include/vcl/field.hxx @@ -336,12 +336,12 @@ public: void SetEmptyDate(); bool IsEmptyDate() const; - void ResetLastDate() { maLastDate = Date( 0, 0, 0 ); } + void ResetLastDate() { maLastDate = Date( Date::EMPTY ); } static void ExpandCentury( Date& rDate ); static void ExpandCentury( Date& rDate, sal_uInt16 nTwoDigitYearStart ); - static Date GetInvalidDate() { return Date( 0, 0, 0 ); } + static Date GetInvalidDate() { return Date( Date::EMPTY ); } /** enables or disables the enforcement of valid values diff --git a/sc/inc/docoptio.hxx b/sc/inc/docoptio.hxx index a5f3bbfdc298..529135bb9a37 100644 --- a/sc/inc/docoptio.hxx +++ b/sc/inc/docoptio.hxx @@ -73,9 +73,9 @@ public: double GetIterEps() const { return fIterEps; } void SetIterEps( double fEps ) { fIterEps = fEps; } - void GetDate( sal_uInt16& rD, sal_uInt16& rM, sal_uInt16& rY ) const + void GetDate( sal_uInt16& rD, sal_uInt16& rM, sal_Int16& rY ) const { rD = nDay; rM = nMonth; rY = nYear;} - void SetDate (sal_uInt16 nD, sal_uInt16 nM, sal_uInt16 nY) + void SetDate (sal_uInt16 nD, sal_uInt16 nM, sal_Int16 nY) { nDay = nD; nMonth = nM; nYear = nY; } sal_uInt16 GetTabDistance() const { return nTabDistance;} void SetTabDistance( sal_uInt16 nTabDist ) {nTabDistance = nTabDist;} diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index 684498c8616c..cf7af863c188 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -1692,7 +1692,7 @@ bool ScCondDateFormatEntry::IsValid( const ScAddress& rPos ) const case condformat::LASTMONTH: if( rActDate.GetMonth() == 1 ) { - if( aCellDate.GetMonth() == 12 && rActDate.GetYear() == aCellDate.GetYear() + 1 ) + if( aCellDate.GetMonth() == 12 && rActDate.GetYear() == aCellDate.GetNextYear() ) return true; } else if( rActDate.GetYear() == aCellDate.GetYear() ) @@ -1721,7 +1721,7 @@ bool ScCondDateFormatEntry::IsValid( const ScAddress& rPos ) const } break; case condformat::LASTYEAR: - if( rActDate.GetYear() == aCellDate.GetYear() + 1 ) + if( rActDate.GetYear() == aCellDate.GetNextYear() ) return true; break; case condformat::THISYEAR: diff --git a/sc/source/core/data/poolhelp.cxx b/sc/source/core/data/poolhelp.cxx index 40bae0aa690f..b469155f6968 100644 --- a/sc/source/core/data/poolhelp.cxx +++ b/sc/source/core/data/poolhelp.cxx @@ -78,7 +78,8 @@ void ScPoolHelper::UseDocOptions() const { if (pFormTable) { - sal_uInt16 d,m,y; + sal_uInt16 d,m; + sal_Int16 y; aOpt.GetDate( d,m,y ); pFormTable->ChangeNullDate( d,m,y ); pFormTable->ChangeStandardPrec( (sal_uInt16)aOpt.GetStdPrecision() ); @@ -102,7 +103,8 @@ SvNumberFormatter* ScPoolHelper::CreateNumberFormatter() const p->SetColorLink( LINK(m_pSourceDoc, ScDocument, GetUserDefinedColor) ); p->SetEvalDateFormat(NF_EVALDATEFORMAT_INTL_FORMAT); - sal_uInt16 d,m,y; + sal_uInt16 d,m; + sal_Int16 y; aOpt.GetDate(d, m, y); p->ChangeNullDate(d, m, y); p->ChangeStandardPrec(aOpt.GetStdPrecision()); diff --git a/sc/source/core/tool/chgviset.cxx b/sc/source/core/tool/chgviset.cxx index 50a784f8b390..938c26591e62 100644 --- a/sc/source/core/tool/chgviset.cxx +++ b/sc/source/core/tool/chgviset.cxx @@ -146,7 +146,7 @@ void ScChangeViewSettings::AdjustDateMode( const ScDocument& rDoc ) aFirstDateTime.SetTime( 0 ); } aLastDateTime = Date( Date::SYSTEM ); - aLastDateTime.SetYear( aLastDateTime.GetYear() + 100 ); + aLastDateTime.AddYears( 100 ); } break; default: diff --git a/sc/source/core/tool/docoptio.cxx b/sc/source/core/tool/docoptio.cxx index c8ee49a93795..a84f8ae15a48 100644 --- a/sc/source/core/tool/docoptio.cxx +++ b/sc/source/core/tool/docoptio.cxx @@ -212,7 +212,8 @@ ScDocCfg::ScDocCfg() : Sequence<Any> aValues; const Any* pValues = nullptr; - sal_uInt16 nDateDay, nDateMonth, nDateYear; + sal_uInt16 nDateDay, nDateMonth; + sal_Int16 nDateYear; GetDate( nDateDay, nDateMonth, nDateYear ); aNames = GetCalcPropertyNames(); @@ -246,7 +247,7 @@ ScDocCfg::ScDocCfg() : if (pValues[nProp] >>= nIntVal) nDateMonth = (sal_uInt16) nIntVal; break; case SCCALCOPT_DATE_YEAR: - if (pValues[nProp] >>= nIntVal) nDateYear = (sal_uInt16) nIntVal; + if (pValues[nProp] >>= nIntVal) nDateYear = (sal_Int16) nIntVal; break; case SCCALCOPT_DECIMALS: if (pValues[nProp] >>= nIntVal) SetStdPrecision( (sal_uInt16) nIntVal ); @@ -310,7 +311,8 @@ IMPL_LINK_NOARG_TYPED(ScDocCfg, CalcCommitHdl, ScLinkConfigItem&, void) Sequence<Any> aValues(aNames.getLength()); Any* pValues = aValues.getArray(); - sal_uInt16 nDateDay, nDateMonth, nDateYear; + sal_uInt16 nDateDay, nDateMonth; + sal_Int16 nDateYear; GetDate( nDateDay, nDateMonth, nDateYear ); for(int nProp = 0; nProp < aNames.getLength(); nProp++) diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index fe4331431c02..cc735270d4fd 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -807,7 +807,8 @@ void ScInterpreter::ScGetDateDif() } // split dates in day, month, year for use with formats other than "d" - sal_uInt16 d1, m1, y1, d2, m2, y2; + sal_uInt16 d1, m1, d2, m2; + sal_Int16 y1, y2; Date aDate1( *( pFormatter->GetNullDate())); aDate1 += (long) ::rtl::math::approxFloor( nDate1 ); y1 = aDate1.GetYear(); @@ -819,6 +820,12 @@ void ScInterpreter::ScGetDateDif() m2 = aDate2.GetMonth(); d2 = aDate2.GetDay(); + // Close the year 0 gap to calculate year difference. + if (y1 < 0 && y2 > 0) + ++y1; + else if (y1 > 0 && y2 < 0) + ++y2; + if ( aInterval.equalsIgnoreAsciiCase( "m" ) ) { // Return number of months. @@ -871,7 +878,7 @@ void ScInterpreter::ScGetDateDif() { if (m2 == 1) { - aDate1.SetYear( y2 - 1 ); + aDate1.SetYear( y2 == 1 ? -1 : y2 - 1 ); aDate1.SetMonth( 12 ); } else diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 32e2e11364fa..93f9aef01da0 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -1442,7 +1442,7 @@ void ScCheckListMenuWindow::addDateMember(const OUString& rsName, double nVal, b Date aDate = *(pFormatter->GetNullDate()); aDate += static_cast<long>(rtl::math::approxFloor(nVal)); - sal_uInt16 nYear = aDate.GetYear(); + sal_Int16 nYear = aDate.GetYear(); sal_uInt16 nMonth = aDate.GetMonth(); sal_uInt16 nDay = aDate.GetDay(); diff --git a/sc/source/ui/optdlg/tpcalc.cxx b/sc/source/ui/optdlg/tpcalc.cxx index 9cf30a177009..a9834f4e69aa 100644 --- a/sc/source/ui/optdlg/tpcalc.cxx +++ b/sc/source/ui/optdlg/tpcalc.cxx @@ -112,7 +112,8 @@ VclPtr<SfxTabPage> ScTpCalcOptions::Create( vcl::Window* pParent, const SfxItemS void ScTpCalcOptions::Reset( const SfxItemSet* /* rCoreAttrs */ ) { - sal_uInt16 d,m,y; + sal_uInt16 d,m; + sal_Int16 y; *pLocalOptions = *pOldOptions; diff --git a/sc/source/ui/unoobj/optuno.cxx b/sc/source/ui/unoobj/optuno.cxx index 925af4e63c26..ff479fe92677 100644 --- a/sc/source/ui/unoobj/optuno.cxx +++ b/sc/source/ui/unoobj/optuno.cxx @@ -162,7 +162,8 @@ uno::Any ScDocOptionsHelper::getPropertyValue( break; case PROP_UNO_NULLDATE: { - sal_uInt16 nD, nM, nY; + sal_uInt16 nD, nM; + sal_Int16 nY; rOptions.GetDate( nD, nM, nY ); util::Date aDate( nD, nM, nY ); aRet <<= aDate; diff --git a/sfx2/source/doc/objcont.cxx b/sfx2/source/doc/objcont.cxx index ea1ea377a365..bac439a9247d 100644 --- a/sfx2/source/doc/objcont.cxx +++ b/sfx2/source/doc/objcont.cxx @@ -245,7 +245,7 @@ void SfxObjectShell::UpdateTime_Impl( if (aNow.GetDate()>=pImpl->nTime.GetDate()) { // Get count of days last editing. - nDays = aNow.GetSecFromDateTime(pImpl->nTime.GetDate())/86400 ; + nDays = aNow.GetSecFromDateTime(Date(pImpl->nTime.GetDate()))/86400 ; if (nDays==0) { diff --git a/solenv/gdb/libreoffice/tl.py b/solenv/gdb/libreoffice/tl.py index 87e4924e0d99..2e096fc8d26c 100644 --- a/solenv/gdb/libreoffice/tl.py +++ b/solenv/gdb/libreoffice/tl.py @@ -112,10 +112,12 @@ class DateImpl(DateTimeImpl): @staticmethod def parse(val): - date = val['nDate'] - d = date % 100 - m = (date / 100) % 100 + date = val['mnDate'] y = date / 10000 + if date < 0: + date = -date + m = (date / 100) % 100 + d = date % 100 return DateImpl(y, m, d) class DatePrinter(object): diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx index 6154e2a9bb78..7fc7f8c079fd 100644 --- a/svl/source/numbers/zforfind.cxx +++ b/svl/source/numbers/zforfind.cxx @@ -3406,7 +3406,7 @@ void ImpSvNumberInputScan::InvalidateDateAcceptancePatterns() void ImpSvNumberInputScan::ChangeNullDate( const sal_uInt16 Day, const sal_uInt16 Month, - const sal_uInt16 Year ) + const sal_Int16 Year ) { if ( pNullDate ) { diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx index 7cabce77cf2a..5f62e281f10c 100644 --- a/svl/source/numbers/zforfind.hxx +++ b/svl/source/numbers/zforfind.hxx @@ -40,7 +40,7 @@ public: /// set reference date for offset calculation void ChangeNullDate( const sal_uInt16 nDay, const sal_uInt16 nMonth, - const sal_uInt16 nYear ); + const sal_Int16 nYear ); /// convert input string to number bool IsNumberFormat( const OUString& rString, /// input string diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx index bd67e25e9c09..5ca78ed0b370 100644 --- a/svl/source/numbers/zforlist.cxx +++ b/svl/source/numbers/zforlist.cxx @@ -398,7 +398,7 @@ Color* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex) void SvNumberFormatter::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, - sal_uInt16 nYear) + sal_Int16 nYear) { pFormatScanner->ChangeNullDate(nDay, nMonth, nYear); pStringScanner->ChangeNullDate(nDay, nMonth, nYear); diff --git a/svl/source/numbers/zforscan.cxx b/svl/source/numbers/zforscan.cxx index b208364d5e95..8025ae6fd1e0 100644 --- a/svl/source/numbers/zforscan.cxx +++ b/svl/source/numbers/zforscan.cxx @@ -446,7 +446,7 @@ void ImpSvNumberformatScan::SetDependentKeywords() InitCompatCur(); } -void ImpSvNumberformatScan::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear) +void ImpSvNumberformatScan::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear) { if ( pNullDate ) *pNullDate = Date(nDay, nMonth, nYear); diff --git a/svl/source/numbers/zforscan.hxx b/svl/source/numbers/zforscan.hxx index 82535fd1e84a..bf92049bae1f 100644 --- a/svl/source/numbers/zforscan.hxx +++ b/svl/source/numbers/zforscan.hxx @@ -44,7 +44,7 @@ public: ~ImpSvNumberformatScan(); void ChangeIntl(); // Replaces Keywords - void ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear); // Replaces reference date + void ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear); // Replaces reference date void ChangeStandardPrec(sal_uInt16 nPrec); // Replaces standard precision sal_Int32 ScanFormat( OUString& rString ); // Call scan analysis diff --git a/svtools/source/control/calendar.cxx b/svtools/source/control/calendar.cxx index 575463bd3912..b89b9061fde0 100644 --- a/svtools/source/control/calendar.cxx +++ b/svtools/source/control/calendar.cxx @@ -453,8 +453,8 @@ void Calendar::ImplFormat() } // get DateInfo - sal_uInt16 nNewFirstYear = maFirstDate.GetYear(); - sal_uInt16 nNewLastYear = GetLastDate().GetYear(); + sal_Int16 nNewFirstYear = maFirstDate.GetYear(); + sal_Int16 nNewLastYear = GetLastDate().GetYear(); if ( mnFirstYear ) { if ( nNewFirstYear < mnFirstYear ) @@ -670,9 +670,9 @@ void Calendar::ImplDrawSpin(vcl::RenderContext& rRenderContext ) void Calendar::ImplDrawDate(vcl::RenderContext& rRenderContext, long nX, long nY, - sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear, + sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear, DayOfWeek eDayOfWeek, - bool bOther, sal_uLong nToday ) + bool bOther, sal_Int32 nToday ) { Color* pTextColor = nullptr; const OUString& rDay = maDayTexts[nDay - 1]; @@ -769,10 +769,10 @@ void Calendar::ImplDraw(vcl::RenderContext& rRenderContext) long nDeltaY; long nDayX; long nDayY; - sal_uLong nToday = Date(Date::SYSTEM).GetDate(); + sal_Int32 nToday = Date(Date::SYSTEM).GetDate(); sal_uInt16 nDay; sal_uInt16 nMonth; - sal_uInt16 nYear; + sal_Int16 nYear; Date aDate = GetFirstMonth(); DayOfWeek eStartDay = ImplGetWeekStart(); @@ -1559,7 +1559,7 @@ void Calendar::RequestHelp( const HelpEvent& rHEvt ) if ( (nMonth == 12) && (nWeek == 1) ) { aStr += ", "; - aStr += OUString::number(aDate.GetYear()+1); + aStr += OUString::number(aDate.GetNextYear()); } else if ( (nMonth == 1) && (nWeek > 50) ) { @@ -1761,7 +1761,7 @@ Date Calendar::GetFirstMonth() const if ( maFirstDate.GetDay() > 1 ) { if ( maFirstDate.GetMonth() == 12 ) - return Date( 1, 1, maFirstDate.GetYear()+1 ); + return Date( 1, 1, maFirstDate.GetNextYear() ); else return Date( 1, maFirstDate.GetMonth()+1, maFirstDate.GetYear() ); } @@ -2155,7 +2155,7 @@ CalendarField::CalendarField(vcl::Window* pParent, WinBits nWinStyle) , mnCalendarStyle(0) , mpTodayBtn(nullptr) , mpNoneBtn(nullptr) - , maDefaultDate( 0, 0, 0 ) + , maDefaultDate( Date::EMPTY ) , mbToday(false) , mbNone(false) { diff --git a/svx/source/dialog/ctredlin.cxx b/svx/source/dialog/ctredlin.cxx index 677cc081497a..40de9bac9d45 100644 --- a/svx/source/dialog/ctredlin.cxx +++ b/svx/source/dialog/ctredlin.cxx @@ -170,8 +170,7 @@ void SvxRedlinTable::SetCalcView() void SvxRedlinTable::UpdateFilterTest() { Date aDateMax( Date::SYSTEM ); - sal_uInt16 nYEAR=aDateMax.GetYear()+100; - aDateMax.SetYear(nYEAR); + aDateMax.AddYears(100); Date aDateMin(1,1,1989); tools::Time aTMin(0); tools::Time aTMax(23,59,59); diff --git a/sw/inc/docufld.hxx b/sw/inc/docufld.hxx index 4a0b91bd5224..f14b3b7b00b6 100644 --- a/sw/inc/docufld.hxx +++ b/sw/inc/docufld.hxx @@ -464,7 +464,7 @@ public: virtual SwField* Copy() const override; const DateTime& GetDateTime() const { return aDateTime; } - inline const Date GetDate() const { return aDateTime.GetDate(); } + inline const Date GetDate() const { return Date(aDateTime.GetDate()); } inline const tools::Time GetTime() const { return aDateTime.GetTime(); } /// Author diff --git a/sw/source/core/fields/flddat.cxx b/sw/source/core/fields/flddat.cxx index 358a20740e0c..e6e11451df72 100644 --- a/sw/source/core/fields/flddat.cxx +++ b/sw/source/core/fields/flddat.cxx @@ -152,7 +152,7 @@ tools::Time SwDateTimeField::GetTime() const { double fDummy; double fFract = modf(GetValue(), &fDummy); - DateTime aDT((long)fDummy, 0); + DateTime aDT(Date(static_cast<sal_Int32>(fDummy)), 0); aDT += fFract; return static_cast<tools::Time>(aDT); } diff --git a/sw/source/core/unocore/unocrsrhelper.cxx b/sw/source/core/unocore/unocrsrhelper.cxx index 4e935d6fe8ea..462b19df73b6 100644 --- a/sw/source/core/unocore/unocrsrhelper.cxx +++ b/sw/source/core/unocore/unocrsrhelper.cxx @@ -1192,8 +1192,7 @@ void makeRedline( SwPaM& rPaM, aDateTimeValue = aPropMap.getUnpackedValueOrDefault("RedlineDateTime", aDateTimeValue); if( aDateTimeValue >>= aStamp ) { - aRedlineData.SetTimeStamp( - DateTime( Date( aStamp.Day, aStamp.Month, aStamp.Year ), tools::Time( aStamp.Hours, aStamp.Minutes, aStamp.Seconds ) ) ); + aRedlineData.SetTimeStamp( DateTime( aStamp)); } SwRedlineExtraData_FormattingChanges* pRedlineExtraData = nullptr; diff --git a/sw/source/core/unocore/unofield.cxx b/sw/source/core/unocore/unofield.cxx index e2efdad70749..36bf54b9d291 100644 --- a/sw/source/core/unocore/unofield.cxx +++ b/sw/source/core/unocore/unofield.cxx @@ -1357,12 +1357,7 @@ throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) DateTime aDateTime( DateTime::EMPTY ); if (m_pImpl->m_pProps->pDateTime) { - aDateTime.SetYear(m_pImpl->m_pProps->pDateTime->Year); - aDateTime.SetMonth(m_pImpl->m_pProps->pDateTime->Month); - aDateTime.SetDay(m_pImpl->m_pProps->pDateTime->Day); - aDateTime.SetHour(m_pImpl->m_pProps->pDateTime->Hours); - aDateTime.SetMin(m_pImpl->m_pProps->pDateTime->Minutes); - aDateTime.SetSec(m_pImpl->m_pProps->pDateTime->Seconds); + aDateTime = *(m_pImpl->m_pProps->pDateTime); } SwPostItField* pPostItField = new SwPostItField( static_cast<SwPostItFieldType*>(pFieldType), diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 4e55c49055fe..f4d2c8168410 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -4584,9 +4584,7 @@ void DocxAttributeOutput::WritePostponedFormControl(const SdrObject* pObject) { css::util::Date aUNODate; aGrabBag[i].Value >>= aUNODate; - aOriginalDate.SetDay(aUNODate.Day); - aOriginalDate.SetMonth(aUNODate.Month); - aOriginalDate.SetYear(aUNODate.Year); + aOriginalDate = aUNODate; } else if (aGrabBag[i].Name == "CharFormat") aGrabBag[i].Value >>= aCharFormat; diff --git a/tools/CppunitTest_tools_test.mk b/tools/CppunitTest_tools_test.mk index e90b52457244..aced4bf6698a 100644 --- a/tools/CppunitTest_tools_test.mk +++ b/tools/CppunitTest_tools_test.mk @@ -15,6 +15,7 @@ $(eval $(call gb_CppunitTest_use_external,tools_test,boost_headers)) $(eval $(call gb_CppunitTest_add_exception_objects,tools_test, \ tools/qa/cppunit/test_bigint \ + tools/qa/cppunit/test_date \ tools/qa/cppunit/test_fract \ tools/qa/cppunit/test_inetmime \ tools/qa/cppunit/test_pathutils \ diff --git a/tools/qa/cppunit/test_date.cxx b/tools/qa/cppunit/test_date.cxx new file mode 100644 index 000000000000..0ee30089b7b5 --- /dev/null +++ b/tools/qa/cppunit/test_date.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +#include <tools/date.hxx> + +namespace tools +{ + +class DateTest : public CppUnit::TestFixture +{ +public: + void testDate(); + + CPPUNIT_TEST_SUITE(DateTest); + CPPUNIT_TEST(testDate); + CPPUNIT_TEST_SUITE_END(); +}; + +void DateTest::testDate() +{ + const Date aCE(1,1,1); // first day CE + const Date aBCE(31,12,-1); // last day BCE + const Date aMin(1,1,-32768); // minimum date + const Date aMax(31,12,32767); // maximum date + Date aDate(Date::EMPTY); + const long kMinDays = -11968265; + const long kMaxDays = 11967900; + + // Last day BCE to first day CE is 1 day difference. + CPPUNIT_ASSERT_EQUAL( static_cast<long>(1), aCE - aBCE); + CPPUNIT_ASSERT_EQUAL( static_cast<long>(-1), aBCE - aCE); + aDate = aBCE; + CPPUNIT_ASSERT_EQUAL( aCE.GetDate(), (aDate += 1).GetDate()); + aDate = aCE; + CPPUNIT_ASSERT_EQUAL( aBCE.GetDate(), (aDate -= 1).GetDate()); + + // The entire BCE and CE ranges cover that many days. Day 0 is -0001-12-31 + CPPUNIT_ASSERT_EQUAL( kMaxDays, aMax - aBCE); + CPPUNIT_ASSERT_EQUAL( kMinDays, aMin - aBCE); + + // Truncate at limits, not under-/overflow or wrap. + aDate = aMin; + CPPUNIT_ASSERT_EQUAL( aMin.GetDate(), (aDate -= 1).GetDate()); + aDate = aMax; + CPPUNIT_ASSERT_EQUAL( aMax.GetDate(), (aDate += 1).GetDate()); + aDate = aBCE; + CPPUNIT_ASSERT_EQUAL( aMin.GetDate(), (aDate += (kMinDays-10)).GetDate()); + aDate = aBCE; + CPPUNIT_ASSERT_EQUAL( aMax.GetDate(), (aDate += (kMaxDays+10)).GetDate()); + + // Year -1 is a leap year. + aDate = Date(28,2,-1); + CPPUNIT_ASSERT_EQUAL( Date(29,2,-1).GetDate(), (aDate += 1).GetDate()); + aDate = Date(1,3,-1); + CPPUNIT_ASSERT_EQUAL( Date(29,2,-1).GetDate(), (aDate -= 1).GetDate()); + // Year -5 is a leap year. + aDate = Date(28,2,-5); + CPPUNIT_ASSERT_EQUAL( Date(29,2,-5).GetDate(), (aDate += 1).GetDate()); + aDate = Date(1,3,-5); + CPPUNIT_ASSERT_EQUAL( Date(29,2,-5).GetDate(), (aDate -= 1).GetDate()); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(DateTest); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/tools/source/datetime/datetime.cxx b/tools/source/datetime/datetime.cxx index cc0fc13a9ae6..d24f6f818184 100644 --- a/tools/source/datetime/datetime.cxx +++ b/tools/source/datetime/datetime.cxx @@ -25,6 +25,13 @@ DateTime::DateTime( const css::util::DateTime& rDateTime ) { } +DateTime& DateTime::operator =( const css::util::DateTime& rUDateTime ) +{ + Date::operator=( Date( rUDateTime.Day, rUDateTime.Month, rUDateTime.Year)); + Time::operator=( Time( rUDateTime)); + return *this; +} + bool DateTime::IsBetween( const DateTime& rFrom, const DateTime& rTo ) const { if ( (*this >= rFrom) && (*this <= rTo) ) diff --git a/tools/source/datetime/tdate.cxx b/tools/source/datetime/tdate.cxx index 78b1ec63ac70..e4556be8c1c0 100644 --- a/tools/source/datetime/tdate.cxx +++ b/tools/source/datetime/tdate.cxx @@ -29,36 +29,64 @@ static const sal_uInt16 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -// The number of days we internally handle. +// Once upon a time the number of days we internally handled was limited to +// MAX_DAYS 3636532. That changed with a full 16-bit year. // Assuming the first valid positive date in a proleptic Gregorian calendar is -// 0001-01-01, this results in an end date of 9957-06-26. +// 0001-01-01, this resulted in an end date of 9957-06-26. // Hence we documented that years up to and including 9956 are handled. /* XXX: it is unclear history why this value was chosen, the representable * 9999-12-31 would be 3652060 days from 0001-01-01. Even 9998-12-31 to - * distinguish from a maximum possible date would be 3651695. Better keep the - * value in case something somewhere relies on it or there is another reason - * beyond.. - * At least connectivity/source/commontools/dbconversion.cxx has the same - * value to calculate with css::util::Date */ -#define MAX_DAYS 3636532 + * distinguish from a maximum possible date would be 3651695. + * There is connectivity/source/commontools/dbconversion.cxx that still has the + * same value to calculate with css::util::Date */ +/* XXX can that dbconversion cope with years > 9999 or negative years at all? + * Database fields may be limited to positive 4 digits. */ + +static const long MIN_DAYS = -11968265; // -32768-01-01 +static const long MAX_DAYS = 11967900; // 32767-12-31 namespace { -inline long ImpYearToDays( sal_uInt16 nYear ) +const sal_Int16 kYearMax = SAL_MAX_INT16; +const sal_Int16 kYearMin = SAL_MIN_INT16; + +// Days until start of year from zero, so month and day of month can be added. +// year 1 => 0 days, year 2 => 365 days, ... +// year -1 => -366 days, year -2 => -731 days, ... +inline long ImpYearToDays( sal_Int16 nYear ) { - const long nYr(static_cast<long>(nYear) - 1); - return nYr*365 + nYr/4 - nYr/100 + nYr/400; + assert( nYear != 0 ); + long nOffset; + long nYr; + if (nYear < 0) + { + nOffset = -366; + nYr = nYear + 1; + } + else + { + nOffset = 0; + nYr = nYear - 1; + } + return nOffset + nYr*365 + nYr/4 - nYr/100 + nYr/400; } -inline bool ImpIsLeapYear( sal_uInt16 nYear ) +inline bool ImpIsLeapYear( sal_Int16 nYear ) { + // Leap years BCE are -1, -5, -9, ... + // See + // https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar#Usage + // https://en.wikipedia.org/wiki/0_(year)#History_of_astronomical_usage + assert( nYear != 0 ); + if (nYear < 0) + nYear = -nYear - 1; return ( ( ((nYear % 4) == 0) && ((nYear % 100) != 0) ) || ( (nYear % 400) == 0 ) ); } // All callers must have sanitized or normalized month and year values! -inline sal_uInt16 ImplDaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) +inline sal_uInt16 ImplDaysInMonth( sal_uInt16 nMonth, sal_Int16 nYear ) { if ( nMonth != 2 ) return aDaysInMonth[nMonth-1]; @@ -73,8 +101,29 @@ inline sal_uInt16 ImplDaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) } +void Date::setDateFromDMY( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ) +{ + SAL_WARN_IF( nYear == 0, "tools","Date::setDateFromDMY - sure about 0 year? It's not in the calendar."); + if (nYear < 0) + mnDate = + (static_cast<sal_Int32>( nYear ) * 10000) - + (static_cast<sal_Int32>( nMonth % 100 ) * 100) - + (static_cast<sal_Int32>( nDay % 100 )); + else + mnDate = + (static_cast<sal_Int32>( nYear ) * 10000) + + (static_cast<sal_Int32>( nMonth % 100 ) * 100) + + (static_cast<sal_Int32>( nDay % 100 )); +} + +void Date::SetDate( sal_Int32 nNewDate ) +{ + assert( ((nNewDate / 10000) != 0) && "you don't want to set a 0 year, do you?" ); + mnDate = nNewDate; +} + // static -sal_uInt16 Date::GetDaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) +sal_uInt16 Date::GetDaysInMonth( sal_uInt16 nMonth, sal_Int16 nYear ) { SAL_WARN_IF( nMonth < 1 || 12 < nMonth, "tools", "Date::GetDaysInMonth - nMonth out of bounds " << nMonth); if (nMonth < 1) @@ -87,7 +136,7 @@ sal_uInt16 Date::GetDaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) long Date::GetAsNormalizedDays() const { // This is a very common datum we often calculate from. - if (nDate == 18991230) // 1899-12-30 + if (mnDate == 18991230) // 1899-12-30 { assert(DateToDays( GetDay(), GetMonth(), GetYear() ) == 693594); return 693594; @@ -95,7 +144,7 @@ long Date::GetAsNormalizedDays() const return DateToDays( GetDay(), GetMonth(), GetYear() ); } -long Date::DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) +long Date::DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ) { Normalize( nDay, nMonth, nYear); @@ -108,25 +157,28 @@ long Date::DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) static Date lcl_DaysToDate( long nDays ) { + if ( nDays <= MIN_DAYS ) + return Date( 1, 1, kYearMin ); if ( nDays >= MAX_DAYS ) - return Date( 31, 12, 9999 ); - - if ( nDays <= 0 ) - return Date( 1, 0, 0 ); + return Date( 31, 12, kYearMax ); - long nTempDays; - long i = 0; - bool bCalc; + // Day 0 is -0001-12-31, day 1 is 0001-01-01 + const sal_Int16 nSign = (nDays <= 0 ? -1 : 1); + long nTempDays; + long i = 0; + bool bCalc; - sal_uInt16 nYear; + sal_Int16 nYear; do { - nYear = (sal_uInt16)((nDays / 365) - i); + nYear = static_cast<sal_Int16>((nDays / 365) - (i * nSign)); + if (nYear == 0) + nYear = nSign; nTempDays = nDays - ImpYearToDays(nYear); bCalc = false; if ( nTempDays < 1 ) { - i++; + i += nSign; bCalc = true; } else @@ -135,7 +187,7 @@ static Date lcl_DaysToDate( long nDays ) { if ( (nTempDays != 366) || !ImpIsLeapYear( nYear ) ) { - i--; + i -= nSign; bCalc = true; } } @@ -147,7 +199,7 @@ static Date lcl_DaysToDate( long nDays ) while ( nTempDays > static_cast<long>(ImplDaysInMonth( nMonth, nYear )) ) { nTempDays -= ImplDaysInMonth( nMonth, nYear ); - nMonth++; + ++nMonth; } return Date( static_cast<sal_uInt16>(nTempDays), nMonth, nYear ); @@ -195,11 +247,73 @@ void Date::SetMonth( sal_uInt16 nNewMonth ) setDateFromDMY( GetDay(), nNewMonth, GetYear() ); } -void Date::SetYear( sal_uInt16 nNewYear ) +void Date::SetYear( sal_Int16 nNewYear ) { + assert( nNewYear != 0 ); setDateFromDMY( GetDay(), GetMonth(), nNewYear ); } +void Date::AddYears( sal_Int16 nAddYears ) +{ + sal_Int16 nYear = GetYear(); + if (nYear < 0) + { + if (nAddYears < 0) + { + if (nYear < kYearMin - nAddYears) + nYear = kYearMin; + else + nYear += nAddYears; + } + else + { + nYear += nAddYears; + if (nYear == 0) + nYear = 1; + } + } + else + { + if (nAddYears > 0) + { + if (kYearMax - nAddYears < nYear) + nYear = kYearMax; + else + nYear += nAddYears; + } + else + { + nYear += nAddYears; + if (nYear == 0) + nYear = -1; + } + } + + SetYear( nYear ); + if (GetMonth() == 2 && GetDay() == 29 && !ImpIsLeapYear( nYear)) + SetDay(28); +} + +void Date::AddMonths( sal_Int32 nAddMonths ) +{ + long nMonths = GetMonth() + nAddMonths; + long nNewMonth = nMonths % 12; + long nYear = GetYear() + nMonths / 12; + if( nMonths <= 0 || nNewMonth == 0 ) + --nYear; + if( nNewMonth <= 0 ) + nNewMonth += 12; + if (nYear == 0) + nYear = (nAddMonths < 0 ? -1 : 1); + else if (nYear < kYearMin) + nYear = kYearMin; + else if (nYear > kYearMax) + nYear = kYearMax; + SetMonth( static_cast<sal_uInt16>(nNewMonth) ); + SetYear( static_cast<sal_Int16>(nYear) ); + Normalize(); +} + DayOfWeek Date::GetDayOfWeek() const { return static_cast<DayOfWeek>((GetAsNormalizedDays()-1) % 7); @@ -209,7 +323,7 @@ sal_uInt16 Date::GetDayOfYear() const { sal_uInt16 nDay = GetDay(); sal_uInt16 nMonth = GetMonth(); - sal_uInt16 nYear = GetYear(); + sal_Int16 nYear = GetYear(); Normalize( nDay, nMonth, nYear); for( sal_uInt16 i = 1; i < nMonth; i++ ) @@ -245,7 +359,7 @@ sal_uInt16 Date::GetWeekOfYear( DayOfWeek eStartDay, else if ( nWeek == 53 ) { short nDaysInYear = (short)GetDaysInYear(); - short nDaysNextYear = (short)Date( 1, 1, GetYear()+1 ).GetDayOfWeek(); + short nDaysNextYear = (short)Date( 1, 1, GetNextYear() ).GetDayOfWeek(); nDaysNextYear = (nDaysNextYear+(7-(short)eStartDay)) % 7; if ( nDayOfYear > (nDaysInYear-nDaysNextYear-1) ) nWeek = 1; @@ -257,7 +371,7 @@ sal_uInt16 Date::GetWeekOfYear( DayOfWeek eStartDay, // First week of a year is equal to the last week of the previous year if ( nWeek == 0 ) { - Date aLastDatePrevYear( 31, 12, GetYear()-1 ); + Date aLastDatePrevYear( 31, 12, GetPrevYear() ); nWeek = aLastDatePrevYear.GetWeekOfYear( eStartDay, nMinimumNumberOfDaysInWeek ); } } @@ -273,7 +387,7 @@ sal_uInt16 Date::GetWeekOfYear( DayOfWeek eStartDay, else if ( n1WDay == nMinimumNumberOfDaysInWeek + 1 ) { // Year after leapyear - if ( Date( 1, 1, GetYear()-1 ).IsLeapYear() ) + if ( Date( 1, 1, GetPrevYear() ).IsLeapYear() ) nWeek = 53; else nWeek = 52; @@ -307,7 +421,7 @@ sal_uInt16 Date::GetDaysInMonth() const { sal_uInt16 nDay = GetDay(); sal_uInt16 nMonth = GetMonth(); - sal_uInt16 nYear = GetYear(); + sal_Int16 nYear = GetYear(); Normalize( nDay, nMonth, nYear); return ImplDaysInMonth( nMonth, nYear ); @@ -315,7 +429,7 @@ sal_uInt16 Date::GetDaysInMonth() const bool Date::IsLeapYear() const { - sal_uInt16 nYear = GetYear(); + sal_Int16 nYear = GetYear(); return ImpIsLeapYear( nYear ); } @@ -323,7 +437,7 @@ bool Date::IsValidAndGregorian() const { sal_uInt16 nDay = GetDay(); sal_uInt16 nMonth = GetMonth(); - sal_uInt16 nYear = GetYear(); + sal_Int16 nYear = GetYear(); if ( !nMonth || (nMonth > 12) ) return false; @@ -348,7 +462,7 @@ bool Date::IsValidDate() const } //static -bool Date::IsValidDate( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) +bool Date::IsValidDate( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ) { if ( !nMonth || (nMonth > 12) ) return false; @@ -361,7 +475,7 @@ bool Date::Normalize() { sal_uInt16 nDay = GetDay(); sal_uInt16 nMonth = GetMonth(); - sal_uInt16 nYear = GetYear(); + sal_Int16 nYear = GetYear(); if (!Normalize( nDay, nMonth, nYear)) return false; @@ -372,7 +486,7 @@ bool Date::Normalize() } //static -bool Date::Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_uInt16 & rYear ) +bool Date::Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_Int16 & rYear ) { if (IsValidDate( rDay, rMonth, rYear)) return false; @@ -381,42 +495,59 @@ bool Date::Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_uInt16 & rYear { rYear += rMonth / 12; rMonth = rMonth % 12; + if (rYear == 0) + rYear = 1; } - if (!rMonth) + if (rMonth == 0) { - if (!rYear) + --rYear; + if (rYear == 0) + rYear = -1; + rMonth = 12; + } + + if (rYear < 0) + { + sal_uInt16 nDays; + while (rDay > (nDays = ImplDaysInMonth( rMonth, rYear))) { - rYear = 0; - rMonth = 1; - if (rDay > 31) - rDay -= 31; + rDay -= nDays; + if (rMonth > 1) + --rMonth; else - rDay = 1; - } - else - { - --rYear; - rMonth = 12; + { + if (rYear == kYearMin) + { + rDay = 1; + rMonth = 1; + return true; + } + --rYear; + rMonth = 12; + } } } - sal_uInt16 nDays; - while (rDay > (nDays = ImplDaysInMonth( rMonth, rYear))) + else { - rDay -= nDays; - if (rMonth < 12) - ++rMonth; - else + sal_uInt16 nDays; + while (rDay > (nDays = ImplDaysInMonth( rMonth, rYear))) { - ++rYear; - rMonth = 1; + rDay -= nDays; + if (rMonth < 12) + ++rMonth; + else + { + if (rYear == kYearMax) + { + rDay = 31; + rMonth = 12; + return true; + } + ++rYear; + rMonth = 1; + } } } - if (rYear > 9999) - { - rDay = 31; - rMonth = 12; - rYear = 9999; - } return true; } diff --git a/unotools/source/i18n/localedatawrapper.cxx b/unotools/source/i18n/localedatawrapper.cxx index 7204f66392bb..6dbd1388ba52 100644 --- a/unotools/source/i18n/localedatawrapper.cxx +++ b/unotools/source/i18n/localedatawrapper.cxx @@ -1134,6 +1134,16 @@ static sal_Unicode* ImplAddUNum( sal_Unicode* pBuf, sal_uInt64 nNumber, int nMin return pBuf; } +static sal_Unicode* ImplAddNum( sal_Unicode* pBuf, sal_Int64 nNumber, int nMinLen ) +{ + if (nNumber < 0) + { + *pBuf++ = '-'; + nNumber = -nNumber; + } + return ImplAddUNum( pBuf, nNumber, nMinLen); +} + static sal_Unicode* ImplAdd2UNum( sal_Unicode* pBuf, sal_uInt16 nNumber, bool bLeading ) { DBG_ASSERT( nNumber < 100, "ImplAdd2UNum() - Number >= 100" ); @@ -1324,7 +1334,7 @@ OUString LocaleDataWrapper::getDate( const Date& rDate ) const sal_Unicode* pBuf = aBuf; sal_uInt16 nDay = rDate.GetDay(); sal_uInt16 nMonth = rDate.GetMonth(); - sal_uInt16 nYear = rDate.GetYear(); + sal_Int16 nYear = rDate.GetYear(); sal_uInt16 nYearLen; if ( true /* IsDateCentury() */ ) @@ -1342,17 +1352,17 @@ OUString LocaleDataWrapper::getDate( const Date& rDate ) const pBuf = ImplAddString( pBuf, getDateSep() ); pBuf = ImplAdd2UNum( pBuf, nMonth, true /* IsDateMonthLeadingZero() */ ); pBuf = ImplAddString( pBuf, getDateSep() ); - pBuf = ImplAddUNum( pBuf, nYear, nYearLen ); + pBuf = ImplAddNum( pBuf, nYear, nYearLen ); break; case MDY : pBuf = ImplAdd2UNum( pBuf, nMonth, true /* IsDateMonthLeadingZero() */ ); pBuf = ImplAddString( pBuf, getDateSep() ); pBuf = ImplAdd2UNum( pBuf, nDay, true /* IsDateDayLeadingZero() */ ); pBuf = ImplAddString( pBuf, getDateSep() ); - pBuf = ImplAddUNum( pBuf, nYear, nYearLen ); + pBuf = ImplAddNum( pBuf, nYear, nYearLen ); break; default: - pBuf = ImplAddUNum( pBuf, nYear, nYearLen ); + pBuf = ImplAddNum( pBuf, nYear, nYearLen ); pBuf = ImplAddString( pBuf, getDateSep() ); pBuf = ImplAdd2UNum( pBuf, nMonth, true /* IsDateMonthLeadingZero() */ ); pBuf = ImplAddString( pBuf, getDateSep() ); diff --git a/unotools/source/ucbhelper/ucblockbytes.cxx b/unotools/source/ucbhelper/ucblockbytes.cxx index f894c1cf7e1a..1e88ab7287b4 100644 --- a/unotools/source/ucbhelper/ucblockbytes.cxx +++ b/unotools/source/ucbhelper/ucblockbytes.cxx @@ -176,7 +176,7 @@ void SAL_CALL UcbPropertiesChangeListener_Impl::propertiesChange ( const Sequenc if (aName.compareToIgnoreAsciiCaseAscii("Expires") == 0) { - DateTime aExpires (0, 0); + DateTime aExpires( DateTime::EMPTY ); if (INetMIMEMessage::ParseDateField (aValue, aExpires)) { aExpires.ConvertToLocalTime(); diff --git a/vcl/source/control/field2.cxx b/vcl/source/control/field2.cxx index 7f0e9a8e1135..27b6b41ade8e 100644 --- a/vcl/source/control/field2.cxx +++ b/vcl/source/control/field2.cxx @@ -115,6 +115,16 @@ static sal_Unicode* ImplAddNum( sal_Unicode* pBuf, sal_uLong nNumber, int nMinLe return pBuf; } +static sal_Unicode* ImplAddSNum( sal_Unicode* pBuf, sal_Int32 nNumber, int nMinLen ) +{ + if (nNumber < 0) + { + *pBuf++ = '-'; + nNumber = -nNumber; + } + return ImplAddNum( pBuf, nNumber, nMinLen); +} + static sal_uInt16 ImplGetNum( const sal_Unicode*& rpBuf, bool& rbError ) { if ( !*rpBuf ) @@ -1048,7 +1058,7 @@ static bool ImplDateGetValue( const OUString& rStr, Date& rDate, ExtDateFieldFor if ( ( nSepPos < 0 ) || ( nSepPos == (aStr.getLength()-1) ) ) { bYear = false; - nYear = Date( Date::SYSTEM ).GetYear(); + nYear = Date( Date::SYSTEM ).GetYearUnsigned(); } const sal_Unicode* pBuf = aStr.getStr(); @@ -1114,7 +1124,7 @@ static bool ImplDateGetValue( const OUString& rStr, Date& rDate, ExtDateFieldFor bool DateFormatter::ImplDateReformat( const OUString& rStr, OUString& rOutStr, const AllSettings& rSettings ) { - Date aDate( 0, 0, 0 ); + Date aDate( Date::EMPTY ); if ( !ImplDateGetValue( rStr, aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) ) return true; @@ -1155,7 +1165,7 @@ OUString DateFormatter::ImplGetDateAsText( const Date& rDate, { // Check if I have to use force showing the century sal_uInt16 nTwoDigitYearStart = utl::MiscCfg().GetYear2000(); - sal_uInt16 nYear = rDate.GetYear(); + sal_uInt16 nYear = rDate.GetYearUnsigned(); // If year is not in double digit range if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) ) @@ -1168,7 +1178,7 @@ OUString DateFormatter::ImplGetDateAsText( const Date& rDate, OUString aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), GetExtDateFormat( true ) ); sal_uInt16 nDay = rDate.GetDay(); sal_uInt16 nMonth = rDate.GetMonth(); - sal_uInt16 nYear = rDate.GetYear(); + sal_Int16 nYear = rDate.GetYear(); sal_uInt16 nYearLen = bShowCentury ? 4 : 2; if ( !bShowCentury ) @@ -1187,7 +1197,7 @@ OUString DateFormatter::ImplGetDateAsText( const Date& rDate, pBuf = ImplAddString( pBuf, aDateSep ); pBuf = ImplAddNum( pBuf, nMonth, 2 ); pBuf = ImplAddString( pBuf, aDateSep ); - pBuf = ImplAddNum( pBuf, nYear, nYearLen ); + pBuf = ImplAddSNum( pBuf, nYear, nYearLen ); } break; case XTDATEF_SHORT_MMDDYY: @@ -1197,7 +1207,7 @@ OUString DateFormatter::ImplGetDateAsText( const Date& rDate, pBuf = ImplAddString( pBuf, aDateSep ); pBuf = ImplAddNum( pBuf, nDay, 2 ); pBuf = ImplAddString( pBuf, aDateSep ); - pBuf = ImplAddNum( pBuf, nYear, nYearLen ); + pBuf = ImplAddSNum( pBuf, nYear, nYearLen ); } break; case XTDATEF_SHORT_YYMMDD: @@ -1205,7 +1215,7 @@ OUString DateFormatter::ImplGetDateAsText( const Date& rDate, case XTDATEF_SHORT_YYMMDD_DIN5008: case XTDATEF_SHORT_YYYYMMDD_DIN5008: { - pBuf = ImplAddNum( pBuf, nYear, nYearLen ); + pBuf = ImplAddSNum( pBuf, nYear, nYearLen ); pBuf = ImplAddString( pBuf, aDateSep ); pBuf = ImplAddNum( pBuf, nMonth, 2 ); pBuf = ImplAddString( pBuf, aDateSep ); @@ -1227,12 +1237,12 @@ static void ImplDateIncrementDay( Date& rDate, bool bUp ) if ( bUp ) { - if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != 9999) ) + if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != SAL_MAX_INT16) ) ++rDate; } else { - if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != 0) ) + if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != SAL_MIN_INT16) ) --rDate; } } @@ -1242,13 +1252,13 @@ static void ImplDateIncrementMonth( Date& rDate, bool bUp ) DateFormatter::ExpandCentury( rDate ); sal_uInt16 nMonth = rDate.GetMonth(); - sal_uInt16 nYear = rDate.GetYear(); + sal_Int16 nYear = rDate.GetYear(); if ( bUp ) { - if ( (nMonth == 12) && (nYear < 9999) ) + if ( (nMonth == 12) && (nYear < SAL_MAX_INT16) ) { rDate.SetMonth( 1 ); - rDate.SetYear( nYear + 1 ); + rDate.SetYear( rDate.GetNextYear() ); } else { @@ -1258,10 +1268,10 @@ static void ImplDateIncrementMonth( Date& rDate, bool bUp ) } else { - if ( (nMonth == 1) && (nYear > 0) ) + if ( (nMonth == 1) && (nYear > SAL_MIN_INT16) ) { rDate.SetMonth( 12 ); - rDate.SetYear( nYear - 1 ); + rDate.SetYear( rDate.GetPrevYear() ); } else { @@ -1279,17 +1289,17 @@ static void ImplDateIncrementYear( Date& rDate, bool bUp ) { DateFormatter::ExpandCentury( rDate ); - sal_uInt16 nYear = rDate.GetYear(); + sal_Int16 nYear = rDate.GetYear(); sal_uInt16 nMonth = rDate.GetMonth(); if ( bUp ) { - if ( nYear < 9999 ) - rDate.SetYear( nYear + 1 ); + if ( nYear < SAL_MAX_INT16 ) + rDate.SetYear( rDate.GetNextYear() ); } else { - if ( nYear > 0 ) - rDate.SetYear( nYear - 1 ); + if ( nYear > SAL_MIN_INT16 ) + rDate.SetYear( rDate.GetPrevYear() ); } if (nMonth == 2) { @@ -1611,7 +1621,7 @@ void DateFormatter::ImplNewFieldValue( const Date& rDate ) Date DateFormatter::GetDate() const { - Date aDate( 0, 0, 0 ); + Date aDate( Date::EMPTY ); if ( GetField() ) { @@ -1705,8 +1715,8 @@ void DateFormatter::ExpandCentury( Date& rDate ) void DateFormatter::ExpandCentury( Date& rDate, sal_uInt16 nTwoDigitYearStart ) { - sal_uInt16 nDateYear = rDate.GetYear(); - if ( nDateYear < 100 ) + sal_Int16 nDateYear = rDate.GetYear(); + if ( 0 <= nDateYear && nDateYear < 100 ) { sal_uInt16 nCentury = nTwoDigitYearStart / 100; if ( nDateYear < (nTwoDigitYearStart % 100) ) diff --git a/xmloff/source/core/xmluconv.cxx b/xmloff/source/core/xmluconv.cxx index 1f2fe2446f38..fa34a3006f6b 100644 --- a/xmloff/source/core/xmluconv.cxx +++ b/xmloff/source/core/xmluconv.cxx @@ -375,21 +375,29 @@ void SvXMLUnitConverter::convertDateTime( OUStringBuffer& rBuffer, aDate += 1; } } - sal_uInt16 nTemp = aDate.GetYear(); - if (nTemp < 1000) + sal_Int16 nTempYear = aDate.GetYear(); + assert(nTempYear != 0); + if (nTempYear < 0) + { + rBuffer.append( '-'); + nTempYear = -nTempYear; + } + if (nTempYear < 1000) rBuffer.append( '0'); - if (nTemp < 100) + if (nTempYear < 100) rBuffer.append( '0'); - if (nTemp < 10) + if (nTempYear < 10) rBuffer.append( '0'); - rBuffer.append( sal_Int32( nTemp)); + rBuffer.append( sal_Int32( nTempYear)); rBuffer.append( '-'); - nTemp = aDate.GetMonth(); + sal_uInt16 nTemp = aDate.GetMonth(); + assert(1 <= nTemp && nTemp <= 12); if (nTemp < 10) rBuffer.append( '0'); rBuffer.append( sal_Int32( nTemp)); rBuffer.append( '-'); nTemp = aDate.GetDay(); + assert(1 <= nTemp && nTemp <= 31); if (nTemp < 10) rBuffer.append( '0'); rBuffer.append( sal_Int32( nTemp)); diff --git a/xmloff/source/text/txtlists.cxx b/xmloff/source/text/txtlists.cxx index 3fd31e514b4b..09c62c7f742c 100644 --- a/xmloff/source/text/txtlists.cxx +++ b/xmloff/source/text/txtlists.cxx @@ -225,7 +225,7 @@ OUString XMLTextListsHelper::GenerateNewListId() const { // Value of xml:id in element <text:list> has to be a valid ID type (#i92478#) sal_Int64 n = ::tools::Time( ::tools::Time::SYSTEM ).GetTime(); - n += Date( Date::SYSTEM ).GetDate(); + n += Date( Date::SYSTEM ).GetDateUnsigned(); n += comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max()); // Value of xml:id in element <text:list> has to be a valid ID type (#i92478#) sTmpStr += OUString::number( n ); diff --git a/xmlscript/source/xmldlg_imexp/xmldlg_export.cxx b/xmlscript/source/xmldlg_imexp/xmldlg_export.cxx index 1732d64523de..b352053c8ee6 100644 --- a/xmlscript/source/xmldlg_imexp/xmldlg_export.cxx +++ b/xmlscript/source/xmldlg_imexp/xmldlg_export.cxx @@ -591,7 +591,7 @@ void ElementDescriptor::readDateAttr( OUString const & rPropName, OUString const if (a >>= aUDate) { ::Date aTDate(aUDate); - addAttribute( rAttrName, OUString::number( aTDate.GetDate() ) ); + addAttribute( rAttrName, OUString::number( static_cast<sal_Int32>(aTDate.GetDate()) ) ); } else OSL_FAIL( "### internal error" ); diff --git a/xmlsecurity/source/dialogs/certificateviewer.cxx b/xmlsecurity/source/dialogs/certificateviewer.cxx index 509a467fbf4d..a2b61370e86b 100644 --- a/xmlsecurity/source/dialogs/certificateviewer.cxx +++ b/xmlsecurity/source/dialogs/certificateviewer.cxx @@ -129,8 +129,8 @@ CertificateViewerGeneralTP::CertificateViewerGeneralTP( vcl::Window* _pParent, C utl::typeConvert( xCert->getNotValidBefore(), aDateTimeStart ); utl::typeConvert( xCert->getNotValidAfter(), aDateTimeEnd ); - OUString sValidFromDate = GetSettings().GetUILocaleDataWrapper().getDate( aDateTimeStart.GetDate() ); - OUString sValidToDate = GetSettings().GetUILocaleDataWrapper().getDate( aDateTimeEnd.GetDate() ); + OUString sValidFromDate = GetSettings().GetUILocaleDataWrapper().getDate( Date( aDateTimeStart.GetDate())); + OUString sValidToDate = GetSettings().GetUILocaleDataWrapper().getDate( Date( aDateTimeEnd.GetDate())); m_pValidFromDateFI->SetText(sValidFromDate); m_pValidToDateFI->SetText(sValidToDate); @@ -253,12 +253,12 @@ CertificateViewerDetailsTP::CertificateViewerDetailsTP( vcl::Window* _pParent, C DateTime aDateTime( DateTime::EMPTY ); utl::typeConvert( xCert->getNotValidBefore(), aDateTime ); - aLBEntry = GetSettings().GetUILocaleDataWrapper().getDate( aDateTime.GetDate() ); + aLBEntry = GetSettings().GetUILocaleDataWrapper().getDate( Date( aDateTime.GetDate()) ); aLBEntry += " "; aLBEntry += GetSettings().GetUILocaleDataWrapper().getTime( aDateTime.GetTime() ); InsertElement( XMLSEC_RES( STR_VALIDFROM ), aLBEntry, aLBEntry ); utl::typeConvert( xCert->getNotValidAfter(), aDateTime ); - aLBEntry = GetSettings().GetUILocaleDataWrapper().getDate( aDateTime.GetDate() ); + aLBEntry = GetSettings().GetUILocaleDataWrapper().getDate( Date( aDateTime.GetDate()) ); aLBEntry += " "; aLBEntry += GetSettings().GetUILocaleDataWrapper().getTime( aDateTime.GetTime() ); InsertElement( XMLSEC_RES( STR_VALIDTO ), aLBEntry, aLBEntry ); |