Replace lookup-based time logic with direct epoch calculation formulas
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in -59m29s
Builds / ExectOS (amd64, release) (push) Successful in -59m30s
Builds / ExectOS (i686, debug) (push) Successful in -59m27s
Builds / ExectOS (i686, release) (push) Successful in -59m29s

This commit is contained in:
2026-04-24 23:27:25 +02:00
parent 8ab3ddb8eb
commit 439ea891ca
3 changed files with 60 additions and 34 deletions

View File

@@ -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,

View File

@@ -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}
};

View File

@@ -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;