Port changes from SolidPP

This commit is contained in:
doylet 2025-11-20 22:39:46 +11:00
parent 061aebfff9
commit 38c0e7dda0
10 changed files with 621 additions and 492 deletions

View File

@ -1,4 +1,4 @@
// Generated by the DN single header generator 2025-11-16 21:35:27 // Generated by the DN single header generator 2025-11-20 22:39:16
#define DN_BASE_INC_CPP #define DN_BASE_INC_CPP
@ -2828,61 +2828,72 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64(DN_U64 duration_ms, DN_AgeUnit units)
units &= ~DN_AgeUnit_Ms; units &= ~DN_AgeUnit_Ms;
} }
DN_Str8 unit_suffix = {};
if (units & DN_AgeUnit_Year) { if (units & DN_AgeUnit_Year) {
unit_suffix = DN_Str8Lit("y");
DN_USize value_usize = remainder_ms / (DN_SecFromYears(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromYears(1) * 1000);
remainder_ms -= DN_SecFromYears(value_usize) * 1000; remainder_ms -= DN_SecFromYears(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuyr", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Week) { if (units & DN_AgeUnit_Week) {
unit_suffix = DN_Str8Lit("w");
DN_USize value_usize = remainder_ms / (DN_SecFromWeeks(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromWeeks(1) * 1000);
remainder_ms -= DN_SecFromWeeks(value_usize) * 1000; remainder_ms -= DN_SecFromWeeks(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuw", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Day) { if (units & DN_AgeUnit_Day) {
unit_suffix = DN_Str8Lit("d");
DN_USize value_usize = remainder_ms / (DN_SecFromDays(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromDays(1) * 1000);
remainder_ms -= DN_SecFromDays(value_usize) * 1000; remainder_ms -= DN_SecFromDays(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zud", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Hr) { if (units & DN_AgeUnit_Hr) {
unit_suffix = DN_Str8Lit("h");
DN_USize value_usize = remainder_ms / (DN_SecFromHours(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromHours(1) * 1000);
remainder_ms -= DN_SecFromHours(value_usize) * 1000; remainder_ms -= DN_SecFromHours(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuh", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Min) { if (units & DN_AgeUnit_Min) {
unit_suffix = DN_Str8Lit("m");
DN_USize value_usize = remainder_ms / (DN_SecFromMins(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromMins(1) * 1000);
remainder_ms -= DN_SecFromMins(value_usize) * 1000; remainder_ms -= DN_SecFromMins(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zum", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Sec) { if (units & DN_AgeUnit_Sec) {
unit_suffix = DN_Str8Lit("s");
if (units & DN_AgeUnit_FractionalSec) { if (units & DN_AgeUnit_FractionalSec) {
DN_F64 remainder_s = remainder_ms / 1000.0; DN_F64 remainder_s = remainder_ms / 1000.0;
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%.3fs", result.size ? " " : "", remainder_s); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%.3f%.*s", result.size ? " " : "", remainder_s, DN_Str8PrintFmt(unit_suffix));
remainder_ms = 0; remainder_ms = 0;
} else { } else {
DN_USize value_usize = remainder_ms / 1000; DN_USize value_usize = remainder_ms / 1000;
remainder_ms -= DN_Cast(DN_USize)(value_usize * 1000); remainder_ms -= DN_Cast(DN_USize)(value_usize * 1000);
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zus", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
} }
if (units & DN_AgeUnit_Ms) { if (units & DN_AgeUnit_Ms) {
unit_suffix = DN_Str8Lit("ms");
DN_Assert((units & DN_AgeUnit_FractionalSec) == 0); DN_Assert((units & DN_AgeUnit_FractionalSec) == 0);
DN_USize value_usize = remainder_ms; DN_USize value_usize = remainder_ms;
remainder_ms -= value_usize; remainder_ms -= value_usize;
if (value_usize || result.size == 0) if (value_usize || result.size == 0)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zums", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (result.size == 0)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "0%.*s", DN_Str8PrintFmt(unit_suffix));
return result; return result;
} }
@ -2900,6 +2911,104 @@ DN_API DN_Str8x128 DN_AgeStr8FromSecF64(DN_F64 duration_s, DN_AgeUnit units)
return result; return result;
} }
DN_API int DN_IsLeapYear(int year)
{
if (year % 4 != 0)
return 0;
if (year % 100 != 0)
return 1;
return (year % 400 == 0);
}
DN_API bool DN_DateIsValid(DN_Date date)
{
if (date.year < 1970)
return false;
if (date.month <= 0 || date.month >= 13)
return false;
if (date.day <= 0 || date.day >= 32)
return false;
if (date.hour >= 24)
return false;
if (date.minutes >= 60)
return false;
if (date.seconds >= 60)
return false;
return true;
}
DN_API DN_Date DN_DateFromUnixTimeMs(DN_USize unix_ts_ms)
{
DN_Date result = {};
DN_USize ms = unix_ts_ms % 1000;
DN_USize total_seconds = unix_ts_ms / 1000;
result.milliseconds = (DN_U16)ms;
DN_USize secs_in_day = total_seconds % 86400;
DN_USize days = total_seconds / 86400;
result.hour = (DN_U8)(secs_in_day / 3600);
result.minutes = (DN_U8)((secs_in_day % 3600) / 60);
result.seconds = (DN_U8)(secs_in_day % 60);
DN_U16 days_in_month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
DN_USize days_left = days;
DN_U16 year = 1970;
while (days_left >= (DN_IsLeapYear(year) ? 366 : 365)) {
DN_USize days_in_year = DN_IsLeapYear(year) ? 366 : 365;
days_left -= days_in_year;
year++;
}
DN_U8 month = 1;
for (;;) {
DN_U16 day_count = days_in_month[month];
if (month == 2 && DN_IsLeapYear(year))
day_count = 29;
if (days_left < day_count)
break;
days_left -= day_count;
month++;
}
result.year = year;
result.month = month;
result.day = (DN_U8)days_left + 1;
return result;
}
DN_API DN_U64 DN_UnixTimeMsFromDate(DN_Date date)
{
DN_Assert(DN_DateIsValid(date));
// Precomputed cumulative days before each month (non-leap year)
const DN_U16 days_before_month[13] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
DN_U16 y = date.year;
DN_U8 m = date.month;
DN_U8 d = date.day;
DN_U32 days = d - 1; // day of month starts at 0 internally
days += days_before_month[m - 1]; // Add days from previous months this year
if (m > 2 && DN_IsLeapYear(y)) // Add February 29 if leap year and month > 2
days += 1;
// Add full years from 1970 to y-1
for (DN_U16 year = 1970; year < y; ++year)
days += DN_IsLeapYear(year) ? 366 : 365;
// Convert to seconds
DN_U64 seconds = DN_Cast(DN_U64)days * 86400ULL;
seconds += DN_Cast(DN_U64)date.hour * 3600ULL;
seconds += DN_Cast(DN_U64)date.minutes * 60ULL;
seconds += DN_Cast(DN_U64)date.seconds;
DN_U64 result = seconds * 1000ULL + date.milliseconds;
return result;
}
DN_API DN_Str8 DN_Str8FromByteCountType(DN_ByteCountType type) DN_API DN_Str8 DN_Str8FromByteCountType(DN_ByteCountType type)
{ {
DN_Str8 result = DN_Str8Lit(""); DN_Str8 result = DN_Str8Lit("");
@ -5457,7 +5566,7 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data,
} }
} }
DN_OSDateTime os_date = DN_OS_DateLocalTimeNow(); DN_Date os_date = DN_OS_DateLocalTimeNow();
DN_LOGDate log_date = {}; DN_LOGDate log_date = {};
log_date.year = os_date.year; log_date.year = os_date.year;
log_date.month = os_date.month; log_date.month = os_date.month;
@ -5586,57 +5695,30 @@ DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS(void const *bytes, DN_USize bytes_c
return result; return result;
} }
// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// // NOTE: Date
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8(DN_OSDateTime time, char date_separator, char hms_separator) DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8(DN_Date time, char date_separator, char hms_separator)
{ {
DN_OSDateTimeStr8 result = {}; DN_Str8x32 result = DN_Str8x32FromFmt("%hu%c%02hhu%c%02hhu %02hhu%c%02hhu%c%02hhu",
result.hms_size = DN_Cast(uint8_t) DN_SNPrintF(result.hms, time.year,
DN_ArrayCountI(result.hms), date_separator,
"%02hhu%c%02hhu%c%02hhu", time.month,
date_separator,
time.day,
time.hour, time.hour,
hms_separator, hms_separator,
time.minutes, time.minutes,
hms_separator, hms_separator,
time.seconds); time.seconds);
result.date_size = DN_Cast(uint8_t) DN_SNPrintF(result.date,
DN_ArrayCountI(result.date),
"%hu%c%02hhu%c%02hhu",
time.year,
date_separator,
time.month,
date_separator,
time.day);
DN_Assert(result.hms_size < DN_ArrayCountU(result.hms));
DN_Assert(result.date_size < DN_ArrayCountU(result.date));
return result; return result;
} }
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator) DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator)
{ {
DN_OSDateTime time = DN_OS_DateLocalTimeNow(); DN_Date time = DN_OS_DateLocalTimeNow();
DN_OSDateTimeStr8 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator); DN_Str8x32 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator);
return result; return result;
} }
DN_API bool DN_OS_DateIsValid(DN_OSDateTime date)
{
if (date.year < 1970)
return false;
if (date.month <= 0 || date.month >= 13)
return false;
if (date.day <= 0 || date.day >= 32)
return false;
if (date.hour >= 24)
return false;
if (date.minutes >= 60)
return false;
if (date.seconds >= 60)
return false;
return true;
}
// NOTE: Other // NOTE: Other
DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena) DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena)
{ {
@ -7005,10 +7087,10 @@ DN_API void DN_OS_MemDealloc(void *ptr)
free(ptr); free(ptr);
} }
// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// // NOTE: Date
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() DN_API DN_Date DN_OS_DateLocalTimeNow()
{ {
DN_OSDateTime result = {}; DN_Date result = {};
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);
@ -7026,47 +7108,57 @@ DN_API DN_OSDateTime DN_OS_DateLocalTimeNow()
result.hour = time.tm_hour; result.hour = time.tm_hour;
result.minutes = time.tm_min; result.minutes = time.tm_min;
result.seconds = time.tm_sec; result.seconds = time.tm_sec;
result.milliseconds = ts.tv_nsec / (1000 * 1000); // TODO: Verify that getting the milliseconds like this is correct
result.day = DN_Cast(uint8_t) time.tm_mday; result.day = DN_Cast(DN_U8) time.tm_mday;
result.month = DN_Cast(uint8_t) time.tm_mon + 1; result.month = DN_Cast(DN_U8) time.tm_mon + 1;
result.year = 1900 + DN_Cast(int16_t) time.tm_year; result.year = 1900 + DN_Cast(DN_U16) time.tm_year;
return result; return result;
} }
DN_API uint64_t DN_OS_DateUnixTimeNs() DN_API DN_U64 DN_OS_DateUnixTimeNs()
{ {
struct timespec ts = {}; struct timespec ts = {};
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);
uint64_t result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec; DN_U64 result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec;
return result; return result;
} }
DN_API uint64_t DN_OS_DateLocalToUnixTimeS(DN_OSDateTime) DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate(DN_Date date)
{ {
DN_AssertOnce(!"Unimplemented"); struct tm tm_time = {0};
uint64_t result = 0; tm_time.tm_year = (int)date.year - 1900;
tm_time.tm_mon = (int)date.month - 1; // month is 1-12 in your struct
tm_time.tm_mday = (int)date.day; // day of month 1-31
tm_time.tm_hour = (int)date.hour;
tm_time.tm_min = (int)date.minutes;
tm_time.tm_sec = (int)date.seconds;
tm_time.tm_isdst = -1; // tm_isdst = -1 lets mktime() determine whether DST is in effect
time_t unix_time = mktime(&tm_time);
DN_U64 result = DN_Cast(DN_U64) unix_time;
return result; return result;
} }
DN_API uint64_t DN_OS_DateToUnixTimeS(DN_OSDateTime date) DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s)
{ {
DN_Assert(DN_OS_DateIsValid(date)); struct tm tm_local;
struct tm timeinfo = {}; void *ret = localtime_r(&unix_ts_s, &tm_local);
timeinfo.tm_year = date.year - 1900; DN_Assert(ret);
timeinfo.tm_mon = date.month - 1;
timeinfo.tm_mday = date.day; long local_offset_seconds = tm_local.tm_gmtoff;
timeinfo.tm_hour = date.hour; DN_U64 result = unix_ts_s;
timeinfo.tm_min = date.minutes; if (local_offset_seconds > 0)
timeinfo.tm_sec = date.seconds; result += local_offset_seconds;
uint64_t result = mktime(&timeinfo); else
result -= local_offset_seconds;
return result; return result;
} }
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(uint64_t time) DN_API DN_Date DN_OS_DateUnixTimeSToDate(DN_U64 time)
{ {
time_t posix_time = DN_Cast(time_t) time; time_t posix_time = DN_Cast(time_t) time;
struct tm posix_date = *gmtime(&posix_time); struct tm posix_date = *gmtime(&posix_time);
DN_OSDateTime result = {}; DN_Date result = {};
result.year = posix_date.tm_year + 1900; result.year = posix_date.tm_year + 1900;
result.month = posix_date.tm_mon + 1; result.month = posix_date.tm_mon + 1;
result.day = posix_date.tm_mday; result.day = posix_date.tm_mday;
@ -8558,19 +8650,20 @@ DN_API void DN_OS_MemDealloc(void *ptr)
HeapFree(GetProcessHeap(), 0, ptr); HeapFree(GetProcessHeap(), 0, ptr);
} }
// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// // NOTE: Date
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() DN_API DN_Date DN_OS_DateLocalTimeNow()
{ {
SYSTEMTIME sys_time; SYSTEMTIME sys_time;
GetLocalTime(&sys_time); GetLocalTime(&sys_time);
DN_OSDateTime result = {}; DN_Date result = {};
result.hour = DN_Cast(uint8_t) sys_time.wHour; result.hour = DN_Cast(DN_U8) sys_time.wHour;
result.minutes = DN_Cast(uint8_t) sys_time.wMinute; result.milliseconds = DN_Cast(DN_U8) sys_time.wMilliseconds;
result.seconds = DN_Cast(uint8_t) sys_time.wSecond; result.minutes = DN_Cast(DN_U8) sys_time.wMinute;
result.day = DN_Cast(uint8_t) sys_time.wDay; result.seconds = DN_Cast(DN_U8) sys_time.wSecond;
result.month = DN_Cast(uint8_t) sys_time.wMonth; result.day = DN_Cast(DN_U8) sys_time.wDay;
result.year = DN_Cast(int16_t) sys_time.wYear; result.month = DN_Cast(DN_U8) sys_time.wMonth;
result.year = DN_Cast(DN_U16) sys_time.wYear;
return result; return result;
} }
@ -8591,7 +8684,7 @@ DN_API DN_U64 DN_OS_DateUnixTimeNs()
return result; return result;
} }
static SYSTEMTIME DN_OS_DateToSystemTime_(DN_OSDateTime date) static SYSTEMTIME DN_OS_DateToSystemTime_(DN_Date date)
{ {
SYSTEMTIME result = {}; SYSTEMTIME result = {};
result.wYear = date.year; result.wYear = date.year;
@ -8600,6 +8693,7 @@ static SYSTEMTIME DN_OS_DateToSystemTime_(DN_OSDateTime date)
result.wHour = date.hour; result.wHour = date.hour;
result.wMinute = date.minutes; result.wMinute = date.minutes;
result.wSecond = date.seconds; result.wSecond = date.seconds;
result.wMilliseconds = date.milliseconds;
return result; return result;
} }
@ -8615,7 +8709,7 @@ static DN_U64 DN_OS_SystemTimeToUnixTimeS_(SYSTEMTIME *sys_time)
return result; return result;
} }
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date) DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate(DN_Date date)
{ {
SYSTEMTIME local_time = DN_OS_DateToSystemTime_(date); SYSTEMTIME local_time = DN_OS_DateToSystemTime_(date);
SYSTEMTIME sys_time = {}; SYSTEMTIME sys_time = {};
@ -8624,36 +8718,17 @@ DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date)
return result; return result;
} }
DN_API DN_U64 DN_OS_DateToUnixTimeS(DN_OSDateTime date) DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s)
{ {
DN_Assert(DN_OS_DateIsValid(date)); DN_U64 unix_time = DN_Cast(DN_U64) unix_ts_s * 10000000LL; // seconds -> 100ns units
DN_U64 filetime_utc = unix_time + 116444736000000000LL; // Unix epoch -> Windows epoch
FILETIME ft_utc = {DN_Cast(DWORD) filetime_utc, DN_Cast(DWORD)(filetime_utc >> 32)};
FILETIME ft_local;
bool converted = FileTimeToLocalFileTime(&ft_utc, &ft_local);
DN_Assert(converted);
SYSTEMTIME sys_time = DN_OS_DateToSystemTime_(date); DN_U64 filetime_local = (DN_Cast(DN_U64) ft_local.dwHighDateTime << 32) | ft_local.dwLowDateTime;
DN_U64 result = DN_OS_SystemTimeToUnixTimeS_(&sys_time); DN_U64 result = (filetime_local - 116444736000000000LL) / 10000000LL;
return result;
}
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(DN_U64 time)
{
// NOTE: Windows epoch time starts from Jan 1, 1601 and counts in
// 100-nanoseconds intervals.
//
// See: https://devblogs.microsoft.com/oldnewthing/20090306-00/?p=18913
DN_U64 w32_time = 116'444'736'000'000'000 + (time * 10'000'000);
SYSTEMTIME sys_time = {};
FILETIME file_time = {};
file_time.dwLowDateTime = (DWORD)w32_time;
file_time.dwHighDateTime = w32_time >> 32;
FileTimeToSystemTime(&file_time, &sys_time);
DN_OSDateTime result = {};
result.year = DN_Cast(uint16_t) sys_time.wYear;
result.month = DN_Cast(uint8_t) sys_time.wMonth;
result.day = DN_Cast(uint8_t) sys_time.wDay;
result.hour = DN_Cast(uint8_t) sys_time.wHour;
result.minutes = DN_Cast(uint8_t) sys_time.wMinute;
result.seconds = DN_Cast(uint8_t) sys_time.wSecond;
return result; return result;
} }
@ -11479,6 +11554,17 @@ struct DN_ByteCountResult
DN_F64 bytes; DN_F64 bytes;
}; };
struct DN_Date
{
DN_U8 day;
DN_U8 month;
DN_U16 year;
DN_U8 hour;
DN_U8 minutes;
DN_U8 seconds;
DN_U16 milliseconds;
};
struct DN_FmtAppendResult struct DN_FmtAppendResult
{ {
DN_USize size_req; DN_USize size_req;
@ -13763,6 +13849,11 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms,
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units);
DN_API int DN_IsLeapYear (int year);
DN_API bool DN_DateIsValid (DN_Date date);
DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms);
DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date);
DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type);
#define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) #define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto)
DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type);
@ -15083,9 +15174,10 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
__declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime);
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
__declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName);
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
@ -16431,9 +16523,10 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
__declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime);
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
__declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName);
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
@ -17579,33 +17672,13 @@ DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err,
extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
// NOTE: DN_OSDate /////////////////////////////////////////////////////////////////////////////////
struct DN_OSDateTimeStr8
{
char date[DN_ArrayCountU("YYYY-MM-SS")];
DN_U8 date_size;
char hms[DN_ArrayCountU("HH:MM:SS")];
DN_U8 hms_size;
};
struct DN_OSDateTime
{
DN_U8 day;
DN_U8 month;
DN_U16 year;
DN_U8 hour;
DN_U8 minutes;
DN_U8 seconds;
};
struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. struct DN_OSTimer /// Record time between two time-points using the OS's performance counter.
{ {
DN_U64 start; DN_U64 start;
DN_U64 end; DN_U64 end;
}; };
#if !defined(DN_NO_OS_FILE_API) // NOTE: DN_OSFile
// NOTE: DN_OSFile /////////////////////////////////////////////////////////////////////////////////
enum DN_OSPathInfoType enum DN_OSPathInfoType
{ {
DN_OSPathInfoType_Unknown, DN_OSPathInfoType_Unknown,
@ -17630,7 +17703,7 @@ struct DN_OSDirIterator
char buffer[512]; char buffer[512];
}; };
// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// // NOTE: R/W Stream API
struct DN_OSFileRead struct DN_OSFileRead
{ {
bool success; bool success;
@ -17661,9 +17734,8 @@ enum DN_OSFileAccess_
DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write,
DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly,
}; };
#endif // DN_NO_OS_FILE_API
// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSPath
#if !defined(DN_OSPathSeperator) #if !defined(DN_OSPathSeperator)
#if defined(DN_OS_WIN32) #if defined(DN_OS_WIN32)
#define DN_OSPathSeperator "\\" #define DN_OSPathSeperator "\\"
@ -17689,7 +17761,7 @@ struct DN_OSPath
DN_U16 links_size; DN_U16 links_size;
}; };
// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSExec
typedef DN_U32 DN_OSExecFlags; typedef DN_U32 DN_OSExecFlags;
enum DN_OSExecFlags_ enum DN_OSExecFlags_
@ -17729,7 +17801,7 @@ struct DN_OSExecArgs
DN_Slice<DN_Str8> environment; DN_Slice<DN_Str8> environment;
}; };
// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSSemaphore
DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX;
struct DN_OSSemaphore struct DN_OSSemaphore
@ -17860,17 +17932,15 @@ DN_API int DN_OS_MemProtect (v
DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem); DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem);
DN_API void DN_OS_MemDealloc (void *ptr); DN_API void DN_OS_MemDealloc (void *ptr);
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); DN_API DN_Date DN_OS_DateLocalTimeNow ();
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':');
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date time, char date_separator = '-', char hms_separator = ':');
DN_API DN_U64 DN_OS_DateUnixTimeNs (); DN_API DN_U64 DN_OS_DateUnixTimeNs ();
#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000) #define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000)
#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000)) #define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000))
#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000)) #define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000))
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time); DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date);
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS (DN_OSDateTime date); DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s);
DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date);
DN_API bool DN_OS_DateIsValid (DN_OSDateTime date);
DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size);
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);

