SDL
1/*
2Simple DirectMedia Layer
3Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
4
5This software is provided 'as-is', without any express or implied
6warranty. In no event will the authors be held liable for any damages
7arising from the use of this software.
8
9Permission is granted to anyone to use this software for any purpose,
10including commercial applications, and to alter it and redistribute it
11freely, subject to the following restrictions:
12
131. The origin of this software must not be misrepresented; you must not
14claim that you wrote the original software. If you use this software
15in a product, an acknowledgment in the product documentation would be
16appreciated but is not required.
172. Altered source versions must be plainly marked as such, and must not be
18misrepresented as being the original software.
193. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"22
23#ifdef SDL_TIME_UNIX24
25#include "../SDL_time_c.h"26#include <errno.h>27#include <langinfo.h>28#include <sys/time.h>29#include <time.h>30
31#if !defined(HAVE_CLOCK_GETTIME) && defined(SDL_PLATFORM_APPLE)32#include <mach/clock.h>33#include <mach/mach.h>34#include <mach/mach_time.h>35#endif36
37void SDL_GetSystemTimeLocalePreferences(SDL_DateFormat *df, SDL_TimeFormat *tf)38{
39/* This *should* be well-supported aside from very old legacy systems, but apparently40* Android didn't add this until SDK version 26, so a check is needed...
41*/
42#ifdef HAVE_NL_LANGINFO43if (df) {44const char *s = nl_langinfo(D_FMT);45
46// Figure out the preferred system date format from the first format character.47if (s) {48while (*s) {49switch (*s++) {50case 'Y':51case 'y':52case 'F':53case 'C':54*df = SDL_DATE_FORMAT_YYYYMMDD;55goto found_date;56case 'd':57case 'e':58*df = SDL_DATE_FORMAT_DDMMYYYY;59goto found_date;60case 'b':61case 'D':62case 'h':63case 'm':64*df = SDL_DATE_FORMAT_MMDDYYYY;65goto found_date;66default:67break;68}69}70}71}72
73found_date:74
75if (tf) {76const char *s = nl_langinfo(T_FMT);77
78// Figure out the preferred system date format.79if (s) {80while (*s) {81switch (*s++) {82case 'H':83case 'k':84case 'T':85*tf = SDL_TIME_FORMAT_24HR;86return;87case 'I':88case 'l':89case 'r':90*tf = SDL_TIME_FORMAT_12HR;91return;92default:93break;94}95}96}97}98#endif99}
100
101SDL_bool SDL_GetCurrentTime(SDL_Time *ticks)102{
103if (!ticks) {104return SDL_InvalidParamError("ticks");105}106#ifdef HAVE_CLOCK_GETTIME107struct timespec tp;108
109if (clock_gettime(CLOCK_REALTIME, &tp) == 0) {110//tp.tv_sec = SDL_min(tp.tv_sec, SDL_NS_TO_SECONDS(SDL_MAX_TIME) - 1);111*ticks = SDL_SECONDS_TO_NS(tp.tv_sec) + tp.tv_nsec;112return true;113}114
115SDL_SetError("Failed to retrieve system time (%i)", errno);116
117#elif defined(SDL_PLATFORM_APPLE)118clock_serv_t cclock;119int ret = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);120if (ret == 0) {121mach_timespec_t mts;122
123SDL_zero(mts);124ret = clock_get_time(cclock, &mts);125if (ret == 0) {126// mach_timespec_t tv_sec is 32-bit, so no overflow possible127*ticks = SDL_SECONDS_TO_NS(mts.tv_sec) + mts.tv_nsec;128}129mach_port_deallocate(mach_task_self(), cclock);130
131if (!ret) {132return true;133}134}135
136SDL_SetError("Failed to retrieve system time (%i)", ret);137
138#else139struct timeval tv;140SDL_zero(tv);141if (gettimeofday(&tv, NULL) == 0) {142tv.tv_sec = SDL_min(tv.tv_sec, SDL_NS_TO_SECONDS(SDL_MAX_TIME) - 1);143*ticks = SDL_SECONDS_TO_NS(tv.tv_sec) + SDL_US_TO_NS(tv.tv_usec);144return true;145}146
147SDL_SetError("Failed to retrieve system time (%i)", errno);148#endif149
150return false;151}
152
153SDL_bool SDL_TimeToDateTime(SDL_Time ticks, SDL_DateTime *dt, SDL_bool localTime)154{
155#if defined (HAVE_GMTIME_R) || defined(HAVE_LOCALTIME_R)156struct tm tm_storage;157#endif158struct tm *tm = NULL;159
160if (!dt) {161return SDL_InvalidParamError("dt");162}163
164const time_t tval = (time_t)SDL_NS_TO_SECONDS(ticks);165
166if (localTime) {167#ifdef HAVE_LOCALTIME_R168tm = localtime_r(&tval, &tm_storage);169#else170tm = localtime(&tval);171#endif172} else {173#ifdef HAVE_GMTIME_R174tm = gmtime_r(&tval, &tm_storage);175#else176tm = gmtime(&tval);177#endif178}179
180if (tm) {181dt->year = tm->tm_year + 1900;182dt->month = tm->tm_mon + 1;183dt->day = tm->tm_mday;184dt->hour = tm->tm_hour;185dt->minute = tm->tm_min;186dt->second = tm->tm_sec;187dt->nanosecond = ticks % SDL_NS_PER_SECOND;188dt->day_of_week = tm->tm_wday;189dt->utc_offset = (int)tm->tm_gmtoff;190
191return true;192}193
194return SDL_SetError("SDL_DateTime conversion failed (%i)", errno);195}
196
197#endif // SDL_TIME_UNIX198