diff --git a/core/libs/prx/libc/src/Time.cpp b/core/libs/prx/libc/src/Time.cpp index 1da075245..1a49ca85d 100644 --- a/core/libs/prx/libc/src/Time.cpp +++ b/core/libs/prx/libc/src/Time.cpp @@ -17,6 +17,9 @@ namespace { +constexpr const char* WEEKDAY_NAMES[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; +constexpr const char* MONTH_NAMES[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; +constexpr std::size_t ASCTIME_SIZE = sizeof("Sun Jan-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n"); constexpr std::int64_t SECONDS_PER_DAY = 86400; constexpr std::int64_t DAYS_FROM_MARCH_TO_YEAR_END = 306; @@ -324,8 +327,12 @@ size_t APS5_VABI libc_strftime_nid_postfix(char* str, size_t count, const char* } char* APS5_VABI asctime_nid_postfix(const GuestTm* timeptr) { - const std::tm host = toHostTm(*timeptr); - return std::asctime(&host); + static thread_local char result[ASCTIME_SIZE]; + const char* weekday = timeptr->tm_wday >= 0 && timeptr->tm_wday < 7 ? WEEKDAY_NAMES[timeptr->tm_wday] : "???"; + const char* month = timeptr->tm_mon >= 0 && timeptr->tm_mon < 12 ? MONTH_NAMES[timeptr->tm_mon] : "???"; + std::snprintf(result, sizeof(result), "%s %s%3d %.2d:%.2d:%.2d %lld\n", weekday, month, timeptr->tm_mday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, 1900LL + timeptr->tm_year); + return result; } char* APS5_VABI ctime_nid_postfix(const int64_t* timer) { diff --git a/core/libs/tests/GuestTimeConversion.cpp b/core/libs/tests/GuestTimeConversion.cpp index 3edc8418d..821b509de 100644 --- a/core/libs/tests/GuestTimeConversion.cpp +++ b/core/libs/tests/GuestTimeConversion.cpp @@ -19,6 +19,7 @@ GuestTm* APS5_VABI libc_localtime_nid_postfix(const std::int64_t*); GuestTm* APS5_VABI localtime_nid_postfix(const std::int64_t*); GuestTm* APS5_VABI gmtime_s_nid_postfix(const std::int64_t*, GuestTm*); GuestTm* APS5_VABI localtime_s_nid_postfix(const std::int64_t*, GuestTm*); +char* APS5_VABI asctime_nid_postfix(const GuestTm*); std::int64_t APS5_VABI mktime_nid_postfix(GuestTm*); std::size_t APS5_VABI strftime_nid_postfix(char*, std::size_t, const char*, const GuestTm*); void APS5_VABI tzset_nid_postfix(void); @@ -68,6 +69,17 @@ static void CheckConcurrent(Converter convert, BufferedConverter buffered, const Require(convert(&invalid) == nullptr, "Unrepresentable time was accepted"); } +static GuestTm UtcTime(std::int64_t timer) { + GuestTm utc{}; + Require(gmtime_s_nid_postfix(&timer, &utc) == &utc, "UTC conversion failed"); + return utc; +} + +static void CheckAsctime(const GuestTm& brokenDown, const char* expected) { + const char* text = asctime_nid_postfix(&brokenDown); + Require(text != nullptr && std::strcmp(text, expected) == 0, "asctime did not format the broken-down time"); +} + struct UtcCase { std::int64_t timer; int year; @@ -249,6 +261,14 @@ int main() { GuestTm scratch{}; Require(gmtime_s_nid_postfix(&underflow, &scratch) == nullptr, "Unrepresentable negative time was accepted"); + CheckAsctime(UtcTime(0), "Thu Jan 1 00:00:00 1970\n"); + CheckAsctime(UtcTime(-2208988801), "Sun Dec 31 23:59:59 1899\n"); + CheckAsctime(UtcTime(-30610224000), "Wed Jan 1 00:00:00 1000\n"); + GuestTm pastMonthEnd = UtcTime(983404800); + pastMonthEnd.tm_mon = 1; + pastMonthEnd.tm_mday = 29; + CheckAsctime(pastMonthEnd, "Thu Feb 29 00:00:00 2001\n"); + const std::int64_t epoch = 0; GuestTm local{}; std::memset(&local, 0xAA, sizeof(local));