mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
Added support for timezones, hence localtime() will now return actual localtime. Added timeToCalendarTimeWithMyRule and TimeCalendarTime/TimeCalendarAdditionalInfo, which are used for timezones support.
This commit is contained in:
parent
dc011024f9
commit
4fb364060c
@ -17,6 +17,24 @@ typedef enum {
|
|||||||
TimeType_Default = TimeType_UserSystemClock,
|
TimeType_Default = TimeType_UserSystemClock,
|
||||||
} TimeType;
|
} TimeType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u16 year;
|
||||||
|
u8 month;
|
||||||
|
u8 day;
|
||||||
|
u8 hour;
|
||||||
|
u8 minute;
|
||||||
|
u8 second;
|
||||||
|
u8 pad;
|
||||||
|
} TimeCalendarTime;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 wday; ///< 0-based day-of-week.
|
||||||
|
u32 yday; ///< 0-based day-of-year.
|
||||||
|
char timezoneName[8]; ///< Timezone name string.
|
||||||
|
u32 DST; ///< 0 = no DST, 1 = DST.
|
||||||
|
s32 offset; ///< Seconds relative to UTC for this timezone.
|
||||||
|
} TimeCalendarAdditionalInfo;
|
||||||
|
|
||||||
Result timeInitialize(void);
|
Result timeInitialize(void);
|
||||||
void timeExit(void);
|
void timeExit(void);
|
||||||
|
|
||||||
@ -31,3 +49,6 @@ Result timeGetCurrentTime(TimeType type, u64 *timestamp);
|
|||||||
* @return Result code.
|
* @return Result code.
|
||||||
*/
|
*/
|
||||||
Result timeSetCurrentTime(TimeType type, u64 timestamp);
|
Result timeSetCurrentTime(TimeType type, u64 timestamp);
|
||||||
|
|
||||||
|
Result timeToCalendarTimeWithMyRule(u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info);
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
@ -31,12 +33,17 @@ static struct _reent* __libnx_get_reent(void) {
|
|||||||
return tv->reent;
|
return tv->reent;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: timeGetCurrentTime() returns UTC time. How to handle timezones?
|
|
||||||
static u64 __boottime;
|
static u64 __boottime;
|
||||||
static u64 __bootticks;
|
static u64 __bootticks;
|
||||||
|
|
||||||
// setup boot time variables
|
// setup boot time variables
|
||||||
void __libnx_init_time(void) {
|
void __libnx_init_time(void) {
|
||||||
|
TimeCalendarAdditionalInfo info;
|
||||||
|
char envstr[64];
|
||||||
|
char *strptr;
|
||||||
|
bool is_west=0;
|
||||||
|
s32 tmp_offset, hour, minute, second;
|
||||||
|
|
||||||
Result rc = timeGetCurrentTime(__nx_time_type, &__boottime);
|
Result rc = timeGetCurrentTime(__nx_time_type, &__boottime);
|
||||||
if (R_FAILED(rc) && __nx_time_type != TimeType_Default) rc = timeGetCurrentTime(TimeType_Default, &__boottime);
|
if (R_FAILED(rc) && __nx_time_type != TimeType_Default) rc = timeGetCurrentTime(TimeType_Default, &__boottime);
|
||||||
if (R_FAILED(rc)) {
|
if (R_FAILED(rc)) {
|
||||||
@ -44,6 +51,43 @@ void __libnx_init_time(void) {
|
|||||||
} else {
|
} else {
|
||||||
__bootticks = armGetSystemTick();
|
__bootticks = armGetSystemTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = timeToCalendarTimeWithMyRule(__boottime, NULL, &info);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
info.timezoneName[7] = 0;
|
||||||
|
tmp_offset = info.offset;
|
||||||
|
if (tmp_offset < 0) {
|
||||||
|
is_west = 1;
|
||||||
|
tmp_offset = -tmp_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
second = tmp_offset % 60;
|
||||||
|
tmp_offset /= 60;
|
||||||
|
minute = tmp_offset % 60;
|
||||||
|
tmp_offset /= 60;
|
||||||
|
hour = tmp_offset % 24;
|
||||||
|
|
||||||
|
memset(envstr, 0, sizeof(envstr));
|
||||||
|
|
||||||
|
//Avoid using *printf.
|
||||||
|
strncpy(envstr, info.timezoneName, sizeof(envstr)-1);
|
||||||
|
strptr = &envstr[strlen(envstr)];
|
||||||
|
*strptr++ = is_west ? '+' : '-';
|
||||||
|
|
||||||
|
*strptr++ = '0' + (hour / 10);
|
||||||
|
*strptr++ = '0' + (hour % 10);
|
||||||
|
*strptr++ = ':';
|
||||||
|
|
||||||
|
*strptr++ = '0' + (minute / 10);
|
||||||
|
*strptr++ = '0' + (minute % 10);
|
||||||
|
*strptr++ = ':';
|
||||||
|
|
||||||
|
*strptr++ = '0' + (second / 10);
|
||||||
|
*strptr++ = '0' + (second % 10);
|
||||||
|
|
||||||
|
setenv("TZ", envstr, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const u64 nsec_clockres = 1000000000ULL / 19200000ULL;
|
static const u64 nsec_clockres = 1000000000ULL / 19200000ULL;
|
||||||
|
@ -191,3 +191,41 @@ Result timeSetCurrentTime(TimeType type, u64 timestamp) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result timeToCalendarTimeWithMyRule(u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u64 timestamp;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 101;
|
||||||
|
raw->timestamp = timestamp;
|
||||||
|
|
||||||
|
Result rc = serviceIpcDispatch(&g_timeTimeZoneService);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
TimeCalendarTime caltime;
|
||||||
|
TimeCalendarAdditionalInfo info;
|
||||||
|
} *resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && caltime) memcpy(caltime, &resp->caltime, sizeof(TimeCalendarTime));
|
||||||
|
if (R_SUCCEEDED(rc) && info) memcpy(info, &resp->info, sizeof(TimeCalendarAdditionalInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user