Replace lookup-based time logic with direct epoch calculation formulas
All checks were successful
All checks were successful
This commit is contained in:
@@ -19,7 +19,6 @@ namespace RTL
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
STATIC CUSHORT DaysInMonth[2][12];
|
STATIC CUSHORT DaysInMonth[2][12];
|
||||||
STATIC CUSHORT DaysPrecedingMonth[2][12];
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STATIC XTAPI XTSTATUS TimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields,
|
STATIC XTAPI XTSTATUS TimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
|||||||
@@ -17,9 +17,3 @@ CUSHORT RTL::Time::DaysInMonth[2][12] = {
|
|||||||
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||||
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Lookup table for days preceding a month, Index 0 is normal year, Index 1 is leap year */
|
|
||||||
CUSHORT RTL::Time::DaysPrecedingMonth[2][12] = {
|
|
||||||
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
|
|
||||||
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -45,23 +45,49 @@ XTSTATUS
|
|||||||
RTL::Time::TimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields,
|
RTL::Time::TimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
OUT PLONGLONG UnixTime)
|
OUT PLONGLONG UnixTime)
|
||||||
{
|
{
|
||||||
LONGLONG TotalSeconds;
|
LONGLONG ElapsedDays, TotalSeconds;
|
||||||
LARGE_INTEGER XtTime;
|
LONG Month, Year;
|
||||||
XTSTATUS Status;
|
ULONG Leap;
|
||||||
|
|
||||||
/* Convert to XT Epoch */
|
/* Check leap year */
|
||||||
Status = TimeFieldsToXtEpoch(TimeFields, &XtTime);
|
Leap = LeapYear(TimeFields->Year) ? 1 : 0;
|
||||||
if(Status != STATUS_SUCCESS)
|
|
||||||
|
/* 2. Validate input data */
|
||||||
|
if(TimeFields->Hour < 0 || TimeFields->Hour > 23 ||
|
||||||
|
TimeFields->Minute < 0 || TimeFields->Minute > 59 ||
|
||||||
|
TimeFields->Second < 0 || TimeFields->Second > 59 ||
|
||||||
|
TimeFields->Year < 0 || TimeFields->Year > 30827 ||
|
||||||
|
TimeFields->Month < 1 || TimeFields->Month > 12 ||
|
||||||
|
TimeFields->Day < 1 || TimeFields->Day > DaysInMonth[Leap][TimeFields->Month - 1])
|
||||||
{
|
{
|
||||||
/* Failed to convert to XT Epoch, return error code */
|
/* Invalid input data, return error code */
|
||||||
return Status;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert 100-nanosecond intervals (TICKS) to whole seconds */
|
/* Copy year and month */
|
||||||
TotalSeconds = XtTime.QuadPart / TIME_TICKS_PER_SECOND;
|
Year = (LONG)TimeFields->Year;
|
||||||
|
Month = (LONG)TimeFields->Month;
|
||||||
|
|
||||||
/* Subtract the number of seconds between January 1, 1601 and January 1, 1970 */
|
/* Put February at the end of the calculation cycle, making leap day handling implicit in the year division */
|
||||||
*UnixTime = TotalSeconds - 11644473600LL;
|
if(0 >= (LONG)(Month -= 2))
|
||||||
|
{
|
||||||
|
/* Adjust month and year */
|
||||||
|
Month += 12;
|
||||||
|
Year -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate absolute elapsed days */
|
||||||
|
ElapsedDays = (LONGLONG)(Year/4 - Year/100 + Year/400 + 367*Month/12 + TimeFields->Day) +
|
||||||
|
(LONGLONG)Year*365 - 719499LL;
|
||||||
|
|
||||||
|
/* Calculate total seconds */
|
||||||
|
TotalSeconds = (ElapsedDays * TIME_SECONDS_PER_DAY) +
|
||||||
|
((LONGLONG)TimeFields->Hour * TIME_SECONDS_PER_HOUR) +
|
||||||
|
((LONGLONG)TimeFields->Minute * TIME_SECONDS_PER_MINUTE) +
|
||||||
|
(LONGLONG)TimeFields->Second;
|
||||||
|
|
||||||
|
/* Output the final Unix timestamp */
|
||||||
|
*UnixTime = TotalSeconds;
|
||||||
|
|
||||||
/* Return success */
|
/* Return success */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@@ -86,8 +112,9 @@ XTSTATUS
|
|||||||
RTL::Time::TimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields,
|
RTL::Time::TimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
OUT PLARGE_INTEGER XtTime)
|
OUT PLARGE_INTEGER XtTime)
|
||||||
{
|
{
|
||||||
ULONG Leap, ElapsedYears, ElapsedDays;
|
LONGLONG ElapsedDays, TotalSeconds;
|
||||||
ULONGLONG TotalSeconds;
|
LONG Month, Year;
|
||||||
|
ULONG Leap;
|
||||||
|
|
||||||
/* Check leap year */
|
/* Check leap year */
|
||||||
Leap = LeapYear(TimeFields->Year) ? 1 : 0;
|
Leap = LeapYear(TimeFields->Year) ? 1 : 0;
|
||||||
@@ -105,25 +132,31 @@ RTL::Time::TimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields,
|
|||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate days elapsed in previous years */
|
/* Copy year and month */
|
||||||
ElapsedYears = (ULONG)(TimeFields->Year - 1601);
|
Year = (LONG)TimeFields->Year;
|
||||||
ElapsedDays = (ElapsedYears * 365) + (ElapsedYears / 4) - (ElapsedYears / 100) + (ElapsedYears / 400);
|
Month = (LONG)TimeFields->Month;
|
||||||
|
|
||||||
/* Add days elapsed in previous months of the current year */
|
/* Put February at the end of the calculation cycle, making leap day handling implicit in the year division */
|
||||||
ElapsedDays += DaysPrecedingMonth[Leap][TimeFields->Month - 1];
|
if(0 >= (LONG)(Month -= 2))
|
||||||
|
{
|
||||||
|
/* Adjust month and year */
|
||||||
|
Month += 12;
|
||||||
|
Year -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add days elapsed in the current month */
|
/* Calculate absolute elapsed days */
|
||||||
ElapsedDays += (TimeFields->Day - 1);
|
ElapsedDays = (LONGLONG)(Year/4 - Year/100 + Year/400 + 367*Month/12 + TimeFields->Day) +
|
||||||
|
(LONGLONG)Year*365 - 584725LL;
|
||||||
|
|
||||||
/* Calculate a total number of seconds */
|
/* Calculate total seconds */
|
||||||
TotalSeconds = ((ULONGLONG)ElapsedDays * TIME_SECONDS_PER_DAY) +
|
TotalSeconds = (ElapsedDays * TIME_SECONDS_PER_DAY) +
|
||||||
((ULONGLONG)TimeFields->Hour * TIME_SECONDS_PER_HOUR) +
|
((LONGLONG)TimeFields->Hour * TIME_SECONDS_PER_HOUR) +
|
||||||
((ULONGLONG)TimeFields->Minute * TIME_SECONDS_PER_MINUTE) +
|
((LONGLONG)TimeFields->Minute * TIME_SECONDS_PER_MINUTE) +
|
||||||
(ULONGLONG)TimeFields->Second;
|
(LONGLONG)TimeFields->Second;
|
||||||
|
|
||||||
/* Convert to 100-ns intervals and slap milliseconds on top */
|
/* Convert to 100-ns intervals and slap milliseconds on top */
|
||||||
XtTime->QuadPart = (TotalSeconds * TIME_TICKS_PER_SECOND) +
|
XtTime->QuadPart = (TotalSeconds * TIME_TICKS_PER_SECOND) +
|
||||||
((ULONGLONG)TimeFields->Milliseconds * TIME_TICKS_PER_MILLISECOND);
|
((LONGLONG)TimeFields->Milliseconds * TIME_TICKS_PER_MILLISECOND);
|
||||||
|
|
||||||
/* Return success */
|
/* Return success */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|||||||
Reference in New Issue
Block a user