From 0093bc2decc9e807853336e434a5be86ca5a3a98 Mon Sep 17 00:00:00 2001 From: Sandu Liviu Catalin Date: Sat, 4 Jun 2016 19:17:42 +0300 Subject: [PATCH] Implemented and improved more types in the Chrono library. --- source/Exports.cpp | 6 +- source/Library/Chrono.cpp | 137 +++-- source/Library/Chrono.hpp | 104 +++- source/Library/Chrono/Date.cpp | 292 ++++------- source/Library/Chrono/Date.hpp | 112 ++-- source/Library/Chrono/Datetime.cpp | 773 +++++++++++++++++++++++++++- source/Library/Chrono/Datetime.hpp | 559 +++++++++++++++++++- source/Library/Chrono/Time.cpp | 407 +++++++++------ source/Library/Chrono/Time.hpp | 101 ++-- source/Library/Chrono/Timer.cpp | 13 +- source/Library/Chrono/Timer.hpp | 2 +- source/Library/Chrono/Timestamp.cpp | 5 +- source/Library/Chrono/Timestamp.hpp | 2 +- source/Routine.cpp | 4 +- 14 files changed, 1994 insertions(+), 523 deletions(-) diff --git a/source/Exports.cpp b/source/Exports.cpp index 5877505e..c7445f81 100644 --- a/source/Exports.cpp +++ b/source/Exports.cpp @@ -273,9 +273,9 @@ void InitExports() g_SqExports.PushULongObject = SqEx_PushULongObject; //time utilities - g_SqExports.GetCurrentSysTime = GetCurrentSysTime; - g_SqExports.GetEpochTimeMicro = GetEpochTimeMicro; - g_SqExports.GetEpochTimeMilli = GetEpochTimeMilli; + g_SqExports.GetCurrentSysTime = Chrono::GetCurrentSysTime; + g_SqExports.GetEpochTimeMicro = Chrono::GetEpochTimeMicro; + g_SqExports.GetEpochTimeMilli = Chrono::GetEpochTimeMilli; g_SqExports.GetTimestamp = SqEx_GetTimestamp; g_SqExports.PushTimestamp = SqEx_PushTimestamp; diff --git a/source/Library/Chrono.cpp b/source/Library/Chrono.cpp index 622e1d1a..147ef332 100644 --- a/source/Library/Chrono.cpp +++ b/source/Library/Chrono.cpp @@ -18,13 +18,23 @@ // ------------------------------------------------------------------------------------------------ namespace SqMod { +// ------------------------------------------------------------------------------------------------ +extern void Register_ChronoDate(HSQUIRRELVM vm, Table & cns); +extern void Register_ChronoDatetime(HSQUIRRELVM vm, Table & cns); +extern void Register_ChronoTime(HSQUIRRELVM vm, Table & cns); +extern void Register_ChronoTimer(HSQUIRRELVM vm, Table & cns); +extern void Register_ChronoTimestamp(HSQUIRRELVM vm, Table & cns); + +// ------------------------------------------------------------------------------------------------ +const Uint8 Chrono::MonthLengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + // ------------------------------------------------------------------------------------------------ #ifdef SQMOD_OS_WINDOWS /* ------------------------------------------------------------------------------------------------ * Used by GetCurrentSysTime to obtain the system frequency on initial call. */ -LARGE_INTEGER GetFrequency() +inline LARGE_INTEGER GetFrequency() { LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); @@ -32,7 +42,7 @@ LARGE_INTEGER GetFrequency() } // ------------------------------------------------------------------------------------------------ -Int64 GetCurrentSysTime() +Int64 Chrono::GetCurrentSysTime() { // Force the following code to run on first core // (see http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx) @@ -55,7 +65,7 @@ Int64 GetCurrentSysTime() } // ------------------------------------------------------------------------------------------------ -Int64 GetEpochTimeMicro() +Int64 Chrono::GetEpochTimeMicro() { FILETIME ft; GetSystemTimeAsFileTime(&ft); @@ -70,25 +80,17 @@ Int64 GetEpochTimeMicro() } // ------------------------------------------------------------------------------------------------ -Uint32 GetTickCount() -{ - return GetTickCount(); -} - -// ------------------------------------------------------------------------------------------------ +#ifndef _SQ64 Int64 GetTickCount64() { -#ifdef _SQ64 - return GetTickCount64(); -#else - return 0; // Should we fallback to 32 bit? -#endif // _SQ64 + return 0ULL; // Should we fallback to 32 bit? } +#endif // _SQ64 #else // ------------------------------------------------------------------------------------------------ -Int64 GetCurrentSysTime() +Int64 Chrono::GetCurrentSysTime() { // POSIX implementation timespec time; @@ -97,7 +99,7 @@ Int64 GetCurrentSysTime() } // ------------------------------------------------------------------------------------------------ -Int64 GetEpochTimeMicro() +Int64 Chrono::GetEpochTimeMicro() { // POSIX implementation timespec time; @@ -106,7 +108,7 @@ Int64 GetEpochTimeMicro() } // ------------------------------------------------------------------------------------------------ -Uint32 GetTickCount() +Uint32 Chrono::GetTickCount() { // POSIX implementation struct timespec time; @@ -118,7 +120,7 @@ Uint32 GetTickCount() } // ------------------------------------------------------------------------------------------------ -Int64 GetTickCount64() +Int64 Chrono::GetTickCount64() { struct timespec time; if (clock_gettime(CLOCK_MONOTONIC, &time)) @@ -131,33 +133,107 @@ Int64 GetTickCount64() #endif // SQMOD_OS_WINDOWS // ------------------------------------------------------------------------------------------------ -Int64 GetEpochTimeMilli() +Int64 Chrono::GetEpochTimeMilli() { return (GetEpochTimeMicro() / 1000L); } +// ------------------------------------------------------------------------------------------------ +bool Chrono::ValidDate(Uint16 year, Uint8 month, Uint8 day) +{ + // Is this a valid date? + if (year == 0 || month == 0 || day == 0) + { + return false; + } + // Is the month within range? + else if (month > 12) + { + return false; + } + // Return whether the day inside the month + return day <= DaysInMonth(year, month); +} + +// ------------------------------------------------------------------------------------------------ +Uint8 Chrono::DaysInMonth(Uint16 year, Uint8 month) +{ + // Is the specified month within range? + if (month > 12) + { + STHROWF("Month value is out of range: %u > 12", month); + } + // Obtain the days in this month + Uint8 days = *(MonthLengths + month); + // Should we account for January? + if (month == 2 && IsLeapYear(year)) + { + ++days; + } + // Return the resulted days + return days; +} + +// ------------------------------------------------------------------------------------------------ +Uint16 Chrono::DayOfYear(Uint16 year, Uint8 month, Uint8 day) +{ + // Start with 0 days + Uint16 doy = 0; + // Cumulate the days in months + for (Uint8 m = 1; m < month; ++month) + { + doy += DaysInMonth(year, m); + } + // Add the specified days + doy += day; + // Return the result + return doy; +} + +// ------------------------------------------------------------------------------------------------ +Date Chrono::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); +} + // ------------------------------------------------------------------------------------------------ static SLongInt SqGetEpochTimeMicro() { - return SLongInt(GetEpochTimeMicro()); + return SLongInt(Chrono::GetEpochTimeMicro()); } // ------------------------------------------------------------------------------------------------ static SLongInt SqGetEpochTimeMilli() { - return SLongInt(GetEpochTimeMilli()); + return SLongInt(Chrono::GetEpochTimeMilli()); } // ------------------------------------------------------------------------------------------------ static SLongInt SqGetCurrentSysTime() { - return SLongInt(GetCurrentSysTime()); + return SLongInt(Chrono::GetCurrentSysTime()); } // ------------------------------------------------------------------------------------------------ static SQInteger SqGetTickCount() { - return GetTickCount(); + return ConvTo< SQInteger >::From(GetTickCount()); } // ------------------------------------------------------------------------------------------------ @@ -166,13 +242,6 @@ static SLongInt SqGetTickCount64() return SLongInt(GetTickCount64()); } -// ------------------------------------------------------------------------------------------------ -extern void Register_ChronoDate(HSQUIRRELVM vm, Table & cns); -extern void Register_ChronoDatetime(HSQUIRRELVM vm, Table & cns); -extern void Register_ChronoTime(HSQUIRRELVM vm, Table & cns); -extern void Register_ChronoTimer(HSQUIRRELVM vm, Table & cns); -extern void Register_ChronoTimestamp(HSQUIRRELVM vm, Table & cns); - // ================================================================================================ void Register_Chrono(HSQUIRRELVM vm) { @@ -189,7 +258,13 @@ void Register_Chrono(HSQUIRRELVM vm) .Func(_SC("EpochMilli"), &SqGetEpochTimeMilli) .Func(_SC("Current"), &SqGetCurrentSysTime) .Func(_SC("TickCount"), &SqGetTickCount) - .Func(_SC("TickCount64"), &SqGetTickCount64); + .Func(_SC("TickCount64"), &SqGetTickCount64) + .Func(_SC("IsLeapYear"), &Chrono::IsLeapYear) + .Func(_SC("IsDateValid"), &Chrono::ValidDate) + .Func(_SC("DaysInYear"), &Chrono::DaysInYear) + .Func(_SC("DaysInMonth"), &Chrono::DaysInMonth) + .Func(_SC("DayOfYear"), &Chrono::DayOfYear) + .Func(_SC("ReverseDayOfyear"), &Chrono::ReverseDayOfyear); RootTable(vm).Bind(_SC("SqChrono"), cns); } diff --git a/source/Library/Chrono.hpp b/source/Library/Chrono.hpp index 19f0c585..66009ec6 100644 --- a/source/Library/Chrono.hpp +++ b/source/Library/Chrono.hpp @@ -7,20 +7,104 @@ // ------------------------------------------------------------------------------------------------ namespace SqMod { -/* ------------------------------------------------------------------------------------------------ - * Retrieve the current time as microseconds. -*/ -Int64 GetCurrentSysTime(); +// ------------------------------------------------------------------------------------------------ +class Date; +class Time; +class Datetime; +class Timer; +class Timestamp; /* ------------------------------------------------------------------------------------------------ - * Retrieve the epoch time as microseconds. + * Class that offers helpers to work with time related information. */ -Int64 GetEpochTimeMicro(); +class Chrono +{ +public: -/* ------------------------------------------------------------------------------------------------ - * Retrieve the epoch time as milliseconds. -*/ -Int64 GetEpochTimeMilli(); + // ------------------------------------------------------------------------------------------------ + static const Uint8 MonthLengths[12]; + + /* -------------------------------------------------------------------------------------------- + * Default constructor. (disabled) + */ + Chrono() = delete; + + /* -------------------------------------------------------------------------------------------- + * Copy constructor. (disabled) + */ + Chrono(const Chrono & o) = delete; + + /* -------------------------------------------------------------------------------------------- + * Move constructor. (disabled) + */ + Chrono(Chrono && o) = delete; + + /* -------------------------------------------------------------------------------------------- + * Destructor. (disabled) + */ + ~Chrono() = delete; + + /* -------------------------------------------------------------------------------------------- + * Copy assignment operator. (disabled) + */ + Chrono & operator = (const Chrono & o) = delete; + + /* -------------------------------------------------------------------------------------------- + * Move assignment operator. (disabled) + */ + Chrono & operator = (Chrono && o) = delete; + + /* -------------------------------------------------------------------------------------------- + * Retrieve the current time as microseconds. + */ + static Int64 GetCurrentSysTime(); + + /* -------------------------------------------------------------------------------------------- + * Retrieve the epoch time as microseconds. + */ + static Int64 GetEpochTimeMicro(); + + /* -------------------------------------------------------------------------------------------- + * Retrieve the epoch time as milliseconds. + */ + static Int64 GetEpochTimeMilli(); + + /* -------------------------------------------------------------------------------------------- + * See whether the specified date is valid. + */ + static bool ValidDate(Uint16 year, Uint8 month, Uint8 day); + + /* -------------------------------------------------------------------------------------------- + * See whether the specified year is a leap year. + */ + static bool IsLeapYear(Uint16 year) + { + return !(year % 400) || (!(year % 4) && (year % 100)); + } + + /* -------------------------------------------------------------------------------------------- + * retrieve the number of days in the specified year. + */ + static Uint16 DaysInYear(Uint16 year) + { + return IsLeapYear(year) ? 366 : 365; + } + + /* -------------------------------------------------------------------------------------------- + * Retrieve the number of days in the specified month. + */ + static Uint8 DaysInMonth(Uint16 year, Uint8 month); + + /* -------------------------------------------------------------------------------------------- + * 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 diff --git a/source/Library/Chrono/Date.cpp b/source/Library/Chrono/Date.cpp index 2aaf6658..4895fe7c 100644 --- a/source/Library/Chrono/Date.cpp +++ b/source/Library/Chrono/Date.cpp @@ -10,9 +10,6 @@ namespace SqMod { // ------------------------------------------------------------------------------------------------ SQChar Date::Delimiter = '-'; -// ------------------------------------------------------------------------------------------------ -const Uint8 Date::MonthLengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - // ------------------------------------------------------------------------------------------------ SQInteger Date::Typename(HSQUIRRELVM vm) { @@ -21,79 +18,6 @@ SQInteger Date::Typename(HSQUIRRELVM vm) return 1; } -// ------------------------------------------------------------------------------------------------ -Date Date::operator + (const Date & o) const -{ - // Add the components individually - return Date(o); -} - -// ------------------------------------------------------------------------------------------------ -Date Date::operator - (const Date & o) const -{ - return Date(o); -} - -// ------------------------------------------------------------------------------------------------ -Date Date::operator * (const Date & o) const -{ - return Date(o); -} - -// ------------------------------------------------------------------------------------------------ -Date Date::operator / (const Date & o) const -{ - return Date(o); -} - -// ------------------------------------------------------------------------------------------------ -void Date::Set(Uint16 year, Uint8 month, Uint8 day) -{ - if (!ValidDate(year, month, day)) - { - STHROWF("Invalid date: %04u%c%02u%c%02u%c%u" - , m_Delimiter, m_Year - , m_Delimiter, m_Month - , m_Delimiter, m_Day - ); - } -} - -// ------------------------------------------------------------------------------------------------ -CSStr Date::GetStr() const -{ - return ToString(); -} - -// ------------------------------------------------------------------------------------------------ -void Date::SetStr(CSStr str) -{ - // The format specifications that will be used to scan the string - static SQChar fs[] = _SC(" %u , %u , %u,"); - // Is the specified string empty? - if (!str || *str == '\0') - { - // Clear the values - m_Year = 0; - m_Month = 0; - m_Day = 0; - // We're done here - return; - } - // Assign the specified delimiter - fs[4] = m_Delimiter; - fs[9] = m_Delimiter; - // The sscanf function requires at least 32 bit integers - Uint32 year = 0, month = 0, day = 0; - // Attempt to extract the component values from the specified string - sscanf(str, fs, &year, &month, &day); - // Clamp the extracted values to the boundaries of associated type and assign them - Set(ClampL< Uint32, Uint8 >(year), - ClampL< Uint32, Uint8 >(month), - ClampL< Uint32, Uint8 >(day) - ); -} - // ------------------------------------------------------------------------------------------------ Int32 Date::Compare(const Date & o) const { @@ -125,13 +49,76 @@ Int32 Date::Compare(const Date & o) const return 0; } +// ------------------------------------------------------------------------------------------------ +Date Date::operator + (const Date & o) const +{ + // Add the components individually + return Date(o); +} + +// ------------------------------------------------------------------------------------------------ +Date Date::operator - (const Date & o) const +{ + return Date(o); +} + +// ------------------------------------------------------------------------------------------------ +Date Date::operator * (const Date & o) const +{ + return Date(o); +} + +// ------------------------------------------------------------------------------------------------ +Date Date::operator / (const Date & o) const +{ + return Date(o); +} + // ------------------------------------------------------------------------------------------------ CSStr Date::ToString() const { - return ToStrF("%04u%c%02u%c%02u%c%u" - , m_Delimiter, m_Year - , m_Delimiter, m_Month - , m_Delimiter, m_Day + return ToStrF("%04u%c%02u%c%02u", m_Year, m_Delimiter, m_Month, m_Delimiter, m_Day); +} + +// ------------------------------------------------------------------------------------------------ +void Date::Set(Uint16 year, Uint8 month, Uint8 day) +{ + if (!Chrono::ValidDate(year, month, day)) + { + STHROWF("Invalid date: %04u%c%02u%c%02u" , m_Year, m_Delimiter, m_Month, m_Delimiter, m_Day); + } + // Assign the specified values + m_Year = year; + m_Month = month; + m_Day = day; +} + +// ------------------------------------------------------------------------------------------------ +void Date::SetStr(CSStr str) +{ + // The format specifications that will be used to scan the string + static SQChar fs[] = _SC(" %u - %u - %u "); + // Is the specified string empty? + if (!str || *str == '\0') + { + // Clear the values + m_Year = 0; + m_Month = 0; + m_Day = 0; + // We're done here + return; + } + // Assign the specified delimiter + fs[4] = m_Delimiter; + fs[9] = m_Delimiter; + // The sscanf function requires at least 32 bit integers + Uint32 year = 0, month = 0, day = 0; + // Attempt to extract the component values from the specified string + sscanf(str, fs, &year, &month, &day); + // Clamp the extracted values to the boundaries of associated type and assign them + Set(ClampL< Uint32, Uint8 >(year), + ClampL< Uint32, Uint8 >(month), + ClampL< Uint32, Uint8 >(day) ); } @@ -139,7 +126,7 @@ 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); + Date d = Chrono::ReverseDayOfyear(m_Year, doy); // Set the obtained month SetMonth(d.m_Month); // Set the obtained day @@ -157,7 +144,7 @@ void Date::SetYear(Uint16 year) // Assign the value m_Year = year; // Make sure the new date is valid - if (!ValidDate(m_Year, m_Month, m_Day)) + if (!Chrono::ValidDate(m_Year, m_Month, m_Day)) { m_Month = 1; m_Day = 1; @@ -175,7 +162,7 @@ void Date::SetMonth(Uint8 month) // Assign the value m_Month = month; // Make sure the month days are in range - if (m_Day > DaysInMonth(m_Year, m_Month)) + if (m_Day > Chrono::DaysInMonth(m_Year, m_Month)) { m_Month = 1; // Fall back to the beginning of the month } @@ -185,7 +172,7 @@ void Date::SetMonth(Uint8 month) void Date::SetDay(Uint8 day) { // Grab the amount of days in the current month - const Uint8 dim = DaysInMonth(m_Year, m_Month); + const Uint8 dim = Chrono::DaysInMonth(m_Year, m_Month); // Make sure the day is valid if (day == 0) { @@ -200,7 +187,7 @@ void Date::SetDay(Uint8 day) } // ------------------------------------------------------------------------------------------------ -void Date::AddYears(Int32 years) +Date & Date::AddYears(Int32 years) { // Do we have a valid amount of years? if (years) @@ -208,27 +195,33 @@ void Date::AddYears(Int32 years) // Add the specified amount of years SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years)); } + // Allow chaining operations + return *this; } // ------------------------------------------------------------------------------------------------ -void Date::AddMonths(Int32 months) +Date & Date::AddMonths(Int32 months) { // Do we have a valid amount of months? - if (!months) + if (months) { - // Calculate the the years, if any + // Extract the number of years Int32 years = static_cast< Int32 >(months / 12); - // Calculate the months, if any + // Extract the number of months months = (months % 12) + m_Month; // Do we have extra months? if (months >= 12) { + // Increase the years ++years; + // Subtract one year from months months %= 12; } else if (months < 0) { + // Decrease the years --years; + // Add one year to months months = 12 - months; } // Are there any years to add? @@ -239,20 +232,22 @@ void Date::AddMonths(Int32 months) // Add the months SetMonth(months); } + // Allow chaining operations + return *this; } // ------------------------------------------------------------------------------------------------ -void Date::AddDays(Int32 days) +Date & Date::AddDays(Int32 days) { // Do we have a valid amount of days? - if (!days) + if (days) { - // Should we go in a positive or negative direction? - Int32 dir = days > 0 ? 1 : -1; + // Whether the number of days is positive or negative + const Int32 dir = days > 0 ? 1 : -1; // Grab current year Int32 year = m_Year; // Calculate the days in the current year - Int32 diy = DaysInYear(year); + Int32 diy = Chrono::DaysInYear(year); // Calculate the day of year Int32 doy = GetDayOfYear() + days; // Calculate the resulting years @@ -260,13 +255,15 @@ void Date::AddDays(Int32 days) { doy -= diy * dir; year += dir; - diy = DaysInYear(year); + diy = Chrono::DaysInYear(year); } // Set the obtained year SetYear(year); // Set the obtained day of year SetDayOfYear(doy); } + // Allow chaining operations + return *this; } // ------------------------------------------------------------------------------------------------ @@ -275,7 +272,7 @@ Date Date::AndYears(Int32 years) // Do we have a valid amount of years? if (!years) { - return Date(*this); + return Date(*this); // Return the date as is } // Replicate the current date Date d(*this); @@ -291,21 +288,25 @@ Date Date::AndMonths(Int32 months) // Do we have a valid amount of months? if (!months) { - return Date(*this); + return Date(*this); // Return the date as is } - // Calculate the the years, if any + // Extract the number of years Int32 years = static_cast< Int32 >(months / 12); - // Calculate the months, if any + // Extract the number of months months = (months % 12) + m_Month; // Do we have extra months? if (months >= 12) { + // Increase the years ++years; + // Subtract one year from months months %= 12; } else if (months < 0) { + // Decrease the years --years; + // Add one year to months months = 12 - months; } // Replicate the current date @@ -327,14 +328,14 @@ Date Date::AndDays(Int32 days) // Do we have a valid amount of days? if (!days) { - return Date(*this); + return Date(*this); // Return the date as is } - // Should we go in a positive or negative direction? - Int32 dir = days > 0 ? 1 : -1; + // Whether the number of days is positive or negative + const Int32 dir = days > 0 ? 1 : -1; // Grab current year Int32 year = m_Year; // Calculate the days in the current year - Int32 diy = DaysInYear(year); + Int32 diy = Chrono::DaysInYear(year); // Calculate the day of year Int32 doy = GetDayOfYear() + days; // Calculate the resulting years @@ -342,7 +343,7 @@ Date Date::AndDays(Int32 days) { doy -= diy * dir; year += dir; - diy = DaysInYear(year); + diy = Chrono::DaysInYear(year); } // Replicate the current date Date d(*this); @@ -354,80 +355,6 @@ Date Date::AndDays(Int32 days) return d; } -// ------------------------------------------------------------------------------------------------ -bool Date::ValidDate(Uint16 year, Uint8 month, Uint8 day) -{ - // Is this a valid date? - if (year == 0 || month == 0 || day == 0) - { - return false; - } - // Is the month within range? - else if (month > 12) - { - return false; - } - // Return whether the day inside the month - return day <= DaysInMonth(year, month); -} - -// ------------------------------------------------------------------------------------------------ -Uint8 Date::DaysInMonth(Uint16 year, Uint8 month) -{ - // Is the specified month within range? - if (month > 12) - { - STHROWF("Month value is out of range: %u > 12", month); - } - // Obtain the days in this month - Uint8 days = *(MonthLengths + month); - // Should we account for January? - if (month == 2 && IsLeapYear(year)) - { - ++days; - } - // Return the resulted days - return days; -} - -// ------------------------------------------------------------------------------------------------ -Uint16 Date::DayOfYear(Uint16 year, Uint8 month, Uint8 day) -{ - // Start with 0 days - Uint16 doy = 0; - // Cumulate the days in months - for (Uint8 m = 1; m < month; ++month) - { - doy += DaysInMonth(year, m); - } - // Add the specified days - doy += day; - // Return the result - 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*/) { @@ -450,8 +377,8 @@ void Register_ChronoDate(HSQUIRRELVM vm, Table & /*cns*/) .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("DayOfYear"), &Date::GetDayOfYear, &Date::SetDayOfYear) .Prop(_SC("Year"), &Date::GetYear, &Date::SetYear) .Prop(_SC("Month"), &Date::GetMonth, &Date::SetMonth) .Prop(_SC("Day"), &Date::GetDay, &Date::SetDay) @@ -469,13 +396,6 @@ void Register_ChronoDate(HSQUIRRELVM vm, Table & /*cns*/) .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 f15b4fec..c7785578 100644 --- a/source/Library/Chrono/Date.hpp +++ b/source/Library/Chrono/Date.hpp @@ -2,7 +2,7 @@ #define _LIBRARY_CHRONO_DATE_HPP_ // ------------------------------------------------------------------------------------------------ -#include "SqBase.hpp" +#include "Library/Chrono.hpp" // ------------------------------------------------------------------------------------------------ namespace SqMod { @@ -17,8 +17,24 @@ public: // ------------------------------------------------------------------------------------------------ static SQChar Delimiter; +private: + // ------------------------------------------------------------------------------------------------ - static const Uint8 MonthLengths[12]; + Uint16 m_Year; // Year + Uint8 m_Month; // Month + Uint8 m_Day; // Day + + // ------------------------------------------------------------------------------------------------ + SQChar m_Delimiter; // Component delimiter when generating strings. + +protected: + + /* ------------------------------------------------------------------------------------------------ + * Compare the values of two instances. + */ + Int32 Compare(const Date & o) const; + +public: /* ------------------------------------------------------------------------------------------------ * Default constructor. @@ -216,12 +232,25 @@ public: m_Delimiter = c; } + /* ------------------------------------------------------------------------------------------------ + * Retrieve the values as a string. + */ + CSStr GetStr() const + { + return ToString(); + } + + /* ------------------------------------------------------------------------------------------------ + * Extract the values from a string. + */ + void SetStr(CSStr str); + /* ------------------------------------------------------------------------------------------------ * Retrieve the day component. */ Uint16 GetDayOfYear() const { - return DayOfYear(m_Year, m_Month, m_Day); + return Chrono::DayOfYear(m_Year, m_Month, m_Day); } /* ------------------------------------------------------------------------------------------------ @@ -229,16 +258,6 @@ public: */ void SetDayOfYear(Uint16 doy); - /* ------------------------------------------------------------------------------------------------ - * Retrieve the values as a string. - */ - CSStr GetStr() const; - - /* ------------------------------------------------------------------------------------------------ - * Extract the values from a string. - */ - void SetStr(CSStr str); - /* ------------------------------------------------------------------------------------------------ * Retrieve the year component. */ @@ -281,17 +300,17 @@ public: /* ------------------------------------------------------------------------------------------------ * Add the specified amount of years to the current date. */ - void AddYears(Int32 years); + Date & AddYears(Int32 years); /* ------------------------------------------------------------------------------------------------ * Add the specified amount of months to the current date. */ - void AddMonths(Int32 months); + Date & AddMonths(Int32 months); /* ------------------------------------------------------------------------------------------------ * Add the specified amount of days to the current date. */ - void AddDays(Int32 days); + Date & AddDays(Int32 days); /* ------------------------------------------------------------------------------------------------ * Add the specified amount of years to obtain a new date. @@ -313,7 +332,7 @@ public: */ bool IsThisLeapYear() const { - return IsLeapYear(m_Year); + return Chrono::IsLeapYear(m_Year); } /* ------------------------------------------------------------------------------------------------ @@ -321,7 +340,7 @@ public: */ Uint16 GetYearDays() const { - return DaysInYear(m_Year); + return Chrono::DaysInYear(m_Year); } /* ------------------------------------------------------------------------------------------------ @@ -329,64 +348,9 @@ public: */ Uint8 GetMonthDays() const { - return DaysInMonth(m_Year, m_Month); + return Chrono::DaysInMonth(m_Year, m_Month); } -protected: - - /* ------------------------------------------------------------------------------------------------ - * Compare the values of two instances. - */ - Int32 Compare(const Date & o) const; - -private: - - // ------------------------------------------------------------------------------------------------ - Uint16 m_Year; // Year - Uint8 m_Month; // Month - Uint8 m_Day; // Day - - // ------------------------------------------------------------------------------------------------ - SQChar m_Delimiter; // Component delimiter when generating strings. - -public: - - /* ------------------------------------------------------------------------------------------------ - * See whether the specified year is a leap year. - */ - static bool IsLeapYear(Uint16 year) - { - return !(year % 400) || (!(year % 4) && (year % 100)); - } - - /* ------------------------------------------------------------------------------------------------ - * See whether the specified date is valid. - */ - static bool ValidDate(Uint16 year, Uint8 month, Uint8 day); - - /* ------------------------------------------------------------------------------------------------ - * retrieve the number of days in the specified year. - */ - static Uint16 DaysInYear(Uint16 year) - { - return IsLeapYear(year) ? 366 : 365; - } - - /* ------------------------------------------------------------------------------------------------ - * Retrieve the number of days in the specified month. - */ - static Uint8 DaysInMonth(Uint16 year, Uint8 month); - - /* ------------------------------------------------------------------------------------------------ - * 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 diff --git a/source/Library/Chrono/Datetime.cpp b/source/Library/Chrono/Datetime.cpp index f84d1bd2..b03a2c28 100644 --- a/source/Library/Chrono/Datetime.cpp +++ b/source/Library/Chrono/Datetime.cpp @@ -8,11 +8,782 @@ namespace SqMod { // ------------------------------------------------------------------------------------------------ +SQChar Datetime::Delimiter = ' '; +SQChar Datetime::DateDelim = '-'; +SQChar Datetime::TimeDelim = ':'; + +// ------------------------------------------------------------------------------------------------ +SQInteger Datetime::Typename(HSQUIRRELVM vm) +{ + static const SQChar name[] = _SC("SqDatetime"); + sq_pushstring(vm, name, sizeof(name)); + return 1; +} + +// ------------------------------------------------------------------------------------------------ +Int32 Datetime::Compare(const Datetime & o) const +{ + if (m_Year < o.m_Year) + { + return -1; + } + else if (m_Year > o.m_Year) + { + return 1; + } + else if (m_Month < o.m_Month) + { + return -1; + } + else if (m_Month > o.m_Month) + { + return 1; + } + else if (m_Day < o.m_Day) + { + return -1; + } + else if (m_Day > o.m_Day) + { + return 1; + } + else if (m_Hour < o.m_Hour) + { + return -1; + } + else if (m_Hour > o.m_Hour) + { + return 1; + } + else if (m_Minute < o.m_Minute) + { + return -1; + } + else if (m_Minute > o.m_Minute) + { + return 1; + } + else if (m_Second < o.m_Second) + { + return -1; + } + else if (m_Second > o.m_Second) + { + return 1; + } + else if (m_Millisecond < o.m_Millisecond) + { + return -1; + } + else if (m_Millisecond == o.m_Millisecond) + { + return 0; + } + else + { + return 1; + } +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::operator + (const Datetime & o) const +{ + // Add the components individually + return Datetime(o); +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::operator - (const Datetime & o) const +{ + return Datetime(o); +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::operator * (const Datetime & o) const +{ + return Datetime(o); +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::operator / (const Datetime & o) const +{ + return Datetime(o); +} + +// ------------------------------------------------------------------------------------------------ +CSStr Datetime::ToString() const +{ + return ToStrF("%04u%c%02u%c%02u%c%02u%c%02u%c%02u%c%u" + , m_Year, m_DateDelim, m_Month, m_DateDelim, m_Day + , m_Delimiter + , m_Hour, m_TimeDelim, m_Minute, m_TimeDelim, m_Second , m_TimeDelim, m_Millisecond + ); +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond) +{ + // Validate the specified date + if (!Chrono::ValidDate(year, month, day)) + { + STHROWF("Invalid date: %04u%c%02u%c%02u%c%u" + , m_Delimiter, m_Year + , m_Delimiter, m_Month + , m_Delimiter, m_Day + ); + } + // Is the specified hour within range? + else if (hour >= 24) + { + STHROWF("Hour value is out of range: %u >= 24", hour); + } + // Is the specified minute within range? + else if (minute >= 60) + { + STHROWF("Minute value is out of range: %u >= 60", minute); + } + // Is the specified second within range? + else if (second >= 60) + { + STHROWF("Second value is out of range: %u >= 60", second); + } + // Is the specified millisecond within range? + else if (millisecond >= 1000) + { + STHROWF("Millisecond value is out of range: %u >= 1000", millisecond); + } + // Assign the specified values + m_Year = year; + m_Month = month; + m_Day = day; + m_Hour = hour; + m_Minute = minute; + m_Second = second; + m_Millisecond = millisecond; +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::SetStr(CSStr str) +{ + // The format specifications that will be used to scan the string + static SQChar fs[] = _SC(" %u - %u - %u %u : %u : %u : %u "); + // Is the specified string empty? + if (!str || *str == '\0') + { + // Clear the values + m_Year = 0; + m_Month = 0; + m_Day = 0; + m_Hour = 0; + m_Minute = 0; + m_Second = 0; + m_Millisecond = 0; + // We're done here + return; + } + // Assign the specified delimiter + fs[4] = m_DateDelim; + fs[9] = m_DateDelim; + fs[14] = m_Delimiter; + fs[19] = m_TimeDelim; + fs[24] = m_TimeDelim; + fs[29] = m_TimeDelim; + // The sscanf function requires at least 32 bit integers + Uint32 year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, milli = 0; + // Attempt to extract the component values from the specified string + sscanf(str, fs, &year, &month, &day, &hour, &minute, &second, &milli); + // Clamp the extracted values to the boundaries of associated type and assign them + Set(ClampL< Uint32, Uint8 >(year), + ClampL< Uint32, Uint8 >(month), + ClampL< Uint32, Uint8 >(day), + ClampL< Uint32, Uint8 >(hour), + ClampL< Uint32, Uint8 >(minute), + ClampL< Uint32, Uint8 >(second), + ClampL< Uint32, Uint16 >(milli) + ); +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::SetDayOfYear(Uint16 doy) +{ + // Reverse the given day of year to a full date + Date d = Chrono::ReverseDayOfyear(m_Year, doy); + // Set the obtained month + SetMonth(d.GetMonth()); + // Set the obtained day + SetDay(d.GetDay()); +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::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 (!Chrono::ValidDate(m_Year, m_Month, m_Day)) + { + m_Month = 1; + m_Day = 1; + } +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::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 > Chrono::DaysInMonth(m_Year, m_Month)) + { + m_Month = 1; // Fall back to the beginning of the month + } +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::SetDay(Uint8 day) +{ + // Grab the amount of days in the current month + const Uint8 dim = Chrono::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; +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::SetHour(Uint8 hour) +{ + // Is the specified hour within range? + if (hour >= 24) + { + STHROWF("Hour value is out of range: %u >= 24", hour); + } + // Now it's safe to assign the value + m_Hour = hour; +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::SetMinute(Uint8 minute) +{ + // Is the specified minute within range? + if (minute >= 60) + { + STHROWF("Minute value is out of range: %u >= 60", minute); + } + // Now it's safe to assign the value + m_Minute = minute; +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::SetSecond(Uint8 second) +{ + // Is the specified second within range? + if (second >= 60) + { + STHROWF("Second value is out of range: %u >= 60", second); + } + // Now it's safe to assign the value + m_Second = second; +} + +// ------------------------------------------------------------------------------------------------ +void Datetime::SetMillisecond(Uint16 millisecond) +{ + // Is the specified millisecond within range? + if (millisecond >= 1000) + { + STHROWF("Millisecond value is out of range: %u >= 1000", millisecond); + } + // Now it's safe to assign the value + m_Millisecond = millisecond; +} + +// ------------------------------------------------------------------------------------------------ +Datetime & Datetime::AddYears(Int32 years) +{ + // 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)); + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Datetime & Datetime::AddMonths(Int32 months) +{ + // Do we have a valid amount of months? + if (months) + { + // Extract the number of years + Int32 years = static_cast< Int32 >(months / 12); + // Extract the number of months + months = (months % 12) + m_Month; + // Do we have extra months? + if (months >= 12) + { + // Increase the years + ++years; + // Subtract one year from months + months %= 12; + } + else if (months < 0) + { + // Decrease the years + --years; + // Add one year to months + 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); + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Datetime & Datetime::AddDays(Int32 days) +{ + // Do we have a valid amount of days? + if (days) + { + // Whether the number of days is positive or negative + const Int32 dir = days > 0 ? 1 : -1; + // Grab current year + Int32 year = m_Year; + // Calculate the days in the current year + Int32 diy = Chrono::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 = Chrono::DaysInYear(year); + } + // Set the obtained year + SetYear(year); + // Set the obtained day of year + SetDayOfYear(doy); + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Datetime & Datetime::AddHours(Int32 hours) +{ + // Did we even add any hours? + if (hours) + { + // Extract the number of days + Int32 days = static_cast< Int32 >(hours / 24); + // Extract the number of hours + m_Hour += (hours % 24); + // Are the hours overlapping with the next day? + if (m_Hour >= 24) + { + // Increase the days + ++days; + // Subtract one day from hours + m_Hour %= 24; + } + // Should we add any days? + if (days) + { + AddDays(days); + } + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Datetime & Datetime::AddMinutes(Int32 minutes) +{ + // Did we even add any minutes? + if (minutes) + { + // Extract the number of hours + Int32 hours = static_cast< Int32 >(minutes / 60); + // Extract the number of minutes + m_Minute += (minutes % 60); + // Are the minutes overlapping with the next hour? + if (m_Minute >= 60) + { + // Increase the hours + ++hours; + // Subtract one hour from minutes + m_Minute %= 60; + } + // Should we add any hours? + if (hours) + { + AddHours(hours); + } + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Datetime & Datetime::AddSeconds(Int32 seconds) +{ + // Did we even add any seconds? + if (seconds) + { + // Extract the number of minutes + Int32 minutes = static_cast< Int32 >(seconds / 60); + // Extract the number of seconds + m_Second += (seconds % 60); + // Are the seconds overlapping with the next minute? + if (m_Second >= 60) + { + // Increase the minutes + ++minutes; + // Subtract one minute from seconds + m_Second %= 60; + } + // Should we add any minutes? + if (minutes) + { + AddMinutes(minutes); + } + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Datetime & Datetime::AddMilliseconds(Int32 milliseconds) +{ + // Did we even add any milliseconds? + if (milliseconds) + { + // Extract the number of seconds + Int32 seconds = static_cast< Int32 >(milliseconds / 1000); + // Extract the number of milliseconds + m_Millisecond += (milliseconds / 1000); + // Are the milliseconds overlapping with the next second? + if (m_Millisecond >= 1000) + { + // Increase the seconds + ++seconds; + // Subtract one second from milliseconds + m_Millisecond %= 1000; + } + // Should we add any seconds? + if (seconds) + { + AddSeconds(seconds); + } + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::AndYears(Int32 years) +{ + // Do we have a valid amount of years? + if (!years) + { + return Datetime(*this); // Return the date-time as is + } + // Replicate the current date + Datetime dt(*this); + // Add the specified amount of years + dt.SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years)); + // Return the resulted date + return dt; +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::AndMonths(Int32 months) +{ + // Do we have a valid amount of months? + if (!months) + { + return Datetime(*this); // Return the date-time as is + } + // Extract the number of years + Int32 years = static_cast< Int32 >(months / 12); + // Extract the number of months + months = (months % 12) + m_Month; + // Do we have extra months? + if (months >= 12) + { + // Increase the years + ++years; + // Subtract one year from months + months %= 12; + } + else if (months < 0) + { + // Decrease the years + --years; + // Add one year to months + months = 12 - months; + } + // Replicate the current date + Datetime dt(*this); + // Are there any years to add? + if (years) + { + dt.SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years)); + } + // Add the months + dt.SetMonth(months); + // Return the resulted date + return dt; +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::AndDays(Int32 days) +{ + // Do we have a valid amount of days? + if (!days) + { + return Datetime(*this); // Return the date-time as is + } + // Whether the number of days is positive or negative + const Int32 dir = days > 0 ? 1 : -1; + // Grab current year + Int32 year = m_Year; + // Calculate the days in the current year + Int32 diy = Chrono::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 = Chrono::DaysInYear(year); + } + // Replicate the current date + Datetime dt(*this); + // Set the obtained year + dt.SetYear(year); + // Set the obtained day of year + dt.SetDayOfYear(doy); + // Return the resulted date + return dt; +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::AndHours(Int32 hours) +{ + // Did we even add any hours? + if (!hours) + { + return Datetime(*this); // Return the date-time as is + } + // Extract the number of days + Int32 days = static_cast< Int32 >(hours / 24); + // Extract the number of hours + hours = m_Hour + (hours % 24); + // Are the hours overlapping with the next day? + if (hours >= 24) + { + ++days; // Increase the days + } + // Replicate the current time + Datetime dt(*this); + // Should we add any days? + if (days) + { + dt.AddDays(days); + } + // Assign the resulted hours + dt.m_Hour = (hours % 24); + // Return the result + return dt; +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::AndMinutes(Int32 minutes) +{ + // Did we even added any minutes? + if (!minutes) + { + return Datetime(*this); // Return the date-time as is + } + // Extract the number of hours + Int32 hours = static_cast< Int32 >(minutes / 60); + // Extract the number of minutes + minutes = m_Minute + (minutes % 60); + // Are the minutes overlapping with the next hour? + if (minutes >= 60) + { + ++hours; // Increase hours + } + // Replicate the current time + Datetime dt(*this); + // Should we add any hours? + if (hours) + { + dt.AddHours(hours); + } + // Assign the resulted minutes + dt.m_Minute = (minutes % 60); + // Return the result + return dt; +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::AndSeconds(Int32 seconds) +{ + // Did we even added any seconds? + if (!seconds) + { + return Datetime(*this); // Return the date-time as is + } + // Extract the number of minutes + Int32 minutes = static_cast< Int32 >(seconds / 60); + // Extract the number of seconds + seconds = m_Second + (seconds % 60); + // Are the seconds overlapping with the next minute? + if (seconds >= 60) + { + ++minutes; // Increase minutes + } + // Replicate the current time + Datetime dt(*this); + // Should we add any minutes? + if (minutes) + { + dt.AddMinutes(minutes); + } + // Assign the resulted seconds + dt.m_Second = (seconds % 60); + // Return the result + return dt; +} + +// ------------------------------------------------------------------------------------------------ +Datetime Datetime::AndMilliseconds(Int32 milliseconds) +{ + // Did we even added any milliseconds? + if (!milliseconds) + { + return Datetime(*this); // Return the date-time as is + } + // Extract the number of seconds + Int32 seconds = static_cast< Int32 >(milliseconds / 1000); + // Extract the number of milliseconds + milliseconds = m_Millisecond + (milliseconds % 1000); + // Are the milliseconds overlapping with the next second? + if (milliseconds >= 1000) + { + ++seconds; // Increase seconds + } + // Replicate the current time + Datetime dt(*this); + // Should we add any seconds? + if (seconds) + { + dt.AddSeconds(seconds); + } + // Assign the resulted milliseconds + dt.m_Millisecond = (milliseconds % 1000); + // Return the result + return dt; +} // ================================================================================================ void Register_ChronoDatetime(HSQUIRRELVM vm, Table & /*cns*/) { - + RootTable(vm).Bind(_SC("SqDatetime"), Class< Datetime >(vm, _SC("SqDatetime")) + // Constructors + .Ctor() + .Ctor< Uint16 >() + .Ctor< Uint16, Uint8 >() + .Ctor< Uint16, Uint8, Uint8 >() + .Ctor< Uint16, Uint8, Uint8, Uint8 >() + .Ctor< Uint16, Uint8, Uint8, Uint8, Uint8 >() + .Ctor< Uint16, Uint8, Uint8, Uint8, Uint8, Uint8 >() + .Ctor< Uint16, Uint8, Uint8, Uint8, Uint8, Uint8, Uint16 >() + // Static Properties + .SetStaticValue(_SC("GlobalDelimiter"), &Datetime::Delimiter) + .SetStaticValue(_SC("GlobalDateDelim"), &Datetime::DateDelim) + .SetStaticValue(_SC("GlobalTimeDelim"), &Datetime::TimeDelim) + // Core Meta-methods + .Func(_SC("_tostring"), &Datetime::ToString) + .SquirrelFunc(_SC("_typename"), &Datetime::Typename) + .Func(_SC("_cmp"), &Datetime::Cmp) + // Meta-methods + .Func< Datetime (Datetime::*)(const Datetime &) const >(_SC("_add"), &Datetime::operator +) + .Func< Datetime (Datetime::*)(const Datetime &) const >(_SC("_sub"), &Datetime::operator -) + .Func< Datetime (Datetime::*)(const Datetime &) const >(_SC("_mul"), &Datetime::operator *) + .Func< Datetime (Datetime::*)(const Datetime &) const >(_SC("_div"), &Datetime::operator /) + // Properties + .Prop(_SC("Delimiter"), &Datetime::GetDelimiter, &Datetime::SetDelimiter) + .Prop(_SC("DateDelim"), &Datetime::GetDateDelim, &Datetime::SetDateDelim) + .Prop(_SC("TimeDelim"), &Datetime::GetTimeDelim, &Datetime::SetTimeDelim) + .Prop(_SC("Str"), &Datetime::GetStr, &Datetime::SetStr) + .Prop(_SC("DayOfYear"), &Datetime::GetDayOfYear, &Datetime::SetDayOfYear) + .Prop(_SC("Year"), &Datetime::GetYear, &Datetime::SetYear) + .Prop(_SC("Month"), &Datetime::GetMonth, &Datetime::SetMonth) + .Prop(_SC("Day"), &Datetime::GetDay, &Datetime::SetDay) + .Prop(_SC("Hour"), &Datetime::GetHour, &Datetime::SetHour) + .Prop(_SC("Minute"), &Datetime::GetMinute, &Datetime::SetMinute) + .Prop(_SC("Second"), &Datetime::GetSecond, &Datetime::SetSecond) + .Prop(_SC("Millisecond"), &Datetime::GetMillisecond, &Datetime::SetMillisecond) + .Prop(_SC("LeapYear"), &Datetime::IsThisLeapYear) + .Prop(_SC("YearDays"), &Datetime::GetYearDays) + .Prop(_SC("MonthDays"), &Datetime::GetMonthDays) + // Member Methods + .Func(_SC("AddYears"), &Datetime::AddYears) + .Func(_SC("AddMonths"), &Datetime::AddMonths) + .Func(_SC("AddDays"), &Datetime::AddDays) + .Func(_SC("AddHours"), &Datetime::AddHours) + .Func(_SC("AddMinutes"), &Datetime::AddMinutes) + .Func(_SC("AddSeconds"), &Datetime::AddSeconds) + .Func(_SC("AddMillis"), &Datetime::AddMilliseconds) + .Func(_SC("AddMilliseconds"), &Datetime::AddMilliseconds) + .Func(_SC("AndYears"), &Datetime::AndYears) + .Func(_SC("AndMonths"), &Datetime::AndMonths) + .Func(_SC("AndDays"), &Datetime::AndDays) + .Func(_SC("AndHours"), &Datetime::AndHours) + .Func(_SC("AndMinutes"), &Datetime::AndMinutes) + .Func(_SC("AndSeconds"), &Datetime::AndSeconds) + .Func(_SC("AndMillis"), &Datetime::AndMilliseconds) + .Func(_SC("AndMilliseconds"), &Datetime::AndMilliseconds) + // Overloaded Methods + .Overload< void (Datetime::*)(Uint16) >(_SC("Set"), &Datetime::Set) + .Overload< void (Datetime::*)(Uint16, Uint8) >(_SC("Set"), &Datetime::Set) + .Overload< void (Datetime::*)(Uint16, Uint8, Uint8) >(_SC("Set"), &Datetime::Set) + .Overload< void (Datetime::*)(Uint16, Uint8, Uint8, Uint8) >(_SC("Set"), &Datetime::Set) + .Overload< void (Datetime::*)(Uint16, Uint8, Uint8, Uint8, Uint8) >(_SC("Set"), &Datetime::Set) + .Overload< void (Datetime::*)(Uint16, Uint8, Uint8, Uint8, Uint8, Uint8) >(_SC("Set"), &Datetime::Set) + .Overload< void (Datetime::*)(Uint16, Uint8, Uint8, Uint8, Uint8, Uint8, Uint16) >(_SC("Set"), &Datetime::Set) + ); } } // Namespace:: SqMod diff --git a/source/Library/Chrono/Datetime.hpp b/source/Library/Chrono/Datetime.hpp index 4418fc85..a2f2699f 100644 --- a/source/Library/Chrono/Datetime.hpp +++ b/source/Library/Chrono/Datetime.hpp @@ -2,14 +2,569 @@ #define _LIBRARY_CHRONO_DATETIME_HPP_ // ------------------------------------------------------------------------------------------------ -#include "SqBase.hpp" +#include "Library/Chrono.hpp" // ------------------------------------------------------------------------------------------------ namespace SqMod { /* ------------------------------------------------------------------------------------------------ - * + * Helper class used to represent a certain date and time. */ +class Datetime +{ +public: + + // ------------------------------------------------------------------------------------------------ + static SQChar Delimiter; + static SQChar DateDelim; + static SQChar TimeDelim; + +private: + + // ------------------------------------------------------------------------------------------------ + Uint16 m_Year; // Year + Uint8 m_Month; // Month + Uint8 m_Day; // Day + + // ------------------------------------------------------------------------------------------------ + Uint8 m_Hour; // Hour + Uint8 m_Minute; // Minute + Uint8 m_Second; // Second + Uint16 m_Millisecond; // Millisecond + + // ------------------------------------------------------------------------------------------------ + SQChar m_Delimiter; // Date and time delimiter when generating strings. + SQChar m_DateDelim; // Time component delimiter when generating strings. + SQChar m_TimeDelim; // Date component delimiter when generating strings. + +protected: + + /* ------------------------------------------------------------------------------------------------ + * Compare the values of two instances. + */ + Int32 Compare(const Datetime & o) const; + +public: + + /* ------------------------------------------------------------------------------------------------ + * Default constructor. + */ + Datetime() + : m_Year(1970) + , m_Month(1) + , m_Day(1) + , m_Hour(0) + , m_Minute(0) + , m_Second(0) + , m_Millisecond(0) + , m_Delimiter(Delimiter) + , m_DateDelim(DateDelim) + , m_TimeDelim(TimeDelim) + { + /* ... */ + } + + /* ------------------------------------------------------------------------------------------------ + * Speciffic year constructor. + */ + Datetime(Uint16 year) + : m_Delimiter(Delimiter) + , m_DateDelim(DateDelim) + , m_TimeDelim(TimeDelim) + { + Set(year, 1, 1, 0, 0, 0, 0); + } + + /* ------------------------------------------------------------------------------------------------ + * Speciffic year and month constructor. + */ + Datetime(Uint16 year, Uint8 month) + : m_Delimiter(Delimiter) + , m_DateDelim(DateDelim) + , m_TimeDelim(TimeDelim) + { + Set(year, month, 1, 0, 0, 0, 0); + } + + /* ------------------------------------------------------------------------------------------------ + * Speciffic date constructor. + */ + Datetime(Uint16 year, Uint8 month, Uint8 day) + : m_Delimiter(Delimiter) + , m_DateDelim(DateDelim) + , m_TimeDelim(TimeDelim) + { + Set(year, month, day, 0, 0, 0, 0); + } + + /* ------------------------------------------------------------------------------------------------ + * Speciffic date and hour constructor. + */ + Datetime(Uint16 year, Uint8 month, Uint8 day, Uint8 hour) + : m_Delimiter(Delimiter) + , m_DateDelim(DateDelim) + , m_TimeDelim(TimeDelim) + { + Set(year, month, day, hour, 0, 0, 0); + } + + /* ------------------------------------------------------------------------------------------------ + * Speciffic date, hour and minute constructor. + */ + Datetime(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute) + : m_Delimiter(Delimiter) + , m_DateDelim(DateDelim) + , m_TimeDelim(TimeDelim) + { + Set(year, month, day, hour, minute, 0, 0); + } + + /* ------------------------------------------------------------------------------------------------ + * Speciffic date and time constructor. + */ + Datetime(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second) + : m_Delimiter(Delimiter) + , m_DateDelim(DateDelim) + , m_TimeDelim(TimeDelim) + { + Set(year, month, day, hour, minute, second, 0); + } + + /* ------------------------------------------------------------------------------------------------ + * Speciffic date and precise time constructor. + */ + Datetime(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond) + : m_Delimiter(Delimiter) + , m_DateDelim(DateDelim) + , m_TimeDelim(TimeDelim) + { + Set(year, month, day, hour, minute, second, millisecond); + } + + /* -------------------------------------------------------------------------------------------- + * Copy constructor. + */ + Datetime(const Datetime & o) = default; + + /* -------------------------------------------------------------------------------------------- + * Move constructor. + */ + Datetime(Datetime && o) = default; + + /* -------------------------------------------------------------------------------------------- + * Destructor. + */ + ~Datetime() = default; + + /* -------------------------------------------------------------------------------------------- + * Copy assignment operator. + */ + Datetime & operator = (const Datetime & o) = default; + + /* -------------------------------------------------------------------------------------------- + * Move assignment operator. + */ + Datetime & operator = (Datetime && o) = default; + + /* -------------------------------------------------------------------------------------------- + * Equality comparison operator. + */ + bool operator == (const Datetime & o) const + { + return Compare(o) == 0; + } + + /* -------------------------------------------------------------------------------------------- + * Inequality comparison operator. + */ + bool operator != (const Datetime & o) const + { + return Compare(o) != 0; + } + + /* -------------------------------------------------------------------------------------------- + * Less than comparison operator. + */ + bool operator < (const Datetime & o) const + { + return Compare(o) < 0; + } + + /* -------------------------------------------------------------------------------------------- + * Greater than comparison operator. + */ + bool operator > (const Datetime & o) const + { + return Compare(o) > 0; + } + + /* -------------------------------------------------------------------------------------------- + * Less than or equal comparison operator. + */ + bool operator <= (const Datetime & o) const + { + return Compare(o) <= 0; + } + + /* -------------------------------------------------------------------------------------------- + * Greater than or equal comparison operator. + */ + bool operator >= (const Datetime & o) const + { + return Compare(o) >= 0; + } + + /* -------------------------------------------------------------------------------------------- + * Addition operator. + */ + Datetime operator + (const Datetime & o) const; + + /* -------------------------------------------------------------------------------------------- + * Subtraction operator. + */ + Datetime operator - (const Datetime & o) const; + + /* -------------------------------------------------------------------------------------------- + * Multiplication operator. + */ + Datetime operator * (const Datetime & o) const; + + /* -------------------------------------------------------------------------------------------- + * Division operator. + */ + Datetime operator / (const Datetime & o) const; + + /* -------------------------------------------------------------------------------------------- + * Used by the script engine to compare two instances of this type. + */ + Int32 Cmp(const Datetime & o) const + { + return Compare(o); + } + + /* -------------------------------------------------------------------------------------------- + * Used by the script engine to convert an instance of this type to a string. + */ + CSStr ToString() const; + + /* -------------------------------------------------------------------------------------------- + * Used by the script engine to retrieve the name from instances of this type. + */ + static SQInteger Typename(HSQUIRRELVM vm); + + /* ------------------------------------------------------------------------------------------------ + * Assign the specified values. + */ + void Set(Uint16 year) + { + Set(year, m_Month, m_Day, m_Hour, m_Minute, m_Second, m_Millisecond); + } + + /* ------------------------------------------------------------------------------------------------ + * Assign the specified values. + */ + void Set(Uint16 year, Uint8 month) + { + Set(year, month, m_Day, m_Hour, m_Minute, m_Second, m_Millisecond); + } + + /* ------------------------------------------------------------------------------------------------ + * Assign the specified values. + */ + void Set(Uint16 year, Uint8 month, Uint8 day) + { + Set(year, month, day, m_Hour, m_Minute, m_Second, m_Millisecond); + } + + /* ------------------------------------------------------------------------------------------------ + * Assign the specified values. + */ + void Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour) + { + Set(year, month, day, hour, m_Minute, m_Second, m_Millisecond); + } + + /* ------------------------------------------------------------------------------------------------ + * Assign the specified values. + */ + void Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute) + { + Set(year, month, day, hour, minute, m_Second, m_Millisecond); + } + + /* ------------------------------------------------------------------------------------------------ + * Assign the specified values. + */ + void Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second) + { + Set(year, month, day, hour, minute, second, m_Millisecond); + } + + /* ------------------------------------------------------------------------------------------------ + * Assign the specified values. + */ + void Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond); + + /* ------------------------------------------------------------------------------------------------ + * 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 local date delimiter character. + */ + SQChar GetDateDelim() const + { + return m_DateDelim; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the local date delimiter character. + */ + void SetDateDelim(SQChar c) + { + m_DateDelim = c; + } + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the local time delimiter character. + */ + SQChar GetTimeDelim() const + { + return m_TimeDelim; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the local time delimiter character. + */ + void SetTimeDelim(SQChar c) + { + m_TimeDelim = c; + } + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the values as a string. + */ + CSStr GetStr() const + { + return ToString(); + } + + /* ------------------------------------------------------------------------------------------------ + * Extract the values from a string. + */ + void SetStr(CSStr str); + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the day component. + */ + Uint16 GetDayOfYear() const + { + return Chrono::DayOfYear(m_Year, m_Month, m_Day); + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the day component. + */ + void SetDayOfYear(Uint16 doy); + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the year component. + */ + Uint16 GetYear() const + { + return m_Year; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the year component. + */ + void SetYear(Uint16 year); + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the month component. + */ + Uint8 GetMonth() const + { + return m_Month; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the month component. + */ + void SetMonth(Uint8 month); + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the day component. + */ + Uint8 GetDay() const + { + return m_Day; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the day component. + */ + void SetDay(Uint8 day); + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the hour component. + */ + Uint8 GetHour() const + { + return m_Hour; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the hour component. + */ + void SetHour(Uint8 hour); + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the minute component. + */ + Uint8 GetMinute() const + { + return m_Minute; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the minute component. + */ + void SetMinute(Uint8 minute); + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the second component. + */ + Uint8 GetSecond() const + { + return m_Second; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the second component. + */ + void SetSecond(Uint8 second); + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the millisecond component. + */ + Uint16 GetMillisecond() const + { + return m_Millisecond; + } + + /* ------------------------------------------------------------------------------------------------ + * Modify the millisecond component. + */ + void SetMillisecond(Uint16 millisecond); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of years to the current date. + */ + Datetime & AddYears(Int32 years); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of months to the current date. + */ + Datetime & AddMonths(Int32 months); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of days to the current date. + */ + Datetime & AddDays(Int32 days); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of hours to the current time. + */ + Datetime & AddHours(Int32 hours); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of minutes to the current time. + */ + Datetime & AddMinutes(Int32 minutes); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of seconds to the current time. + */ + Datetime & AddSeconds(Int32 seconds); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of milliseconds to the current time. + */ + Datetime & AddMilliseconds(Int32 milliseconds); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of years to obtain a new date. + */ + Datetime AndYears(Int32 years); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of months to obtain a new date. + */ + Datetime AndMonths(Int32 months); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of days to obtain a new date. + */ + Datetime AndDays(Int32 days); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of hours to obtain a new time. + */ + Datetime AndHours(Int32 hours); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of minutes to obtain a new time. + */ + Datetime AndMinutes(Int32 minutes); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of seconds to obtain a new time. + */ + Datetime AndSeconds(Int32 seconds); + + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of milliseconds to obtain a new time. + */ + Datetime AndMilliseconds(Int32 milliseconds); + + /* ------------------------------------------------------------------------------------------------ + * See whether the associated year is a leap year. + */ + bool IsThisLeapYear() const + { + return Chrono::IsLeapYear(m_Year); + } + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the number of days in the associated year. + */ + Uint16 GetYearDays() const + { + return Chrono::DaysInYear(m_Year); + } + + /* ------------------------------------------------------------------------------------------------ + * Retrieve the number of days in the associated month. + */ + Uint8 GetMonthDays() const + { + return Chrono::DaysInMonth(m_Year, m_Month); + } + +}; } // Namespace:: SqMod diff --git a/source/Library/Chrono/Time.cpp b/source/Library/Chrono/Time.cpp index 5a2eaa94..7b4b1a6f 100644 --- a/source/Library/Chrono/Time.cpp +++ b/source/Library/Chrono/Time.cpp @@ -13,103 +13,11 @@ SQChar Time::Delimiter = ':'; // ------------------------------------------------------------------------------------------------ SQInteger Time::Typename(HSQUIRRELVM vm) { - static const SQChar name[] = _SC("SqChronoTime"); + static const SQChar name[] = _SC("SqTime"); sq_pushstring(vm, name, sizeof(name)); return 1; } -// ------------------------------------------------------------------------------------------------ -Time Time::operator + (const Time & o) const -{ - return Time(o); -} - -// ------------------------------------------------------------------------------------------------ -Time Time::operator - (const Time & o) const -{ - return Time(o); -} - -// ------------------------------------------------------------------------------------------------ -Time Time::operator * (const Time & o) const -{ - return Time(o); -} - -// ------------------------------------------------------------------------------------------------ -Time Time::operator / (const Time & o) const -{ - return Time(o); -} - -// ------------------------------------------------------------------------------------------------ -void Time::Set(Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond) -{ - // Is the specified hour within range? - if (hour >= 24) - { - STHROWF("Hour value is out of range: %u >= 24", hour); - } - // Is the specified minute within range? - else if (minute >= 60) - { - STHROWF("Minute value is out of range: %u >= 60", minute); - } - // Is the specified second within range? - else if (second >= 60) - { - STHROWF("Second value is out of range: %u >= 60", second); - } - // Is the specified millisecond within range? - else if (millisecond >= 1000) - { - STHROWF("Millisecond value is out of range: %u >= 1000", millisecond); - } - // Now it's safe to assign the values - m_Hour = hour; - m_Minute = minute; - m_Second = second; - m_Millisecond = millisecond; -} - -// ------------------------------------------------------------------------------------------------ -CSStr Time::GetStr() const -{ - return ToString(); -} - -// ------------------------------------------------------------------------------------------------ -void Time::SetStr(CSStr str) -{ - // The format specifications that will be used to scan the string - static SQChar fs[] = _SC(" %u , %u , %u, %u "); - // Is the specified string empty? - if (!str || *str == '\0') - { - // Clear the values - m_Hour = 0; - m_Minute = 0; - m_Second = 0; - m_Millisecond = 0; - // We're done here - return; - } - // Assign the specified delimiter - fs[4] = m_Delimiter; - fs[9] = m_Delimiter; - fs[14] = m_Delimiter; - // The sscanf function requires at least 32 bit integers - Uint32 hour = 0, minute = 0, second = 0, milli = 0; - // Attempt to extract the component values from the specified string - sscanf(str, fs, &hour, &minute, &second, &milli); - // Clamp the extracted values to the boundaries of associated type and assign them - Set(ClampL< Uint32, Uint8 >(hour), - ClampL< Uint32, Uint8 >(minute), - ClampL< Uint32, Uint8 >(second), - ClampL< Uint32, Uint16 >(milli) - ); -} - // ------------------------------------------------------------------------------------------------ Int32 Time::Compare(const Time & o) const { @@ -151,14 +59,99 @@ Int32 Time::Compare(const Time & o) const } } +// ------------------------------------------------------------------------------------------------ +Time Time::operator + (const Time & o) const +{ + return Time(o); +} + +// ------------------------------------------------------------------------------------------------ +Time Time::operator - (const Time & o) const +{ + return Time(o); +} + +// ------------------------------------------------------------------------------------------------ +Time Time::operator * (const Time & o) const +{ + return Time(o); +} + +// ------------------------------------------------------------------------------------------------ +Time Time::operator / (const Time & o) const +{ + return Time(o); +} + // ------------------------------------------------------------------------------------------------ CSStr Time::ToString() const { - return ToStrF("%02u%c%02u%c%02u%c%u" - , m_Delimiter, m_Hour - , m_Delimiter, m_Minute - , m_Delimiter, m_Second - , m_Delimiter, m_Millisecond + return ToStrF("%02u%c%02u%c%02u%c%u", + m_Hour, m_Delimiter, + m_Minute, m_Delimiter, + m_Second, m_Delimiter, + m_Millisecond); +} + +// ------------------------------------------------------------------------------------------------ +void Time::Set(Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond) +{ + // Is the specified hour within range? + if (hour >= 24) + { + STHROWF("Hour value is out of range: %u >= 24", hour); + } + // Is the specified minute within range? + else if (minute >= 60) + { + STHROWF("Minute value is out of range: %u >= 60", minute); + } + // Is the specified second within range? + else if (second >= 60) + { + STHROWF("Second value is out of range: %u >= 60", second); + } + // Is the specified millisecond within range? + else if (millisecond >= 1000) + { + STHROWF("Millisecond value is out of range: %u >= 1000", millisecond); + } + // Now it's safe to assign the values + m_Hour = hour; + m_Minute = minute; + m_Second = second; + m_Millisecond = millisecond; +} + +// ------------------------------------------------------------------------------------------------ +void Time::SetStr(CSStr str) +{ + // The format specifications that will be used to scan the string + static SQChar fs[] = _SC(" %u : %u : %u : %u "); + // Is the specified string empty? + if (!str || *str == '\0') + { + // Clear the values + m_Hour = 0; + m_Minute = 0; + m_Second = 0; + m_Millisecond = 0; + // We're done here + return; + } + // Assign the specified delimiter + fs[4] = m_Delimiter; + fs[9] = m_Delimiter; + fs[14] = m_Delimiter; + // The sscanf function requires at least 32 bit integers + Uint32 hour = 0, minute = 0, second = 0, milli = 0; + // Attempt to extract the component values from the specified string + sscanf(str, fs, &hour, &minute, &second, &milli); + // Clamp the extracted values to the boundaries of associated type and assign them + Set(ClampL< Uint32, Uint8 >(hour), + ClampL< Uint32, Uint8 >(minute), + ClampL< Uint32, Uint8 >(second), + ClampL< Uint32, Uint16 >(milli) ); } @@ -211,129 +204,210 @@ void Time::SetMillisecond(Uint16 millisecond) } // ------------------------------------------------------------------------------------------------ -Time Time::AddHours(Int32 hours) +Time & Time::AddHours(Int32 hours) { - // Replicate the current time - Time tm(*this); - // Did we even added any hours? - if (!hours) + // Did we even add any hours? + if (hours) { - return tm; // Return the time as is + // Add the specified amount of hours + m_Hour += (hours % 24); + // Make sure the value is within range + m_Hour %= 24; } - // Add the specified amount of hours - tm.m_Hour = ((hours % 24) + m_Hour); - // Make sure the value is within range - tm.m_Hour %= 24; - // Return the result - return tm; + // Allow chaining operations + return *this; } // ------------------------------------------------------------------------------------------------ -Time Time::AddMinutes(Int32 minutes) +Time & Time::AddMinutes(Int32 minutes) +{ + // Did we even add any minutes? + if (minutes) + { + // Extract the number of hours + Int32 hours = static_cast< Int32 >(minutes / 60); + // Extract the number of minutes + m_Minute += (minutes % 60); + // Are the minutes overlapping with the next hour? + if (m_Minute >= 60) + { + // Increase the hours + ++hours; + // Subtract one hour from minutes + m_Minute %= 60; + } + // Should we add any hours? + if (hours) + { + AddHours(hours); + } + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Time & Time::AddSeconds(Int32 seconds) +{ + // Did we even add any seconds? + if (seconds) + { + // Extract the number of minutes + Int32 minutes = static_cast< Int32 >(seconds / 60); + // Extract the number of seconds + m_Second += (seconds % 60); + // Are the seconds overlapping with the next minute? + if (m_Second >= 60) + { + // Increase the minutes + ++minutes; + // Subtract one minute from seconds + m_Second %= 60; + } + // Should we add any minutes? + if (minutes) + { + AddMinutes(minutes); + } + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Time & Time::AddMilliseconds(Int32 milliseconds) +{ + // Did we even add any milliseconds? + if (milliseconds) + { + // Extract the number of seconds + Int32 seconds = static_cast< Int32 >(milliseconds / 1000); + // Extract the number of milliseconds + m_Millisecond += (milliseconds / 1000); + // Are the milliseconds overlapping with the next second? + if (m_Millisecond >= 1000) + { + // Increase the seconds + ++seconds; + // Subtract one second from milliseconds + m_Millisecond %= 1000; + } + // Should we add any seconds? + if (seconds) + { + AddSeconds(seconds); + } + } + // Allow chaining operations + return *this; +} + +// ------------------------------------------------------------------------------------------------ +Time Time::AndHours(Int32 hours) +{ + // Did we even add any hours? + if (hours) + { + return Time((m_Hour + (hours % 24)) % 24, m_Minute, m_Second, m_Millisecond); + } + // Return the time as is + return Time(*this); +} + +// ------------------------------------------------------------------------------------------------ +Time Time::AndMinutes(Int32 minutes) { - // Replicate the current time - Time tm(*this); // Did we even added any minutes? if (!minutes) { - return tm; // Return the time as is + return Time(*this); // Return the time as is } // Extract the number of hours - Int32 hours = minutes / 60; + Int32 hours = static_cast< Int32 >(minutes / 60); // Extract the number of minutes - minutes = (minutes % 60) + m_Minute; - // Make sure the value is within range + minutes = m_Minute + (minutes % 60); + // Are the minutes overlapping with the next hour? if (minutes >= 60) { - // Increase hours - ++hours; - // Subtract from minutes - minutes %= 60; + ++hours; // Increase hours } - // Do we have any hours? - if (hours > 0) + // Replicate the current time + Time t(*this); + // Should we add any hours? + if (hours) { - // Add the hours - tm = tm.AddHours(hours); + t.AddHours(hours); } // Assign the resulted minutes - tm.m_Minute = minutes; + t.m_Minute = (minutes % 60); // Return the result - return tm; + return t; } // ------------------------------------------------------------------------------------------------ -Time Time::AddSeconds(Int32 seconds) +Time Time::AndSeconds(Int32 seconds) { - // Replicate the current time - Time tm(*this); // Did we even added any seconds? if (!seconds) { - return tm; // Return the time as is + return Time(*this); // Return the time as is } // Extract the number of minutes - Int32 minutes = seconds / 60; + Int32 minutes = static_cast< Int32 >(seconds / 60); // Extract the number of seconds - seconds = (seconds % 60) + m_Second; - // Make sure the value is within range + seconds = m_Second + (seconds % 60); + // Are the seconds overlapping with the next minute? if (seconds >= 60) { - // Increase minutes - ++minutes; - // Subtract from seconds - seconds %= 60; + ++minutes; // Increase minutes } - // Do we have any minutes? - if (minutes > 0) + // Replicate the current time + Time t(*this); + // Should we add any minutes? + if (minutes) { - // Add the minutes - tm = tm.AddMinutes(minutes); + t.AddMinutes(minutes); } // Assign the resulted seconds - tm.m_Second = seconds; + t.m_Second = (seconds % 60); // Return the result - return tm; + return t; } // ------------------------------------------------------------------------------------------------ -Time Time::AddMilliseconds(Int32 milliseconds) +Time Time::AndMilliseconds(Int32 milliseconds) { - // Replicate the current time - Time tm(*this); // Did we even added any milliseconds? if (!milliseconds) { - return tm; // Return the time as is + return Time(*this); // Return the time as is } // Extract the number of seconds - Int32 seconds = milliseconds / 1000; + Int32 seconds = static_cast< Int32 >(milliseconds / 1000); // Extract the number of milliseconds - milliseconds = (milliseconds % 1000) + m_Millisecond; - // Make sure the value is within range + milliseconds = m_Millisecond + (milliseconds % 1000); + // Are the milliseconds overlapping with the next second? if (milliseconds >= 1000) { - // Increase seconds - ++seconds; - // Subtract from milliseconds - milliseconds %= 1000; + ++seconds; // Increase seconds } - // Do we have any seconds? - if (seconds > 0) + // Replicate the current time + Time t(*this); + // Should we add any seconds? + if (seconds) { - // Add the seconds - tm = tm.AddSeconds(seconds); + t.AddSeconds(seconds); } // Assign the resulted milliseconds - tm.m_Millisecond = milliseconds; + t.m_Millisecond = (milliseconds % 1000); // Return the result - return tm; + return t; } // ================================================================================================ void Register_ChronoTime(HSQUIRRELVM vm, Table & /*cns*/) { - RootTable(vm).Bind(_SC("SqTime"), Class< Time >(vm, _SC("SqChronoTime")) + RootTable(vm).Bind(_SC("SqTime"), Class< Time >(vm, _SC("SqTime")) // Constructors .Ctor() .Ctor< Uint8 >() @@ -352,18 +426,23 @@ void Register_ChronoTime(HSQUIRRELVM vm, Table & /*cns*/) .Func< Time (Time::*)(const Time &) const >(_SC("_mul"), &Time::operator *) .Func< Time (Time::*)(const Time &) const >(_SC("_div"), &Time::operator /) // Properties + .Prop(_SC("Delimiter"), &Time::GetDelimiter, &Time::SetDelimiter) + .Prop(_SC("Str"), &Time::GetStr, &Time::SetStr) .Prop(_SC("Hour"), &Time::GetHour, &Time::SetHour) .Prop(_SC("Minute"), &Time::GetMinute, &Time::SetMinute) .Prop(_SC("Second"), &Time::GetSecond, &Time::SetSecond) .Prop(_SC("Millisecond"), &Time::GetMillisecond, &Time::SetMillisecond) - .Prop(_SC("Str"), &Time::GetStr, &Time::SetStr) - .Prop(_SC("Delimiter"), &Date::GetDelimiter, &Date::SetDelimiter) // Member Methods .Func(_SC("AddHours"), &Time::AddHours) .Func(_SC("AddMinutes"), &Time::AddMinutes) .Func(_SC("AddSeconds"), &Time::AddSeconds) .Func(_SC("AddMillis"), &Time::AddMilliseconds) .Func(_SC("AddMilliseconds"), &Time::AddMilliseconds) + .Func(_SC("AndHours"), &Time::AndHours) + .Func(_SC("AndMinutes"), &Time::AndMinutes) + .Func(_SC("AndSeconds"), &Time::AndSeconds) + .Func(_SC("AndMillis"), &Time::AndMilliseconds) + .Func(_SC("AndMilliseconds"), &Time::AndMilliseconds) // Overloaded Methods .Overload< void (Time::*)(Uint8) >(_SC("Set"), &Time::Set) .Overload< void (Time::*)(Uint8, Uint8) >(_SC("Set"), &Time::Set) diff --git a/source/Library/Chrono/Time.hpp b/source/Library/Chrono/Time.hpp index e9babd26..3a0b1a4a 100644 --- a/source/Library/Chrono/Time.hpp +++ b/source/Library/Chrono/Time.hpp @@ -2,7 +2,7 @@ #define _LIBRARY_CHRONO_TIME_HPP_ // ------------------------------------------------------------------------------------------------ -#include "SqBase.hpp" +#include "Library/Chrono.hpp" // ------------------------------------------------------------------------------------------------ namespace SqMod { @@ -17,6 +17,26 @@ public: // ------------------------------------------------------------------------------------------------ static SQChar Delimiter; +protected: + + /* ------------------------------------------------------------------------------------------------ + * Compare the values of two instances. + */ + Int32 Compare(const Time & o) const; + +private: + + // ------------------------------------------------------------------------------------------------ + Uint8 m_Hour; // Hour + Uint8 m_Minute; // Minute + Uint8 m_Second; // Second + Uint16 m_Millisecond; // Millisecond + + // ------------------------------------------------------------------------------------------------ + SQChar m_Delimiter; // Component delimiter when generating strings. + +public: + /* ------------------------------------------------------------------------------------------------ * Default constructor. */ @@ -186,22 +206,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. */ @@ -231,10 +235,29 @@ public: */ void Set(Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond); + /* ------------------------------------------------------------------------------------------------ + * 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 values as a string. */ - CSStr GetStr() const; + CSStr GetStr() const + { + return ToString(); + } /* ------------------------------------------------------------------------------------------------ * Extract the values from a string. @@ -294,42 +317,44 @@ public: void SetMillisecond(Uint16 millisecond); /* ------------------------------------------------------------------------------------------------ - * Add the specified amount of hours. + * Add the specified amount of hours to the current time. */ - Time AddHours(Int32 hours); + Time & AddHours(Int32 hours); /* ------------------------------------------------------------------------------------------------ - * Add the specified amount of minutes. + * Add the specified amount of minutes to the current time. */ - Time AddMinutes(Int32 minutes); + Time & AddMinutes(Int32 minutes); /* ------------------------------------------------------------------------------------------------ - * Add the specified amount of seconds. + * Add the specified amount of seconds to the current time. */ - Time AddSeconds(Int32 seconds); + Time & AddSeconds(Int32 seconds); /* ------------------------------------------------------------------------------------------------ - * Add the specified amount of milliseconds. + * Add the specified amount of milliseconds to the current time. */ - Time AddMilliseconds(Int32 milliseconds); - -protected: + Time & AddMilliseconds(Int32 milliseconds); /* ------------------------------------------------------------------------------------------------ - * Compare the values of two instances. + * Add the specified amount of hours to obtain a new time. */ - Int32 Compare(const Time & o) const; + Time AndHours(Int32 hours); -private: + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of minutes to obtain a new time. + */ + Time AndMinutes(Int32 minutes); - // ------------------------------------------------------------------------------------------------ - Uint8 m_Hour; // Hour - Uint8 m_Minute; // Minute - Uint8 m_Second; // Second - Uint16 m_Millisecond; // Millisecond + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of seconds to obtain a new time. + */ + Time AndSeconds(Int32 seconds); - // ------------------------------------------------------------------------------------------------ - SQChar m_Delimiter; // Component selimiter when generating strings. + /* ------------------------------------------------------------------------------------------------ + * Add the specified amount of milliseconds to obtain a new time. + */ + Time AndMilliseconds(Int32 milliseconds); }; } // Namespace:: SqMod diff --git a/source/Library/Chrono/Timer.cpp b/source/Library/Chrono/Timer.cpp index 0d19f848..0b2f5633 100644 --- a/source/Library/Chrono/Timer.cpp +++ b/source/Library/Chrono/Timer.cpp @@ -1,7 +1,6 @@ // ------------------------------------------------------------------------------------------------ #include "Library/Chrono/Timer.hpp" #include "Library/Chrono/Timestamp.hpp" -#include "Library/Chrono.hpp" #include "Base/Shared.hpp" // ------------------------------------------------------------------------------------------------ @@ -9,7 +8,7 @@ namespace SqMod { // ------------------------------------------------------------------------------------------------ Timer::Timer() - : m_Timestamp(GetCurrentSysTime()) + : m_Timestamp(Chrono::GetCurrentSysTime()) { /* ... */ } @@ -34,13 +33,13 @@ CSStr Timer::ToString() const // ------------------------------------------------------------------------------------------------ void Timer::Reset() { - m_Timestamp = GetCurrentSysTime(); + m_Timestamp = Chrono::GetCurrentSysTime(); } // ------------------------------------------------------------------------------------------------ Timestamp Timer::Restart() { - const Int64 now = GetCurrentSysTime(), elapsed = now - m_Timestamp; + const Int64 now = Chrono::GetCurrentSysTime(), elapsed = now - m_Timestamp; m_Timestamp = now; return Timestamp(elapsed); } @@ -48,7 +47,7 @@ Timestamp Timer::Restart() // ------------------------------------------------------------------------------------------------ Int64 Timer::RestartRaw() { - const Int64 now = GetCurrentSysTime(), elapsed = now - m_Timestamp; + const Int64 now = Chrono::GetCurrentSysTime(), elapsed = now - m_Timestamp; m_Timestamp = now; return elapsed; } @@ -56,13 +55,13 @@ Int64 Timer::RestartRaw() // ------------------------------------------------------------------------------------------------ Timestamp Timer::GetElapsedTime() const { - return Timestamp(GetCurrentSysTime() - m_Timestamp); + return Timestamp(Chrono::GetCurrentSysTime() - m_Timestamp); } // ------------------------------------------------------------------------------------------------ Int64 Timer::GetElapsedTimeRaw() const { - return (GetCurrentSysTime() - m_Timestamp); + return (Chrono::GetCurrentSysTime() - m_Timestamp); } // ================================================================================================ diff --git a/source/Library/Chrono/Timer.hpp b/source/Library/Chrono/Timer.hpp index 038569fe..3bbae349 100644 --- a/source/Library/Chrono/Timer.hpp +++ b/source/Library/Chrono/Timer.hpp @@ -2,7 +2,7 @@ #define _LIBRARY_CHRONO_TIMER_HPP_ // ------------------------------------------------------------------------------------------------ -#include "SqBase.hpp" +#include "Library/Chrono.hpp" // ------------------------------------------------------------------------------------------------ namespace SqMod { diff --git a/source/Library/Chrono/Timestamp.cpp b/source/Library/Chrono/Timestamp.cpp index ed710641..476ec97e 100644 --- a/source/Library/Chrono/Timestamp.cpp +++ b/source/Library/Chrono/Timestamp.cpp @@ -1,7 +1,6 @@ // ------------------------------------------------------------------------------------------------ #include "Library/Chrono/Timestamp.hpp" #include "Library/Chrono/Timer.hpp" -#include "Library/Chrono.hpp" #include "Library/Numeric.hpp" #include "Base/Shared.hpp" @@ -35,7 +34,7 @@ CSStr Timestamp::ToString() const // ------------------------------------------------------------------------------------------------ void Timestamp::SetNow() { - m_Timestamp = GetCurrentSysTime(); + m_Timestamp = Chrono::GetCurrentSysTime(); } // ------------------------------------------------------------------------------------------------ @@ -65,7 +64,7 @@ void Timestamp::SetMilliseconds(const SLongInt & ammount) // ------------------------------------------------------------------------------------------------ static Timestamp SqGetEpochTimeNow() { - return Timestamp(GetEpochTimeMicro()); + return Timestamp(Chrono::GetEpochTimeMicro()); } // ------------------------------------------------------------------------------------------------ diff --git a/source/Library/Chrono/Timestamp.hpp b/source/Library/Chrono/Timestamp.hpp index 3be7506b..88ee0dd2 100644 --- a/source/Library/Chrono/Timestamp.hpp +++ b/source/Library/Chrono/Timestamp.hpp @@ -2,7 +2,7 @@ #define _LIBRARY_CHRONO_TIMESTAMP_HPP_ // ------------------------------------------------------------------------------------------------ -#include "SqBase.hpp" +#include "Library/Chrono.hpp" // ------------------------------------------------------------------------------------------------ namespace SqMod { diff --git a/source/Routine.cpp b/source/Routine.cpp index 38217ab0..06e0a914 100644 --- a/source/Routine.cpp +++ b/source/Routine.cpp @@ -28,14 +28,14 @@ void Routine::Process() // Is this the first call? if (s_Last == 0) { - s_Last = GetCurrentSysTime(); + s_Last = Chrono::GetCurrentSysTime(); // We'll do it text time return; } // Backup the last known time-stamp s_Prev = s_Last; // Get the current time-stamp - s_Last = GetCurrentSysTime(); + s_Last = Chrono::GetCurrentSysTime(); // Calculate the elapsed time const Int32 delta = Int32((s_Last - s_Prev) / 1000L); // Process all active routines