소스 검색

time: Use a function instead of properties to retrieve the system date and time locale info

This allows applications to re-query the values if the system locale is changed during runtime, and better matches the other locale functions. A note is included in the documentation mentioning that this can be slow, as it has to call into OS functions.

Also allows for the removal of the init/quit time functions, as they are no longer needed.
Frank Praznik 11 달 전
부모
커밋
1f43c88220

+ 11 - 19
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
- */
-#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.
+ * \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 macro is available since SDL 3.0.0.
- *
- * \sa SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER
+ * \since This function is available since SDL 3.0.0.
  */
-#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

+ 0 - 3
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();

+ 1 - 0
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: *;
 };

+ 1 - 0
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

+ 1 - 0
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)

+ 7 - 22
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)

+ 0 - 3
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).
  */

+ 12 - 4
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;
+        }
     }
 }
 

+ 2 - 2
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;

+ 46 - 42
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);
-
-    /* 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;
+    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;
+                }
             }
         }
     }
 
 found_date:
 
-    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;
+    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;
+                }
             }
         }
     }

+ 2 - 2
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;

+ 2 - 2
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++) {

+ 20 - 0
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;
 }
 

+ 15 - 2
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);
             }
         }