From ba6acb0d1979df9e05a4f2650fad0b177ac5bbdd Mon Sep 17 00:00:00 2001 From: Sandu Liviu Catalin Date: Sat, 4 Jun 2016 11:55:06 +0300 Subject: [PATCH] Implement the Date type. --- source/Library/Chrono/Date.cpp | 243 +++++++++++++++++++++++++++++++-- source/Library/Chrono/Date.hpp | 84 ++++++++---- 2 files changed, 289 insertions(+), 38 deletions(-) diff --git a/source/Library/Chrono/Date.cpp b/source/Library/Chrono/Date.cpp index e3757d1a..2aaf6658 100644 --- a/source/Library/Chrono/Date.cpp +++ b/source/Library/Chrono/Date.cpp @@ -16,7 +16,7 @@ const Uint8 Date::MonthLengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 3 // ------------------------------------------------------------------------------------------------ SQInteger Date::Typename(HSQUIRRELVM vm) { - static const SQChar name[] = _SC("SqChronoDate"); + static const SQChar name[] = _SC("SqDate"); sq_pushstring(vm, name, sizeof(name)); return 1; } @@ -24,6 +24,7 @@ SQInteger Date::Typename(HSQUIRRELVM vm) // ------------------------------------------------------------------------------------------------ Date Date::operator + (const Date & o) const { + // Add the components individually return Date(o); } @@ -134,40 +135,223 @@ CSStr Date::ToString() const ); } +// ------------------------------------------------------------------------------------------------ +void Date::SetDayOfYear(Uint16 doy) +{ + // Reverse the given day of year to a full date + Date d = ReverseDayOfyear(m_Year, doy); + // Set the obtained month + SetMonth(d.m_Month); + // Set the obtained day + SetDay(d.m_Day); +} + // ------------------------------------------------------------------------------------------------ void Date::SetYear(Uint16 year) { - + // Make sure the year is valid + if (!year) + { + STHROWF("Invalid year: %u", year); + } + // Assign the value + m_Year = year; + // Make sure the new date is valid + if (!ValidDate(m_Year, m_Month, m_Day)) + { + m_Month = 1; + m_Day = 1; + } } // ------------------------------------------------------------------------------------------------ void Date::SetMonth(Uint8 month) { - + // Make sure the month is valid + if (month == 0 || month > 12) + { + STHROWF("Invalid month: %u", month); + } + // Assign the value + m_Month = month; + // Make sure the month days are in range + if (m_Day > DaysInMonth(m_Year, m_Month)) + { + m_Month = 1; // Fall back to the beginning of the month + } } // ------------------------------------------------------------------------------------------------ void Date::SetDay(Uint8 day) { - + // Grab the amount of days in the current month + const Uint8 dim = DaysInMonth(m_Year, m_Month); + // Make sure the day is valid + if (day == 0) + { + STHROWF("Invalid day: %u", day); + } + else if (day > dim) + { + STHROWF("Day is out of range: %u > %u", day, dim); + } + // Assign the value + m_Day = day; } // ------------------------------------------------------------------------------------------------ -Date Date::AddYears(Int32 years) +void Date::AddYears(Int32 years) { - return Date(*this); + // Do we have a valid amount of years? + if (years) + { + // Add the specified amount of years + SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years)); + } } // ------------------------------------------------------------------------------------------------ -Date Date::AddMonths(Int32 months) +void Date::AddMonths(Int32 months) { - return Date(*this); + // Do we have a valid amount of months? + if (!months) + { + // Calculate the the years, if any + Int32 years = static_cast< Int32 >(months / 12); + // Calculate the months, if any + months = (months % 12) + m_Month; + // Do we have extra months? + if (months >= 12) + { + ++years; + months %= 12; + } + else if (months < 0) + { + --years; + months = 12 - months; + } + // Are there any years to add? + if (years) + { + SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years)); + } + // Add the months + SetMonth(months); + } } // ------------------------------------------------------------------------------------------------ -Date Date::AddDays(Int32 days) +void Date::AddDays(Int32 days) { - return Date(*this); + // Do we have a valid amount of days? + if (!days) + { + // Should we go in a positive or negative direction? + Int32 dir = days > 0 ? 1 : -1; + // Grab current year + Int32 year = m_Year; + // Calculate the days in the current year + Int32 diy = DaysInYear(year); + // Calculate the day of year + Int32 doy = GetDayOfYear() + days; + // Calculate the resulting years + while (doy > diy || doy < 0) + { + doy -= diy * dir; + year += dir; + diy = DaysInYear(year); + } + // Set the obtained year + SetYear(year); + // Set the obtained day of year + SetDayOfYear(doy); + } +} + +// ------------------------------------------------------------------------------------------------ +Date Date::AndYears(Int32 years) +{ + // Do we have a valid amount of years? + if (!years) + { + return Date(*this); + } + // Replicate the current date + Date d(*this); + // Add the specified amount of years + d.SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years)); + // Return the resulted date + return d; +} + +// ------------------------------------------------------------------------------------------------ +Date Date::AndMonths(Int32 months) +{ + // Do we have a valid amount of months? + if (!months) + { + return Date(*this); + } + // Calculate the the years, if any + Int32 years = static_cast< Int32 >(months / 12); + // Calculate the months, if any + months = (months % 12) + m_Month; + // Do we have extra months? + if (months >= 12) + { + ++years; + months %= 12; + } + else if (months < 0) + { + --years; + months = 12 - months; + } + // Replicate the current date + Date d(*this); + // Are there any years to add? + if (years) + { + d.SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years)); + } + // Add the months + d.SetMonth(months); + // Return the resulted date + return d; +} + +// ------------------------------------------------------------------------------------------------ +Date Date::AndDays(Int32 days) +{ + // Do we have a valid amount of days? + if (!days) + { + return Date(*this); + } + // Should we go in a positive or negative direction? + Int32 dir = days > 0 ? 1 : -1; + // Grab current year + Int32 year = m_Year; + // Calculate the days in the current year + Int32 diy = DaysInYear(year); + // Calculate the day of year + Int32 doy = GetDayOfYear() + days; + // Calculate the resulting years + while (doy > diy || doy < 0) + { + doy -= diy * dir; + year += dir; + diy = DaysInYear(year); + } + // Replicate the current date + Date d(*this); + // Set the obtained year + d.SetYear(year); + // Set the obtained day of year + d.SetDayOfYear(doy); + // Return the resulted date + return d; } // ------------------------------------------------------------------------------------------------ @@ -222,10 +406,32 @@ Uint16 Date::DayOfYear(Uint16 year, Uint8 month, Uint8 day) return doy; } +// ------------------------------------------------------------------------------------------------ +Date Date::ReverseDayOfyear(Uint16 year, Uint16 doy) +{ + // The resulted month + Uint8 month = 1; + // Calculate the months till the specified day of year + for (; month < 12; ++month) + { + // Get the number of days in the current month + Uint32 days = DaysInMonth(year, month); + // Can this month fit in the remaining days? + if (days >= doy) + { + break; // The search is complete + } + // Subtract the month days from days of year + doy -= days; + } + // Return the resulted date + return Date(year, month, doy); +} + // ================================================================================================ void Register_ChronoDate(HSQUIRRELVM vm, Table & /*cns*/) { - RootTable(vm).Bind(_SC("SqDate"), Class< Date >(vm, _SC("SqChronoDate")) + RootTable(vm).Bind(_SC("SqDate"), Class< Date >(vm, _SC("SqDate")) // Constructors .Ctor() .Ctor< Uint16 >() @@ -243,11 +449,12 @@ void Register_ChronoDate(HSQUIRRELVM vm, Table & /*cns*/) .Func< Date (Date::*)(const Date &) const >(_SC("_mul"), &Date::operator *) .Func< Date (Date::*)(const Date &) const >(_SC("_div"), &Date::operator /) // Properties + .Prop(_SC("Delimiter"), &Date::GetDelimiter, &Date::SetDelimiter) + .Prop(_SC("DayOfYear"), &Date::GetDayOfYear, &Date::SetDayOfYear) + .Prop(_SC("Str"), &Date::GetStr, &Date::SetStr) .Prop(_SC("Year"), &Date::GetYear, &Date::SetYear) .Prop(_SC("Month"), &Date::GetMonth, &Date::SetMonth) .Prop(_SC("Day"), &Date::GetDay, &Date::SetDay) - .Prop(_SC("Str"), &Date::GetStr, &Date::SetStr) - .Prop(_SC("Delimiter"), &Date::GetDelimiter, &Date::SetDelimiter) .Prop(_SC("LeapYear"), &Date::IsThisLeapYear) .Prop(_SC("YearDays"), &Date::GetYearDays) .Prop(_SC("MonthDays"), &Date::GetMonthDays) @@ -255,10 +462,20 @@ void Register_ChronoDate(HSQUIRRELVM vm, Table & /*cns*/) .Func(_SC("AddYears"), &Date::AddYears) .Func(_SC("AddMonths"), &Date::AddMonths) .Func(_SC("AddDays"), &Date::AddDays) + .Func(_SC("AndYears"), &Date::AndYears) + .Func(_SC("AndMonths"), &Date::AndMonths) + .Func(_SC("AndDays"), &Date::AndDays) // Overloaded Methods .Overload< void (Date::*)(Uint16) >(_SC("Set"), &Date::Set) .Overload< void (Date::*)(Uint16, Uint8) >(_SC("Set"), &Date::Set) .Overload< void (Date::*)(Uint16, Uint8, Uint8) >(_SC("Set"), &Date::Set) + // Static Functions + .StaticFunc(_SC("IsLeapYear"), &Date::IsLeapYear) + .StaticFunc(_SC("IsValidDate"), &Date::ValidDate) + .StaticFunc(_SC("GetDaysInYear"), &Date::DaysInYear) + .StaticFunc(_SC("GetDaysInMonth"), &Date::DaysInMonth) + .StaticFunc(_SC("GetDayOfYear"), &Date::DayOfYear) + .StaticFunc(_SC("GetReverseDayOfyear"), &Date::ReverseDayOfyear) ); } diff --git a/source/Library/Chrono/Date.hpp b/source/Library/Chrono/Date.hpp index 271f34a7..f15b4fec 100644 --- a/source/Library/Chrono/Date.hpp +++ b/source/Library/Chrono/Date.hpp @@ -33,7 +33,7 @@ public: } /* ------------------------------------------------------------------------------------------------ - * Base constructor. + * Speciffic year constructor. */ Date(Uint16 year) : m_Delimiter(Delimiter) @@ -42,7 +42,7 @@ public: } /* ------------------------------------------------------------------------------------------------ - * Base constructor. + * Speciffic year and month constructor. */ Date(Uint16 year, Uint8 month) : m_Delimiter(Delimiter) @@ -51,7 +51,7 @@ public: } /* ------------------------------------------------------------------------------------------------ - * Base constructor. + * Speciffic date constructor. */ Date(Uint16 year, Uint8 month, Uint8 day) : m_Delimiter(Delimiter) @@ -179,22 +179,6 @@ public: */ static SQInteger Typename(HSQUIRRELVM vm); - /* ------------------------------------------------------------------------------------------------ - * Retrieve the local delimiter character. - */ - SQChar GetDelimiter() const - { - return m_Delimiter; - } - - /* ------------------------------------------------------------------------------------------------ - * Modify the local delimiter character. - */ - void SetDelimiter(SQChar c) - { - m_Delimiter = c; - } - /* ------------------------------------------------------------------------------------------------ * Assign the specified values. */ @@ -216,6 +200,35 @@ public: */ void Set(Uint16 year, Uint8 month, Uint8 day); + /* ------------------------------------------------------------------------------------------------ + * Retrieve the local delimiter character. + */ + SQChar GetDelimiter() const + { + return m_Delimiter; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the local delimiter character. + */ + void SetDelimiter(SQChar c) + { + m_Delimiter = c; + } + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the day component. + */ + Uint16 GetDayOfYear() const + { + return DayOfYear(m_Year, m_Month, m_Day); + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the day component. + */ + void SetDayOfYear(Uint16 doy); + /* ------------------------------------------------------------------------------------------------ * Retrieve the values as a string. */ @@ -266,19 +279,34 @@ public: void SetDay(Uint8 day); /* ------------------------------------------------------------------------------------------------ - * Add the specified amount of years. + * Add the specified amount of years to the current date. */ - Date AddYears(Int32 years); + void AddYears(Int32 years); /* ------------------------------------------------------------------------------------------------ - * Add the specified amount of months. + * Add the specified amount of months to the current date. */ - Date AddMonths(Int32 months); + void AddMonths(Int32 months); /* ------------------------------------------------------------------------------------------------ - * Add the specified amount of days. + * Add the specified amount of days to the current date. */ - Date AddDays(Int32 days); + void AddDays(Int32 days); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of years to obtain a new date. + */ + Date AndYears(Int32 years); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of months to obtain a new date. + */ + Date AndMonths(Int32 months); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of days to obtain a new date. + */ + Date AndDays(Int32 days); /* ------------------------------------------------------------------------------------------------ * See whether the associated year is a leap year. @@ -353,6 +381,12 @@ public: * Retrieve the number/position of the specified day in the specified year and month. */ static Uint16 DayOfYear(Uint16 year, Uint8 month, Uint8 day); + + /* ------------------------------------------------------------------------------------------------ + * Convert just the year and day of year to full date. + */ + static Date ReverseDayOfyear(Uint16 year, Uint16 doy); + }; } // Namespace:: SqMod