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:
yellows8 2018-10-05 19:47:49 -04:00
parent dc011024f9
commit 4fb364060c
3 changed files with 104 additions and 1 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;
}