Implement time conversion routines for Unix and XT epoch formats
This commit is contained in:
@@ -297,6 +297,18 @@ BOOLEAN
|
|||||||
RtlTestBit(IN PRTL_BITMAP BitMap,
|
RtlTestBit(IN PRTL_BITMAP BitMap,
|
||||||
IN ULONG_PTR Bit);
|
IN ULONG_PTR Bit);
|
||||||
|
|
||||||
|
XTCLINK
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
RtlTimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
OUT PLONGLONG UnixTime);
|
||||||
|
|
||||||
|
XTCLINK
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
RtlTimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
OUT PLARGE_INTEGER XtTime);
|
||||||
|
|
||||||
XTCLINK
|
XTCLINK
|
||||||
XTAPI
|
XTAPI
|
||||||
PCHAR
|
PCHAR
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <rtl/sha1.hh>
|
#include <rtl/sha1.hh>
|
||||||
#include <rtl/slist.hh>
|
#include <rtl/slist.hh>
|
||||||
#include <rtl/string.hh>
|
#include <rtl/string.hh>
|
||||||
|
#include <rtl/time.hh>
|
||||||
#include <rtl/widestr.hh>
|
#include <rtl/widestr.hh>
|
||||||
|
|
||||||
#endif /* __XTOSKRNL_RTL_HH */
|
#endif /* __XTOSKRNL_RTL_HH */
|
||||||
|
|||||||
36
xtoskrnl/includes/rtl/time.hh
Normal file
36
xtoskrnl/includes/rtl/time.hh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtoskrnl/includes/rtl/time.hh
|
||||||
|
* DESCRIPTION: Time conversion support
|
||||||
|
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XTOSKRNL_RTL_TIME_HH
|
||||||
|
#define __XTOSKRNL_RTL_TIME_HH
|
||||||
|
|
||||||
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/* Runtime Library */
|
||||||
|
namespace RTL
|
||||||
|
{
|
||||||
|
class Time
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
STATIC CUSHORT DaysInMonth[2][12];
|
||||||
|
STATIC CUSHORT DaysPrecedingMonth[2][12];
|
||||||
|
|
||||||
|
public:
|
||||||
|
STATIC XTAPI XTSTATUS TimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
OUT PLONGLONG UnixTime);
|
||||||
|
STATIC XTAPI XTSTATUS TimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
OUT PLARGE_INTEGER XtTime);
|
||||||
|
|
||||||
|
private:
|
||||||
|
STATIC XTFASTCALL BOOLEAN LeapYear(SHORT Year);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __XTOSKRNL_RTL_TIME_HH */
|
||||||
@@ -11,3 +11,15 @@
|
|||||||
|
|
||||||
/* This is required for floating numbers to keep LLVM happy */
|
/* This is required for floating numbers to keep LLVM happy */
|
||||||
XTCLINK INT _fltused = 0xFEEDBULL;
|
XTCLINK INT _fltused = 0xFEEDBULL;
|
||||||
|
|
||||||
|
/* Lookup table for days in a month, Index 0 is normal year, Index 1 is leap year */
|
||||||
|
CUSHORT RTL::Time::DaysInMonth[2][12] = {
|
||||||
|
{31, 28, 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}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1033,6 +1033,52 @@ RtlTestBit(IN PRTL_BITMAP BitMap,
|
|||||||
return RTL::BitMap::TestBit(BitMap, Bit);
|
return RTL::BitMap::TestBit(BitMap, Bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a TIME_FIELDS calendar structure to a 64-bit Unix timestamp.
|
||||||
|
*
|
||||||
|
* @param TimeFields
|
||||||
|
* Supplies a pointer to a fully populated TIME_FIELDS structure.
|
||||||
|
*
|
||||||
|
* @param UnixTime
|
||||||
|
* Supplies a pointer to a 64-bit integer that receives the number of
|
||||||
|
* seconds elapsed since January 1, 1970.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCLINK
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
RtlTimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
OUT PLONGLONG UnixTime)
|
||||||
|
{
|
||||||
|
return RTL::Time::TimeFieldsToUnixEpoch(TimeFields, UnixTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a TIME_FIELDS calendar structure to a 64-bit XT timestamp.
|
||||||
|
*
|
||||||
|
* @param TimeFields
|
||||||
|
* Supplies a pointer to a fully populated TIME_FIELDS structure.
|
||||||
|
*
|
||||||
|
* @param Time
|
||||||
|
* Supplies a pointer to variable that receives the converted time value in 100-nanosecond
|
||||||
|
* intervals since January 1, 1601.
|
||||||
|
*
|
||||||
|
* @return This routine returns the status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCLINK
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
RtlTimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
OUT PLARGE_INTEGER XtTime)
|
||||||
|
{
|
||||||
|
return RTL::Time::TimeFieldsToXtEpoch(TimeFields, XtTime);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the next token in a NULL-terminated string.
|
* Finds the next token in a NULL-terminated string.
|
||||||
*
|
*
|
||||||
|
|||||||
129
xtoskrnl/rtl/time.cc
Normal file
129
xtoskrnl/rtl/time.cc
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtoskrnl/rtl/time.cc
|
||||||
|
* DESCRIPTION: Time conversion support
|
||||||
|
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a given year is a leap year in the Gregorian calendar.
|
||||||
|
*
|
||||||
|
* @param Year
|
||||||
|
* Supplies the year to be checked.
|
||||||
|
*
|
||||||
|
* @return This routine returns TRUE if the year is a leap year, FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
BOOLEAN
|
||||||
|
RTL::Time::LeapYear(SHORT Year)
|
||||||
|
{
|
||||||
|
return ((Year % 4 == 0 && Year % 100 != 0) || (Year % 400 == 0)) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a TIME_FIELDS calendar structure to a 64-bit Unix timestamp.
|
||||||
|
*
|
||||||
|
* @param TimeFields
|
||||||
|
* Supplies a pointer to a fully populated TIME_FIELDS structure.
|
||||||
|
*
|
||||||
|
* @param UnixTime
|
||||||
|
* Supplies a pointer to a 64-bit integer that receives the number of
|
||||||
|
* seconds elapsed since January 1, 1970.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
RTL::Time::TimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
OUT PLONGLONG UnixTime)
|
||||||
|
{
|
||||||
|
LONGLONG TotalSeconds;
|
||||||
|
LARGE_INTEGER XtTime;
|
||||||
|
XTSTATUS Status;
|
||||||
|
|
||||||
|
/* Convert to XT Epoch */
|
||||||
|
Status = TimeFieldsToXtEpoch(TimeFields, &XtTime);
|
||||||
|
if(Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to convert to XT Epoch, return error code */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert 100-nanosecond intervals (TICKS) to whole seconds */
|
||||||
|
TotalSeconds = XtTime.QuadPart / TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
/* Subtract the number of seconds between January 1, 1601 and January 1, 1970 */
|
||||||
|
*UnixTime = TotalSeconds - 11644473600LL;
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a TIME_FIELDS calendar structure to a 64-bit XT timestamp.
|
||||||
|
*
|
||||||
|
* @param TimeFields
|
||||||
|
* Supplies a pointer to a fully populated TIME_FIELDS structure.
|
||||||
|
*
|
||||||
|
* @param Time
|
||||||
|
* Supplies a pointer to variable that receives the converted time value in 100-nanosecond
|
||||||
|
* intervals since January 1, 1601.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
RTL::Time::TimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields,
|
||||||
|
OUT PLARGE_INTEGER XtTime)
|
||||||
|
{
|
||||||
|
ULONG Leap, ElapsedYears, ElapsedDays;
|
||||||
|
ULONGLONG TotalSeconds;
|
||||||
|
|
||||||
|
/* Check leap year */
|
||||||
|
Leap = LeapYear(TimeFields->Year) ? 1 : 0;
|
||||||
|
|
||||||
|
/* Validate input data */
|
||||||
|
if(TimeFields->Hour < 0 || TimeFields->Hour > 23 ||
|
||||||
|
TimeFields->Minute < 0 || TimeFields->Minute > 59 ||
|
||||||
|
TimeFields->Second < 0 || TimeFields->Second > 59 ||
|
||||||
|
TimeFields->Milliseconds < 0 || TimeFields->Milliseconds > 999 ||
|
||||||
|
TimeFields->Year < 1601 || TimeFields->Year > 30827 ||
|
||||||
|
TimeFields->Month < 1 || TimeFields->Month > 12 ||
|
||||||
|
TimeFields->Day < 1 || TimeFields->Day > DaysInMonth[Leap][TimeFields->Month - 1])
|
||||||
|
{
|
||||||
|
/* Invalid input data, return error code */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate days elapsed in previous years */
|
||||||
|
ElapsedYears = (ULONG)(TimeFields->Year - 1601);
|
||||||
|
ElapsedDays = (ElapsedYears * 365) + (ElapsedYears / 4) - (ElapsedYears / 100) + (ElapsedYears / 400);
|
||||||
|
|
||||||
|
/* Add days elapsed in previous months of the current year */
|
||||||
|
ElapsedDays += DaysPrecedingMonth[Leap][TimeFields->Month - 1];
|
||||||
|
|
||||||
|
/* Add days elapsed in the current month */
|
||||||
|
ElapsedDays += (TimeFields->Day - 1);
|
||||||
|
|
||||||
|
/* Calculate a total number of seconds */
|
||||||
|
TotalSeconds = ((ULONGLONG)ElapsedDays * SECONDS_PER_DAY) +
|
||||||
|
((ULONGLONG)TimeFields->Hour * SECONDS_PER_HOUR) +
|
||||||
|
((ULONGLONG)TimeFields->Minute * SECONDS_PER_MINUTE) +
|
||||||
|
(ULONGLONG)TimeFields->Second;
|
||||||
|
|
||||||
|
/* Convert to 100-ns intervals and slap milliseconds on top */
|
||||||
|
Time->QuadPart = (TotalSeconds * TICKS_PER_SECOND) + ((ULONGLONG)TimeFields->Milliseconds * TICKS_PER_MILLISECOND);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
@@ -90,6 +90,8 @@
|
|||||||
@ stdcall RtlStringLength(str long)
|
@ stdcall RtlStringLength(str long)
|
||||||
@ stdcall RtlStringToWideString(wstr str long)
|
@ stdcall RtlStringToWideString(wstr str long)
|
||||||
@ stdcall RtlTestBit(ptr long)
|
@ stdcall RtlTestBit(ptr long)
|
||||||
|
@ stdcall RtlTimeFieldsToUnixEpoch(ptr ptr)
|
||||||
|
@ stdcall RtlTimeFieldsToXtEpoch(ptr ptr)
|
||||||
@ stdcall RtlTokenizeString(str str str)
|
@ stdcall RtlTokenizeString(str str str)
|
||||||
@ stdcall RtlTokenizeWideString(wstr wstr wstr)
|
@ stdcall RtlTokenizeWideString(wstr wstr wstr)
|
||||||
@ stdcall RtlToLowerCharacter(long)
|
@ stdcall RtlToLowerCharacter(long)
|
||||||
|
|||||||
Reference in New Issue
Block a user