View File

@ -1,4 +1,4 @@
// Generated by the DN single header generator 2025-11-16 21:35:27 // Generated by the DN single header generator 2025-11-20 22:39:16
#if !defined(DN_BASE_INC_H) #if !defined(DN_BASE_INC_H)
#define DN_BASE_INC_H #define DN_BASE_INC_H
@ -978,6 +978,17 @@ struct DN_ByteCountResult
DN_F64 bytes; DN_F64 bytes;
}; };
struct DN_Date
{
DN_U8 day;
DN_U8 month;
DN_U16 year;
DN_U8 hour;
DN_U8 minutes;
DN_U8 seconds;
DN_U16 milliseconds;
};
struct DN_FmtAppendResult struct DN_FmtAppendResult
{ {
DN_USize size_req; DN_USize size_req;
@ -3262,6 +3273,11 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms,
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units);
DN_API int DN_IsLeapYear (int year);
DN_API bool DN_DateIsValid (DN_Date date);
DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms);
DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date);
DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type);
#define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) #define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto)
DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type);
@ -4581,9 +4597,10 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
__declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime);
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
__declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName);
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
@ -5929,9 +5946,10 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
__declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime);
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
__declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName);
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
@ -7077,33 +7095,13 @@ DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err,
extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
// NOTE: DN_OSDate /////////////////////////////////////////////////////////////////////////////////
struct DN_OSDateTimeStr8
{
char date[DN_ArrayCountU("YYYY-MM-SS")];
DN_U8 date_size;
char hms[DN_ArrayCountU("HH:MM:SS")];
DN_U8 hms_size;
};
struct DN_OSDateTime
{
DN_U8 day;
DN_U8 month;
DN_U16 year;
DN_U8 hour;
DN_U8 minutes;
DN_U8 seconds;
};
struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. struct DN_OSTimer /// Record time between two time-points using the OS's performance counter.
{ {
DN_U64 start; DN_U64 start;
DN_U64 end; DN_U64 end;
}; };
#if !defined(DN_NO_OS_FILE_API) // NOTE: DN_OSFile
// NOTE: DN_OSFile /////////////////////////////////////////////////////////////////////////////////
enum DN_OSPathInfoType enum DN_OSPathInfoType
{ {
DN_OSPathInfoType_Unknown, DN_OSPathInfoType_Unknown,
@ -7128,7 +7126,7 @@ struct DN_OSDirIterator
char buffer[512]; char buffer[512];
}; };
// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// // NOTE: R/W Stream API
struct DN_OSFileRead struct DN_OSFileRead
{ {
bool success; bool success;
@ -7159,9 +7157,8 @@ enum DN_OSFileAccess_
DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write,
DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly,
}; };
#endif // DN_NO_OS_FILE_API
// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSPath
#if !defined(DN_OSPathSeperator) #if !defined(DN_OSPathSeperator)
#if defined(DN_OS_WIN32) #if defined(DN_OS_WIN32)
#define DN_OSPathSeperator "\\" #define DN_OSPathSeperator "\\"
@ -7187,7 +7184,7 @@ struct DN_OSPath
DN_U16 links_size; DN_U16 links_size;
}; };
// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSExec
typedef DN_U32 DN_OSExecFlags; typedef DN_U32 DN_OSExecFlags;
enum DN_OSExecFlags_ enum DN_OSExecFlags_
@ -7227,7 +7224,7 @@ struct DN_OSExecArgs
DN_Slice<DN_Str8> environment; DN_Slice<DN_Str8> environment;
}; };
// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSSemaphore
DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX;
struct DN_OSSemaphore struct DN_OSSemaphore
@ -7358,17 +7355,15 @@ DN_API int DN_OS_MemProtect (v
DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem); DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem);
DN_API void DN_OS_MemDealloc (void *ptr); DN_API void DN_OS_MemDealloc (void *ptr);
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); DN_API DN_Date DN_OS_DateLocalTimeNow ();
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':');
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date time, char date_separator = '-', char hms_separator = ':');
DN_API DN_U64 DN_OS_DateUnixTimeNs (); DN_API DN_U64 DN_OS_DateUnixTimeNs ();
#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000) #define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000)
#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000)) #define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000))
#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000)) #define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000))
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time); DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date);
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS (DN_OSDateTime date); DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s);
DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date);
DN_API bool DN_OS_DateIsValid (DN_OSDateTime date);
DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size);
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);
@ -8676,6 +8671,17 @@ struct DN_ByteCountResult
DN_F64 bytes; DN_F64 bytes;
}; };
struct DN_Date
{
DN_U8 day;
DN_U8 month;
DN_U16 year;
DN_U8 hour;
DN_U8 minutes;
DN_U8 seconds;
DN_U16 milliseconds;
};
struct DN_FmtAppendResult struct DN_FmtAppendResult
{ {
DN_USize size_req; DN_USize size_req;
@ -10960,6 +10966,11 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms,
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units);
DN_API int DN_IsLeapYear (int year);
DN_API bool DN_DateIsValid (DN_Date date);
DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms);
DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date);
DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type);
#define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) #define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto)
DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type);
@ -12280,9 +12291,10 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
__declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime);
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
__declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName);
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
@ -13628,9 +13640,10 @@ DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
__declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime);
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
__declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName);
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
@ -14776,33 +14789,13 @@ DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err,
extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
// NOTE: DN_OSDate /////////////////////////////////////////////////////////////////////////////////
struct DN_OSDateTimeStr8
{
char date[DN_ArrayCountU("YYYY-MM-SS")];
DN_U8 date_size;
char hms[DN_ArrayCountU("HH:MM:SS")];
DN_U8 hms_size;
};
struct DN_OSDateTime
{
DN_U8 day;
DN_U8 month;
DN_U16 year;
DN_U8 hour;
DN_U8 minutes;
DN_U8 seconds;
};
struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. struct DN_OSTimer /// Record time between two time-points using the OS's performance counter.
{ {
DN_U64 start; DN_U64 start;
DN_U64 end; DN_U64 end;
}; };
#if !defined(DN_NO_OS_FILE_API) // NOTE: DN_OSFile
// NOTE: DN_OSFile /////////////////////////////////////////////////////////////////////////////////
enum DN_OSPathInfoType enum DN_OSPathInfoType
{ {
DN_OSPathInfoType_Unknown, DN_OSPathInfoType_Unknown,
@ -14827,7 +14820,7 @@ struct DN_OSDirIterator
char buffer[512]; char buffer[512];
}; };
// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// // NOTE: R/W Stream API
struct DN_OSFileRead struct DN_OSFileRead
{ {
bool success; bool success;
@ -14858,9 +14851,8 @@ enum DN_OSFileAccess_
DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write,
DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly,
}; };
#endif // DN_NO_OS_FILE_API
// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSPath
#if !defined(DN_OSPathSeperator) #if !defined(DN_OSPathSeperator)
#if defined(DN_OS_WIN32) #if defined(DN_OS_WIN32)
#define DN_OSPathSeperator "\\" #define DN_OSPathSeperator "\\"
@ -14886,7 +14878,7 @@ struct DN_OSPath
DN_U16 links_size; DN_U16 links_size;
}; };
// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSExec
typedef DN_U32 DN_OSExecFlags; typedef DN_U32 DN_OSExecFlags;
enum DN_OSExecFlags_ enum DN_OSExecFlags_
@ -14926,7 +14918,7 @@ struct DN_OSExecArgs
DN_Slice<DN_Str8> environment; DN_Slice<DN_Str8> environment;
}; };
// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSSemaphore
DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX;
struct DN_OSSemaphore struct DN_OSSemaphore
@ -15057,17 +15049,15 @@ DN_API int DN_OS_MemProtect (v
DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem); DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem);
DN_API void DN_OS_MemDealloc (void *ptr); DN_API void DN_OS_MemDealloc (void *ptr);
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); DN_API DN_Date DN_OS_DateLocalTimeNow ();
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':');
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date time, char date_separator = '-', char hms_separator = ':');
DN_API DN_U64 DN_OS_DateUnixTimeNs (); DN_API DN_U64 DN_OS_DateUnixTimeNs ();
#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000) #define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000)
#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000)) #define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000))
#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000)) #define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000))
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time); DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date);
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS (DN_OSDateTime date); DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s);
DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date);
DN_API bool DN_OS_DateIsValid (DN_OSDateTime date);
DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size);
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);

