summaryrefslogtreecommitdiff
path: root/include/tools/date.hxx
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2016-07-08 17:08:47 +0200
committerEike Rathke <erack@redhat.com>2016-07-08 20:41:02 +0000
commit6d4f2dcc7cbba771e9d9b00de50368db4a88ef1b (patch)
tree0301896941b955ffa79ef3e96b874ebdad78662c /include/tools/date.hxx
parent06287b9c348281612854d67c4eb2e7a38dc722ca (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>
Diffstat (limited to 'include/tools/date.hxx')
-rw-r--r--include/tools/date.hxx115
1 files changed, 79 insertions, 36 deletions
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