summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--basic/source/runtime/methods.cxx4
-rw-r--r--chart2/source/tools/NumberFormatterWrapper.cxx3
-rw-r--r--chart2/source/view/axes/DateHelper.cxx18
-rw-r--r--chart2/source/view/inc/DateHelper.hxx4
-rw-r--r--connectivity/source/drivers/dbase/DTable.cxx2
-rw-r--r--editeng/source/items/flditem.cxx4
-rw-r--r--editeng/source/uno/unofield.cxx2
-rw-r--r--i18npool/inc/calendar_gregorian.hxx4
-rw-r--r--i18npool/source/calendar/calendar_gregorian.cxx20
-rw-r--r--include/editeng/flditem.hxx4
-rw-r--r--include/svl/zforlist.hxx2
-rw-r--r--include/svtools/calendar.hxx10
-rw-r--r--include/tools/date.hxx115
-rw-r--r--include/tools/datetime.hxx6
-rw-r--r--include/vcl/field.hxx4
-rw-r--r--sc/inc/docoptio.hxx4
-rw-r--r--sc/source/core/data/conditio.cxx4
-rw-r--r--sc/source/core/data/poolhelp.cxx6
-rw-r--r--sc/source/core/tool/chgviset.cxx2
-rw-r--r--sc/source/core/tool/docoptio.cxx8
-rw-r--r--sc/source/core/tool/interpr2.cxx11
-rw-r--r--sc/source/ui/cctrl/checklistmenu.cxx2
-rw-r--r--sc/source/ui/optdlg/tpcalc.cxx3
-rw-r--r--sc/source/ui/unoobj/optuno.cxx3
-rw-r--r--sfx2/source/doc/objcont.cxx2
-rw-r--r--solenv/gdb/libreoffice/tl.py8
-rw-r--r--svl/source/numbers/zforfind.cxx2
-rw-r--r--svl/source/numbers/zforfind.hxx2
-rw-r--r--svl/source/numbers/zforlist.cxx2
-rw-r--r--svl/source/numbers/zforscan.cxx2
-rw-r--r--svl/source/numbers/zforscan.hxx2
-rw-r--r--svtools/source/control/calendar.cxx18
-rw-r--r--svx/source/dialog/ctredlin.cxx3
-rw-r--r--sw/inc/docufld.hxx2
-rw-r--r--sw/source/core/fields/flddat.cxx2
-rw-r--r--sw/source/core/unocore/unocrsrhelper.cxx3
-rw-r--r--sw/source/core/unocore/unofield.cxx7
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx4
-rw-r--r--tools/CppunitTest_tools_test.mk1
-rw-r--r--tools/qa/cppunit/test_date.cxx76
-rw-r--r--tools/source/datetime/datetime.cxx7
-rw-r--r--tools/source/datetime/tdate.cxx261
-rw-r--r--unotools/source/i18n/localedatawrapper.cxx18
-rw-r--r--unotools/source/ucbhelper/ucblockbytes.cxx2
-rw-r--r--vcl/source/control/field2.cxx54
-rw-r--r--xmloff/source/core/xmluconv.cxx20
-rw-r--r--xmloff/source/text/txtlists.cxx2
-rw-r--r--xmlscript/source/xmldlg_imexp/xmldlg_export.cxx2
-rw-r--r--xmlsecurity/source/dialogs/certificateviewer.cxx8
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 );