View File

@ -2823,61 +2823,72 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64(DN_U64 duration_ms, DN_AgeUnit units)
units &= ~DN_AgeUnit_Ms; units &= ~DN_AgeUnit_Ms;
} }
DN_Str8 unit_suffix = {};
if (units & DN_AgeUnit_Year) { if (units & DN_AgeUnit_Year) {
unit_suffix = DN_Str8Lit("y");
DN_USize value_usize = remainder_ms / (DN_SecFromYears(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromYears(1) * 1000);
remainder_ms -= DN_SecFromYears(value_usize) * 1000; remainder_ms -= DN_SecFromYears(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuyr", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Week) { if (units & DN_AgeUnit_Week) {
unit_suffix = DN_Str8Lit("w");
DN_USize value_usize = remainder_ms / (DN_SecFromWeeks(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromWeeks(1) * 1000);
remainder_ms -= DN_SecFromWeeks(value_usize) * 1000; remainder_ms -= DN_SecFromWeeks(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuw", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Day) { if (units & DN_AgeUnit_Day) {
unit_suffix = DN_Str8Lit("d");
DN_USize value_usize = remainder_ms / (DN_SecFromDays(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromDays(1) * 1000);
remainder_ms -= DN_SecFromDays(value_usize) * 1000; remainder_ms -= DN_SecFromDays(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zud", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Hr) { if (units & DN_AgeUnit_Hr) {
unit_suffix = DN_Str8Lit("h");
DN_USize value_usize = remainder_ms / (DN_SecFromHours(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromHours(1) * 1000);
remainder_ms -= DN_SecFromHours(value_usize) * 1000; remainder_ms -= DN_SecFromHours(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zuh", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Min) { if (units & DN_AgeUnit_Min) {
unit_suffix = DN_Str8Lit("m");
DN_USize value_usize = remainder_ms / (DN_SecFromMins(1) * 1000); DN_USize value_usize = remainder_ms / (DN_SecFromMins(1) * 1000);
remainder_ms -= DN_SecFromMins(value_usize) * 1000; remainder_ms -= DN_SecFromMins(value_usize) * 1000;
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zum", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (units & DN_AgeUnit_Sec) { if (units & DN_AgeUnit_Sec) {
unit_suffix = DN_Str8Lit("s");
if (units & DN_AgeUnit_FractionalSec) { if (units & DN_AgeUnit_FractionalSec) {
DN_F64 remainder_s = remainder_ms / 1000.0; DN_F64 remainder_s = remainder_ms / 1000.0;
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%.3fs", result.size ? " " : "", remainder_s); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%.3f%.*s", result.size ? " " : "", remainder_s, DN_Str8PrintFmt(unit_suffix));
remainder_ms = 0; remainder_ms = 0;
} else { } else {
DN_USize value_usize = remainder_ms / 1000; DN_USize value_usize = remainder_ms / 1000;
remainder_ms -= DN_Cast(DN_USize)(value_usize * 1000); remainder_ms -= DN_Cast(DN_USize)(value_usize * 1000);
if (value_usize) if (value_usize)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zus", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
} }
if (units & DN_AgeUnit_Ms) { if (units & DN_AgeUnit_Ms) {
unit_suffix = DN_Str8Lit("ms");
DN_Assert((units & DN_AgeUnit_FractionalSec) == 0); DN_Assert((units & DN_AgeUnit_FractionalSec) == 0);
DN_USize value_usize = remainder_ms; DN_USize value_usize = remainder_ms;
remainder_ms -= value_usize; remainder_ms -= value_usize;
if (value_usize || result.size == 0) if (value_usize || result.size == 0)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zums", result.size ? " " : "", value_usize); DN_FmtAppend(result.data, &result.size, sizeof(result.data), "%s%zu%.*s", result.size ? " " : "", value_usize, DN_Str8PrintFmt(unit_suffix));
} }
if (result.size == 0)
DN_FmtAppend(result.data, &result.size, sizeof(result.data), "0%.*s", DN_Str8PrintFmt(unit_suffix));
return result; return result;
} }
@ -2895,6 +2906,104 @@ DN_API DN_Str8x128 DN_AgeStr8FromSecF64(DN_F64 duration_s, DN_AgeUnit units)
return result; return result;
} }
DN_API int DN_IsLeapYear(int year)
{
if (year % 4 != 0)
return 0;
if (year % 100 != 0)
return 1;
return (year % 400 == 0);
}
DN_API bool DN_DateIsValid(DN_Date date)
{
if (date.year < 1970)
return false;
if (date.month <= 0 || date.month >= 13)
return false;
if (date.day <= 0 || date.day >= 32)
return false;
if (date.hour >= 24)
return false;
if (date.minutes >= 60)
return false;
if (date.seconds >= 60)
return false;
return true;
}
DN_API DN_Date DN_DateFromUnixTimeMs(DN_USize unix_ts_ms)
{
DN_Date result = {};
DN_USize ms = unix_ts_ms % 1000;
DN_USize total_seconds = unix_ts_ms / 1000;
result.milliseconds = (DN_U16)ms;
DN_USize secs_in_day = total_seconds % 86400;
DN_USize days = total_seconds / 86400;
result.hour = (DN_U8)(secs_in_day / 3600);
result.minutes = (DN_U8)((secs_in_day % 3600) / 60);
result.seconds = (DN_U8)(secs_in_day % 60);
DN_U16 days_in_month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
DN_USize days_left = days;
DN_U16 year = 1970;
while (days_left >= (DN_IsLeapYear(year) ? 366 : 365)) {
DN_USize days_in_year = DN_IsLeapYear(year) ? 366 : 365;
days_left -= days_in_year;
year++;
}
DN_U8 month = 1;
for (;;) {
DN_U16 day_count = days_in_month[month];
if (month == 2 && DN_IsLeapYear(year))
day_count = 29;
if (days_left < day_count)
break;
days_left -= day_count;
month++;
}
result.year = year;
result.month = month;
result.day = (DN_U8)days_left + 1;
return result;
}
DN_API DN_U64 DN_UnixTimeMsFromDate(DN_Date date)
{
DN_Assert(DN_DateIsValid(date));
// Precomputed cumulative days before each month (non-leap year)
const DN_U16 days_before_month[13] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
DN_U16 y = date.year;
DN_U8 m = date.month;
DN_U8 d = date.day;
DN_U32 days = d - 1; // day of month starts at 0 internally
days += days_before_month[m - 1]; // Add days from previous months this year
if (m > 2 && DN_IsLeapYear(y)) // Add February 29 if leap year and month > 2
days += 1;
// Add full years from 1970 to y-1
for (DN_U16 year = 1970; year < y; ++year)
days += DN_IsLeapYear(year) ? 366 : 365;
// Convert to seconds
DN_U64 seconds = DN_Cast(DN_U64)days * 86400ULL;
seconds += DN_Cast(DN_U64)date.hour * 3600ULL;
seconds += DN_Cast(DN_U64)date.minutes * 60ULL;
seconds += DN_Cast(DN_U64)date.seconds;
DN_U64 result = seconds * 1000ULL + date.milliseconds;
return result;
}
DN_API DN_Str8 DN_Str8FromByteCountType(DN_ByteCountType type) DN_API DN_Str8 DN_Str8FromByteCountType(DN_ByteCountType type)
{ {
DN_Str8 result = DN_Str8Lit(""); DN_Str8 result = DN_Str8Lit("");

View File

@ -760,6 +760,17 @@ struct DN_ByteCountResult
DN_F64 bytes; DN_F64 bytes;
}; };
struct DN_Date
{
DN_U8 day;
DN_U8 month;
DN_U16 year;
DN_U8 hour;
DN_U8 minutes;
DN_U8 seconds;
DN_U16 milliseconds;
};
struct DN_FmtAppendResult struct DN_FmtAppendResult
{ {
DN_USize size_req; DN_USize size_req;
@ -1116,6 +1127,11 @@ DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms,
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units);
DN_API int DN_IsLeapYear (int year);
DN_API bool DN_DateIsValid (DN_Date date);
DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms);
DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date);
DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type);
#define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) #define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto)
DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type);

View File

@ -55,7 +55,7 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data,
} }
} }
DN_OSDateTime os_date = DN_OS_DateLocalTimeNow(); DN_Date os_date = DN_OS_DateLocalTimeNow();
DN_LOGDate log_date = {}; DN_LOGDate log_date = {};
log_date.year = os_date.year; log_date.year = os_date.year;
log_date.month = os_date.month; log_date.month = os_date.month;
@ -184,57 +184,30 @@ DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS(void const *bytes, DN_USize bytes_c
return result; return result;
} }
// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// // NOTE: Date
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8(DN_OSDateTime time, char date_separator, char hms_separator) DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8(DN_Date time, char date_separator, char hms_separator)
{ {
DN_OSDateTimeStr8 result = {}; DN_Str8x32 result = DN_Str8x32FromFmt("%hu%c%02hhu%c%02hhu %02hhu%c%02hhu%c%02hhu",
result.hms_size = DN_Cast(uint8_t) DN_SNPrintF(result.hms, time.year,
DN_ArrayCountI(result.hms), date_separator,
"%02hhu%c%02hhu%c%02hhu", time.month,
date_separator,
time.day,
time.hour, time.hour,
hms_separator, hms_separator,
time.minutes, time.minutes,
hms_separator, hms_separator,
time.seconds); time.seconds);
result.date_size = DN_Cast(uint8_t) DN_SNPrintF(result.date,
DN_ArrayCountI(result.date),
"%hu%c%02hhu%c%02hhu",
time.year,
date_separator,
time.month,
date_separator,
time.day);
DN_Assert(result.hms_size < DN_ArrayCountU(result.hms));
DN_Assert(result.date_size < DN_ArrayCountU(result.date));
return result; return result;
} }
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator) DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator)
{ {
DN_OSDateTime time = DN_OS_DateLocalTimeNow(); DN_Date time = DN_OS_DateLocalTimeNow();
DN_OSDateTimeStr8 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator); DN_Str8x32 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator);
return result; return result;
} }
DN_API bool DN_OS_DateIsValid(DN_OSDateTime date)
{
if (date.year < 1970)
return false;
if (date.month <= 0 || date.month >= 13)
return false;
if (date.day <= 0 || date.day >= 32)
return false;
if (date.hour >= 24)
return false;
if (date.minutes >= 60)
return false;
if (date.seconds >= 60)
return false;
return true;
}
// NOTE: Other // NOTE: Other
DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena) DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena)
{ {

View File

@ -37,33 +37,13 @@
extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
// NOTE: DN_OSDate /////////////////////////////////////////////////////////////////////////////////
struct DN_OSDateTimeStr8
{
char date[DN_ArrayCountU("YYYY-MM-SS")];
DN_U8 date_size;
char hms[DN_ArrayCountU("HH:MM:SS")];
DN_U8 hms_size;
};
struct DN_OSDateTime
{
DN_U8 day;
DN_U8 month;
DN_U16 year;
DN_U8 hour;
DN_U8 minutes;
DN_U8 seconds;
};
struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. struct DN_OSTimer /// Record time between two time-points using the OS's performance counter.
{ {
DN_U64 start; DN_U64 start;
DN_U64 end; DN_U64 end;
}; };
#if !defined(DN_NO_OS_FILE_API) // NOTE: DN_OSFile
// NOTE: DN_OSFile /////////////////////////////////////////////////////////////////////////////////
enum DN_OSPathInfoType enum DN_OSPathInfoType
{ {
DN_OSPathInfoType_Unknown, DN_OSPathInfoType_Unknown,
@ -88,7 +68,7 @@ struct DN_OSDirIterator
char buffer[512]; char buffer[512];
}; };
// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// // NOTE: R/W Stream API
struct DN_OSFileRead struct DN_OSFileRead
{ {
bool success; bool success;
@ -119,9 +99,8 @@ enum DN_OSFileAccess_
DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write,
DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly,
}; };
#endif // DN_NO_OS_FILE_API
// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSPath
#if !defined(DN_OSPathSeperator) #if !defined(DN_OSPathSeperator)
#if defined(DN_OS_WIN32) #if defined(DN_OS_WIN32)
#define DN_OSPathSeperator "\\" #define DN_OSPathSeperator "\\"
@ -147,7 +126,7 @@ struct DN_OSPath
DN_U16 links_size; DN_U16 links_size;
}; };
// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSExec
typedef DN_U32 DN_OSExecFlags; typedef DN_U32 DN_OSExecFlags;
enum DN_OSExecFlags_ enum DN_OSExecFlags_
@ -187,7 +166,7 @@ struct DN_OSExecArgs
DN_Slice<DN_Str8> environment; DN_Slice<DN_Str8> environment;
}; };
// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSSemaphore
DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX;
struct DN_OSSemaphore struct DN_OSSemaphore
@ -318,17 +297,15 @@ DN_API int DN_OS_MemProtect (v
DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem); DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem);
DN_API void DN_OS_MemDealloc (void *ptr); DN_API void DN_OS_MemDealloc (void *ptr);
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); DN_API DN_Date DN_OS_DateLocalTimeNow ();
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':');
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date time, char date_separator = '-', char hms_separator = ':');
DN_API DN_U64 DN_OS_DateUnixTimeNs (); DN_API DN_U64 DN_OS_DateUnixTimeNs ();
#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000) #define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000)
#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000)) #define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000))
#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000)) #define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000))
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time); DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date);
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS (DN_OSDateTime date); DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s);
DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date);
DN_API bool DN_OS_DateIsValid (DN_OSDateTime date);
DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size);
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);

