diff --git a/include/SDL3/SDL_time.h b/include/SDL3/SDL_time.h index 193c29cea..204a0419b 100644 --- a/include/SDL3/SDL_time.h +++ b/include/SDL3/SDL_time.h @@ -61,7 +61,7 @@ typedef struct SDL_DateTime * * \since This enum is available since SDL 3.0.0. * - * \sa SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER + * \sa SDL_GetDateTimeLocalePreferences */ typedef enum SDL_DateFormat { @@ -75,7 +75,7 @@ typedef enum SDL_DateFormat * * \since This enum is available since SDL 3.0.0. * - * \sa SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER + * \sa SDL_GetDateTimeLocalePreferences */ typedef enum SDL_TimeFormat { @@ -83,28 +83,20 @@ typedef enum SDL_TimeFormat SDL_TIME_FORMAT_12HR = 1 /**< 12 hour time */ } SDL_TimeFormat; -/* Global date/time properties. */ - /** - * The SDL_DateFormat to use as the preferred date display format for the - * current system locale. + * Gets the current preferred date and time format for the system locale. * - * \since This macro is available since SDL 3.0.0. + * This might be a "slow" call that has to query the operating system. It's + * best to ask for this once and save the results. However, the preferred formats + * can change, usually because the user has changed a system preference outside of + * your program. * - * \sa SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER + * \param dateFormat a pointer to the SDL_DateFormat to hold the returned date format, may be NULL + * \param timeFormat a pointer to the SDL_TimeFormat to hold the returned time format, may be NULL + * + * \since This function is available since SDL 3.0.0. */ -#define SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER "SDL.time.date_format" - -/** - * The SDL_TimeFormat to use as the preferred time display format for the - * current system locale. - * - * \since This macro is available since SDL 3.0.0. - * - * \sa SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER - */ -#define SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER "SDL.time.time_format" - +extern DECLSPEC int SDLCALL SDL_GetDateTimeLocalePreferences(SDL_DateFormat *dateFormat, SDL_TimeFormat *timeFormat); /** * Gets the current value of the system realtime clock in nanoseconds since diff --git a/src/SDL.c b/src/SDL.c index 1b3912f8c..943004300 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -53,7 +53,6 @@ #define SDL_INIT_EVERYTHING ~0U /* Initialization/Cleanup routines */ -#include "time/SDL_time_c.h" #include "timer/SDL_timer_c.h" #ifdef SDL_VIDEO_DRIVER_WINDOWS extern int SDL_HelperWindowCreate(void); @@ -210,7 +209,6 @@ int SDL_InitSubSystem(Uint32 flags) } #endif - SDL_InitTime(); SDL_InitTicks(); /* Initialize the event subsystem */ @@ -543,7 +541,6 @@ void SDL_Quit(void) SDL_QuitSubSystem(SDL_INIT_EVERYTHING); SDL_QuitTicks(); - SDL_QuitTime(); #ifdef SDL_USE_LIBDBUS SDL_DBus_Quit(); diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 2ba2be484..6f4c658e1 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1015,6 +1015,7 @@ SDL3_0.0.0 { SDL_wcsnstr; SDL_wcsstr; SDL_wcstol; + SDL_GetDateTimeLocalePreferences; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 7dbc24eb4..bfd37314f 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1039,3 +1039,4 @@ #define SDL_wcsnstr SDL_wcsnstr_REAL #define SDL_wcsstr SDL_wcsstr_REAL #define SDL_wcstol SDL_wcstol_REAL +#define SDL_GetDateTimeLocalePreferences SDL_GetDateTimeLocalePreferences_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 5b4047195..e92cd9884 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1055,3 +1055,4 @@ SDL_DYNAPI_PROC(size_t,SDL_wcsnlen,(const wchar_t *a, size_t b),(a,b),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),return) SDL_DYNAPI_PROC(long,SDL_wcstol,(const wchar_t *a, wchar_t **b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_GetDateTimeLocalePreferences,(SDL_DateFormat *a, SDL_TimeFormat *b),(a,b),return) diff --git a/src/time/SDL_time.c b/src/time/SDL_time.c index c14d2f643..2a3244bc5 100644 --- a/src/time/SDL_time.c +++ b/src/time/SDL_time.c @@ -22,8 +22,6 @@ #include "SDL_time_c.h" -static SDL_bool time_initialized; - /* The following algorithms are based on those of Howard Hinnant and are in the public domain. * * http://howardhinnant.github.io/date_algorithms.html @@ -59,32 +57,19 @@ Sint64 SDL_CivilToDays(int year, int month, int day, int *day_of_week, int *day_ return z; } -void SDL_InitTime() +int SDL_GetDateTimeLocalePreferences(SDL_DateFormat *dateFormat, SDL_TimeFormat *timeFormat) { - if (time_initialized) { - return; - } - /* Default to ISO 8061 date format, as it is unambiguous, and 24 hour time. */ - SDL_DateFormat dateFormat = SDL_DATE_FORMAT_YYYYMMDD; - SDL_TimeFormat timeFormat = SDL_TIME_FORMAT_24HR; - SDL_PropertiesID props = SDL_GetGlobalProperties(); - - SDL_GetSystemTimeLocalePreferences(&dateFormat, &timeFormat); - - if (!SDL_HasProperty(props, SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER)) { - SDL_SetNumberProperty(props, SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER, dateFormat); + if (dateFormat) { + *dateFormat = SDL_DATE_FORMAT_YYYYMMDD; } - if (!SDL_HasProperty(props, SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER)) { - SDL_SetNumberProperty(props, SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER, timeFormat); + if (timeFormat) { + *timeFormat = SDL_TIME_FORMAT_24HR; } - time_initialized = SDL_TRUE; -} + SDL_GetSystemTimeLocalePreferences(dateFormat, timeFormat); -void SDL_QuitTime() -{ - time_initialized = SDL_FALSE; + return 0; } int SDL_GetDaysInMonth(int year, int month) diff --git a/src/time/SDL_time_c.h b/src/time/SDL_time_c.h index d91b37880..5c92f0cd9 100644 --- a/src/time/SDL_time_c.h +++ b/src/time/SDL_time_c.h @@ -26,9 +26,6 @@ #define SDL_SECONDS_PER_DAY 86400 -extern void SDL_InitTime(void); -extern void SDL_QuitTime(void); - /* Given a calendar date, returns days since Jan 1 1970, and optionally * the day of the week (0-6, 0 is Sunday) and day of the year (0-365). */ diff --git a/src/time/n3ds/SDL_systime.c b/src/time/n3ds/SDL_systime.c index a54f99741..2a470af5d 100644 --- a/src/time/n3ds/SDL_systime.c +++ b/src/time/n3ds/SDL_systime.c @@ -86,15 +86,23 @@ void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf) return; } - *df = LANG_TO_DATE_FORMAT[system_language]; - *tf = SDL_TIME_FORMAT_24HR; + if (df) { + *df = LANG_TO_DATE_FORMAT[system_language]; + } + if (tf) { + *tf = SDL_TIME_FORMAT_24HR; + } /* Only American English (en_US) uses MM/DD/YYYY and 12hr system, this gets the formats wrong for canadians though (en_CA) */ if (system_language == CFG_LANGUAGE_EN && R_SUCCEEDED(has_region) && is_north_america) { - *df = SDL_DATE_FORMAT_MMDDYYYY; - *tf = SDL_TIME_FORMAT_12HR; + if (df) { + *df = SDL_DATE_FORMAT_MMDDYYYY; + } + if (tf) { + *tf = SDL_TIME_FORMAT_12HR; + } } } diff --git a/src/time/psp/SDL_systime.c b/src/time/psp/SDL_systime.c index ac85b4264..df2d588c8 100644 --- a/src/time/psp/SDL_systime.c +++ b/src/time/psp/SDL_systime.c @@ -34,7 +34,7 @@ void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf) { int val; - if (sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_DATE_FORMAT, &val) == 0) { + if (df && sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_DATE_FORMAT, &val) == 0) { switch (val) { case PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD: *df = SDL_DATE_FORMAT_YYYYMMDD; @@ -50,7 +50,7 @@ void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf) } } - if (sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_TIME_FORMAT, &val) == 0) { + if (tf && sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_TIME_FORMAT, &val) == 0) { switch (val) { case PSP_SYSTEMPARAM_TIME_FORMAT_24HR: *tf = SDL_TIME_FORMAT_24HR; diff --git a/src/time/unix/SDL_systime.c b/src/time/unix/SDL_systime.c index 286bd7b72..8f3cb7fc6 100644 --- a/src/time/unix/SDL_systime.c +++ b/src/time/unix/SDL_systime.c @@ -40,54 +40,58 @@ void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf) * Android didn't add this until SDK version 26, so a check is needed... */ #ifdef HAVE_NL_LANGINFO - const char *s = nl_langinfo(D_FMT); + if (df) { + const char *s = nl_langinfo(D_FMT); - /* Figure out the preferred system date format from the first format character. */ - if (s) { - while (*s) { - switch (*s++) { - case 'Y': - case 'y': - case 'F': - case 'C': - *df = SDL_DATE_FORMAT_YYYYMMDD; - goto found_date; - case 'd': - case 'e': - *df = SDL_DATE_FORMAT_DDMMYYYY; - goto found_date; - case 'b': - case 'D': - case 'h': - case 'm': - *df = SDL_DATE_FORMAT_MMDDYYYY; - goto found_date; - default: - break; + /* Figure out the preferred system date format from the first format character. */ + if (s) { + while (*s) { + switch (*s++) { + case 'Y': + case 'y': + case 'F': + case 'C': + *df = SDL_DATE_FORMAT_YYYYMMDD; + goto found_date; + case 'd': + case 'e': + *df = SDL_DATE_FORMAT_DDMMYYYY; + goto found_date; + case 'b': + case 'D': + case 'h': + case 'm': + *df = SDL_DATE_FORMAT_MMDDYYYY; + goto found_date; + default: + break; + } } } } found_date: - s = nl_langinfo(T_FMT); + if (tf) { + const char *s = nl_langinfo(T_FMT); - /* Figure out the preferred system date format. */ - if (s) { - while (*s) { - switch (*s++) { - case 'H': - case 'k': - case 'T': - *tf = SDL_TIME_FORMAT_24HR; - return; - case 'I': - case 'l': - case 'r': - *tf = SDL_TIME_FORMAT_12HR; - return; - default: - break; + /* Figure out the preferred system date format. */ + if (s) { + while (*s) { + switch (*s++) { + case 'H': + case 'k': + case 'T': + *tf = SDL_TIME_FORMAT_24HR; + return; + case 'I': + case 'l': + case 'r': + *tf = SDL_TIME_FORMAT_12HR; + return; + default: + break; + } } } } diff --git a/src/time/vita/SDL_systime.c b/src/time/vita/SDL_systime.c index 64ce32e90..767910f0a 100644 --- a/src/time/vita/SDL_systime.c +++ b/src/time/vita/SDL_systime.c @@ -39,7 +39,7 @@ void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf) SDL_zero(bootParam); sceAppUtilInit(&initParam, &bootParam); - if (sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_DATE_FORMAT, &val) == 0) { + if (df && sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_DATE_FORMAT, &val) == 0) { switch (val) { case SCE_SYSTEM_PARAM_DATE_FORMAT_YYYYMMDD: *df = SDL_DATE_FORMAT_YYYYMMDD; @@ -55,7 +55,7 @@ void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf) } } - if (sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_DATE_FORMAT, &val) == 0) { + if (tf && sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_DATE_FORMAT, &val) == 0) { switch (val) { case SCE_SYSTEM_PARAM_TIME_FORMAT_24HR: *tf = SDL_TIME_FORMAT_24HR; diff --git a/src/time/windows/SDL_systime.c b/src/time/windows/SDL_systime.c index 064bbb172..fadee1f46 100644 --- a/src/time/windows/SDL_systime.c +++ b/src/time/windows/SDL_systime.c @@ -38,7 +38,7 @@ void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf) { WCHAR str[80]; /* Per the docs, the time and short date format strings can be a max of 80 characters. */ - if (GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, str, sizeof(str) / sizeof(WCHAR))) { + if (df && GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, str, sizeof(str) / sizeof(WCHAR))) { LPWSTR s = str; while (*s) { switch (*s++) { @@ -60,7 +60,7 @@ void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf) found_date: /* Figure out the preferred system date format. */ - if (GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, str, sizeof(str) / sizeof(WCHAR))) { + if (tf && GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, str, sizeof(str) / sizeof(WCHAR))) { LPWSTR s = str; while (*s) { switch (*s++) { diff --git a/test/testautomation_time.c b/test/testautomation_time.c index 1385ff98a..eaac52a41 100644 --- a/test/testautomation_time.c +++ b/test/testautomation_time.c @@ -169,6 +169,26 @@ static int time_dateTimeUtilities(void *arg) SDLTest_AssertPass("Call to SDL_TimeFromWindows()"); SDLTest_AssertCheck(ticks > 0 && ticks <= SDL_MAX_TIME, "Check result value, expected >0 && <=%" SDL_PRIs64 ", got: %" SDL_PRIs64, SDL_MAX_TIME, ticks); + /* Test time locale functions */ + SDL_DateFormat dateFormat; + SDL_TimeFormat timeFormat; + + result = SDL_GetDateTimeLocalePreferences(&dateFormat, &timeFormat); + SDLTest_AssertPass("Call to SDL_GetDateTimeLocalePreferences(&dateFormat, &timeFormat)"); + SDLTest_AssertCheck(result == 0, "Check result value, expected 0, got: %i", result); + + result = SDL_GetDateTimeLocalePreferences(&dateFormat, NULL); + SDLTest_AssertPass("Call to SDL_GetDateTimeLocalePreferences(&dateFormat, NULL)"); + SDLTest_AssertCheck(result == 0, "Check result value, expected 0, got: %i", result); + + result = SDL_GetDateTimeLocalePreferences(NULL, &timeFormat); + SDLTest_AssertPass("Call to SDL_GetDateTimeLocalePreferences(NULL, &timeFormat)"); + SDLTest_AssertCheck(result == 0, "Check result value, expected 0, got: %i", result); + + result = SDL_GetDateTimeLocalePreferences(NULL, NULL); + SDLTest_AssertPass("Call to SDL_GetDateTimeLocalePreferences(NULL, NULL)"); + SDLTest_AssertCheck(result == 0, "Check result value, expected 0, got: %i", result); + return TEST_COMPLETED; } diff --git a/test/testtime.c b/test/testtime.c index 956bdc616..3382585d3 100644 --- a/test/testtime.c +++ b/test/testtime.c @@ -79,6 +79,18 @@ static void RenderDateTime(SDL_Renderer *r) SDLTest_DrawString(r, 10, 15, str); SDL_TimeToDateTime(ticks, &dt, SDL_TRUE); + if (time_format) { + if (dt.hour > 12) { /* PM */ + dt.hour -= 12; + postfix = TIMEPOST[2]; + } else { + if (!dt.hour) { /* AM */ + dt.hour = 12; /* Midnight */ + } + postfix = TIMEPOST[1]; + } + } + SDL_snprintf(str, sizeof(str), "Local: %s %02d %s %04d (%s) %02d:%02d:%02d.%09d%s %+05d", WDAY[dt.day_of_week], dt.day, MNAME[dt.month - 1], dt.year, short_date, dt.hour, dt.minute, dt.second, dt.nanosecond, postfix, @@ -154,8 +166,7 @@ int main(int argc, char *argv[]) goto quit; } - time_format = SDL_GetNumberProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER, SDL_TIME_FORMAT_24HR); - date_format = SDL_GetNumberProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER, SDL_DATE_FORMAT_YYYYMMDD); + SDL_GetDateTimeLocalePreferences(&date_format, &time_format); /* Main render loop */ done = 0; @@ -196,6 +207,8 @@ int main(int argc, char *argv[]) default: break; } + } else if (event.type == SDL_EVENT_LOCALE_CHANGED) { + SDL_GetDateTimeLocalePreferences(&date_format, &time_format); } }