View File

@ -96,10 +96,10 @@ DN_API void DN_OS_MemDealloc(void *ptr)
free(ptr); free(ptr);
} }
// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// // NOTE: Date
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() DN_API DN_Date DN_OS_DateLocalTimeNow()
{ {
DN_OSDateTime result = {}; DN_Date result = {};
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);
@ -117,47 +117,57 @@ DN_API DN_OSDateTime DN_OS_DateLocalTimeNow()
result.hour = time.tm_hour; result.hour = time.tm_hour;
result.minutes = time.tm_min; result.minutes = time.tm_min;
result.seconds = time.tm_sec; result.seconds = time.tm_sec;
result.milliseconds = ts.tv_nsec / (1000 * 1000); // TODO: Verify that getting the milliseconds like this is correct
result.day = DN_Cast(uint8_t) time.tm_mday; result.day = DN_Cast(DN_U8) time.tm_mday;
result.month = DN_Cast(uint8_t) time.tm_mon + 1; result.month = DN_Cast(DN_U8) time.tm_mon + 1;
result.year = 1900 + DN_Cast(int16_t) time.tm_year; result.year = 1900 + DN_Cast(DN_U16) time.tm_year;
return result; return result;
} }
DN_API uint64_t DN_OS_DateUnixTimeNs() DN_API DN_U64 DN_OS_DateUnixTimeNs()
{ {
struct timespec ts = {}; struct timespec ts = {};
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);
uint64_t result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec; DN_U64 result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec;
return result; return result;
} }
DN_API uint64_t DN_OS_DateLocalToUnixTimeS(DN_OSDateTime) DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate(DN_Date date)
{ {
DN_AssertOnce(!"Unimplemented"); struct tm tm_time = {0};
uint64_t result = 0; tm_time.tm_year = (int)date.year - 1900;
tm_time.tm_mon = (int)date.month - 1; // month is 1-12 in your struct
tm_time.tm_mday = (int)date.day; // day of month 1-31
tm_time.tm_hour = (int)date.hour;
tm_time.tm_min = (int)date.minutes;
tm_time.tm_sec = (int)date.seconds;
tm_time.tm_isdst = -1; // tm_isdst = -1 lets mktime() determine whether DST is in effect
time_t unix_time = mktime(&tm_time);
DN_U64 result = DN_Cast(DN_U64) unix_time;
return result; return result;
} }
DN_API uint64_t DN_OS_DateToUnixTimeS(DN_OSDateTime date) DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s)
{ {
DN_Assert(DN_OS_DateIsValid(date)); struct tm tm_local;
struct tm timeinfo = {}; void *ret = localtime_r(&unix_ts_s, &tm_local);
timeinfo.tm_year = date.year - 1900; DN_Assert(ret);
timeinfo.tm_mon = date.month - 1;
timeinfo.tm_mday = date.day; long local_offset_seconds = tm_local.tm_gmtoff;
timeinfo.tm_hour = date.hour; DN_U64 result = unix_ts_s;
timeinfo.tm_min = date.minutes; if (local_offset_seconds > 0)
timeinfo.tm_sec = date.seconds; result += local_offset_seconds;
uint64_t result = mktime(&timeinfo); else
result -= local_offset_seconds;
return result; return result;
} }
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(uint64_t time) DN_API DN_Date DN_OS_DateUnixTimeSToDate(DN_U64 time)
{ {
time_t posix_time = DN_Cast(time_t) time; time_t posix_time = DN_Cast(time_t) time;
struct tm posix_date = *gmtime(&posix_time); struct tm posix_date = *gmtime(&posix_time);
DN_OSDateTime result = {}; DN_Date result = {};
result.year = posix_date.tm_year + 1900; result.year = posix_date.tm_year + 1900;
result.month = posix_date.tm_mon + 1; result.month = posix_date.tm_mon + 1;
result.day = posix_date.tm_mday; result.day = posix_date.tm_mday;

View File

@ -125,19 +125,20 @@ DN_API void DN_OS_MemDealloc(void *ptr)
HeapFree(GetProcessHeap(), 0, ptr); HeapFree(GetProcessHeap(), 0, ptr);
} }
// NOTE: Date ////////////////////////////////////////////////////////////////////////////////////// // NOTE: Date
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() DN_API DN_Date DN_OS_DateLocalTimeNow()
{ {
SYSTEMTIME sys_time; SYSTEMTIME sys_time;
GetLocalTime(&sys_time); GetLocalTime(&sys_time);
DN_OSDateTime result = {}; DN_Date result = {};
result.hour = DN_Cast(uint8_t) sys_time.wHour; result.hour = DN_Cast(DN_U8) sys_time.wHour;
result.minutes = DN_Cast(uint8_t) sys_time.wMinute; result.milliseconds = DN_Cast(DN_U8) sys_time.wMilliseconds;
result.seconds = DN_Cast(uint8_t) sys_time.wSecond; result.minutes = DN_Cast(DN_U8) sys_time.wMinute;
result.day = DN_Cast(uint8_t) sys_time.wDay; result.seconds = DN_Cast(DN_U8) sys_time.wSecond;
result.month = DN_Cast(uint8_t) sys_time.wMonth; result.day = DN_Cast(DN_U8) sys_time.wDay;
result.year = DN_Cast(int16_t) sys_time.wYear; result.month = DN_Cast(DN_U8) sys_time.wMonth;
result.year = DN_Cast(DN_U16) sys_time.wYear;
return result; return result;
} }
@ -158,7 +159,7 @@ DN_API DN_U64 DN_OS_DateUnixTimeNs()
return result; return result;
} }
static SYSTEMTIME DN_OS_DateToSystemTime_(DN_OSDateTime date) static SYSTEMTIME DN_OS_DateToSystemTime_(DN_Date date)
{ {
SYSTEMTIME result = {}; SYSTEMTIME result = {};
result.wYear = date.year; result.wYear = date.year;
@ -167,6 +168,7 @@ static SYSTEMTIME DN_OS_DateToSystemTime_(DN_OSDateTime date)
result.wHour = date.hour; result.wHour = date.hour;
result.wMinute = date.minutes; result.wMinute = date.minutes;
result.wSecond = date.seconds; result.wSecond = date.seconds;
result.wMilliseconds = date.milliseconds;
return result; return result;
} }
@ -182,7 +184,7 @@ static DN_U64 DN_OS_SystemTimeToUnixTimeS_(SYSTEMTIME *sys_time)
return result; return result;
} }
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date) DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate(DN_Date date)
{ {
SYSTEMTIME local_time = DN_OS_DateToSystemTime_(date); SYSTEMTIME local_time = DN_OS_DateToSystemTime_(date);
SYSTEMTIME sys_time = {}; SYSTEMTIME sys_time = {};
@ -191,36 +193,17 @@ DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date)
return result; return result;
} }
DN_API DN_U64 DN_OS_DateToUnixTimeS(DN_OSDateTime date) DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s)
{ {
DN_Assert(DN_OS_DateIsValid(date)); DN_U64 unix_time = DN_Cast(DN_U64) unix_ts_s * 10000000LL; // seconds -> 100ns units
DN_U64 filetime_utc = unix_time + 116444736000000000LL; // Unix epoch -> Windows epoch
FILETIME ft_utc = {DN_Cast(DWORD) filetime_utc, DN_Cast(DWORD)(filetime_utc >> 32)};
FILETIME ft_local;
bool converted = FileTimeToLocalFileTime(&ft_utc, &ft_local);
DN_Assert(converted);
SYSTEMTIME sys_time = DN_OS_DateToSystemTime_(date); DN_U64 filetime_local = (DN_Cast(DN_U64) ft_local.dwHighDateTime << 32) | ft_local.dwLowDateTime;
DN_U64 result = DN_OS_SystemTimeToUnixTimeS_(&sys_time); DN_U64 result = (filetime_local - 116444736000000000LL) / 10000000LL;
return result;
}
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(DN_U64 time)
{
// NOTE: Windows epoch time starts from Jan 1, 1601 and counts in
// 100-nanoseconds intervals.
//
// See: https://devblogs.microsoft.com/oldnewthing/20090306-00/?p=18913
DN_U64 w32_time = 116'444'736'000'000'000 + (time * 10'000'000);
SYSTEMTIME sys_time = {};
FILETIME file_time = {};
file_time.dwLowDateTime = (DWORD)w32_time;
file_time.dwHighDateTime = w32_time >> 32;
FileTimeToSystemTime(&file_time, &sys_time);
DN_OSDateTime result = {};
result.year = DN_Cast(uint16_t) sys_time.wYear;
result.month = DN_Cast(uint8_t) sys_time.wMonth;
result.day = DN_Cast(uint8_t) sys_time.wDay;
result.hour = DN_Cast(uint8_t) sys_time.wHour;
result.minutes = DN_Cast(uint8_t) sys_time.wMinute;
result.seconds = DN_Cast(uint8_t) sys_time.wSecond;
return result; return result;
} }

View File

@ -534,9 +534,10 @@
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
__declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime);
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); __declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
__declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName); __declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName);
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);

View File

@ -165,7 +165,7 @@ int main(int argc, char **argv)
AppendCppFileLineByLine(&builder, extra_path); AppendCppFileLineByLine(&builder, extra_path);
} }
DN_OSDateTime date = DN_OS_DateLocalTimeNow(); DN_Date date = DN_OS_DateLocalTimeNow();
DN_Str8BuilderPrependF(&builder, "// Generated by the DN single header generator %04u-%02u-%02u %02u:%02u:%02u\n\n", date.year, date.month, date.day, date.hour, date.minutes, date.seconds); DN_Str8BuilderPrependF(&builder, "// Generated by the DN single header generator %04u-%02u-%02u %02u:%02u:%02u\n\n", date.year, date.month, date.day, date.hour, date.minutes, date.seconds);
DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8BuilderBuildFromTLS(&builder)); DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8BuilderBuildFromTLS(&builder));