localtime: rudimentary, incorrect support for timezone offsets
This commit is contained in:
parent
64bfcce029
commit
0d71c98cc2
2
Makefile
2
Makefile
@ -44,7 +44,7 @@ EMU_ARGS += -smp $(SMP)
|
||||
EMU_ARGS += ${EMU_KVM}
|
||||
EMU_ARGS += -no-reboot
|
||||
EMU_ARGS += -serial mon:stdio
|
||||
EMU_ARGS += -rtc base=localtime
|
||||
EMU_ARGS += -rtc base=utc
|
||||
EMU_ARGS += -soundhw pcspk,ac97
|
||||
|
||||
# Configures two network devices on the same network
|
||||
|
@ -32,7 +32,7 @@ static void show_usage(int argc, char * argv[]) {
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
char * format = "%a %b %d %T %Y";
|
||||
char * format = "%a %b %d %T %Y %Z";
|
||||
struct tm * timeinfo;
|
||||
struct timeval now;
|
||||
char buf[BUFSIZ] = {0};
|
||||
|
@ -6,6 +6,9 @@ export-cmd START kcmdline -g start
|
||||
export USER=root
|
||||
export HOME=/home/root
|
||||
|
||||
export TZ=JST
|
||||
export TZ_OFFSET=32400
|
||||
|
||||
export-cmd GETTY_ARGS qemu-fwcfg opt/org.toaruos.gettyargs
|
||||
|
||||
echo -n "Launching startup application..." > /dev/pex/splash
|
||||
|
@ -16,6 +16,9 @@ struct tm {
|
||||
int tm_wday; /* Day of the week (0-6, Sunday = 0) */
|
||||
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
|
||||
int tm_isdst; /* Daylight saving time */
|
||||
|
||||
const char * _tm_zone_name;
|
||||
int _tm_zone_offset;
|
||||
};
|
||||
|
||||
extern struct tm *localtime(const time_t *timep);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SEC_DAY 86400
|
||||
|
||||
@ -58,73 +60,97 @@ static long secs_of_month(int months, int year) {
|
||||
return days * SEC_DAY;
|
||||
}
|
||||
|
||||
struct tm *localtime_r(const time_t *timep, struct tm * _timevalue) {
|
||||
static struct tm * fill_time(const time_t * timep, struct tm * _timevalue, const char * tzName, int tzOffset) {
|
||||
|
||||
fprintf(stderr, "Hello world? %p %d\n", _timevalue, *timep);
|
||||
|
||||
long seconds = 0; // this needs to be bigger, but whatever
|
||||
time_t timeVal = *timep + tzOffset;
|
||||
_timevalue->_tm_zone_name = tzName;
|
||||
_timevalue->_tm_zone_offset = tzOffset;
|
||||
|
||||
long seconds = 0;
|
||||
long year_sec = 0;
|
||||
|
||||
for (int year = 1970; year < 2100; ++year) {
|
||||
fprintf(stderr, "Checking year %d\n", year);
|
||||
int startYear = timeVal < 0 ? 1900 : 1970;
|
||||
|
||||
for (int year = startYear; year < 2100; ++year) {
|
||||
long added = year_is_leap(year) ? 366 : 365;
|
||||
fprintf(stderr, "adding %d...\n", added);
|
||||
long secs = added * 86400;
|
||||
|
||||
if (seconds + secs > *timep) {
|
||||
if (seconds + secs > timeVal) {
|
||||
_timevalue->tm_year = year - 1900;
|
||||
year_sec = seconds;
|
||||
fprintf(stderr, "The year is %d, year_sec=%d\n", year, year_sec);
|
||||
for (int month = 1; month <= 12; ++month) {
|
||||
fprintf(stderr, "Checking %d\n", month);
|
||||
secs = days_in_month(month, year) * SEC_DAY;
|
||||
fprintf(stderr, "%d vs %d\n", seconds + secs, *timep);
|
||||
if (seconds + secs > *timep) {
|
||||
fprintf(stderr, "The month is %d.\n", month);
|
||||
if (seconds + secs > timeVal) {
|
||||
_timevalue->tm_mon = month - 1;
|
||||
for (int day = 1; day <= days_in_month(month, year); ++day) {
|
||||
secs = 60 * 60 * 24;
|
||||
fprintf(stderr, "Checking day %d, %d vs . %d\n", day, seconds + secs, *timep);
|
||||
if (seconds + secs > *timep) {
|
||||
fprintf(stderr, "The day is %d.\n", day);
|
||||
if (seconds + secs > timeVal) {
|
||||
_timevalue->tm_mday = day;
|
||||
for (int hour = 1; hour <= 24; ++hour) {
|
||||
secs = 60 * 60;
|
||||
if (seconds + secs > *timep) {
|
||||
long remaining = *timep - seconds;
|
||||
if (seconds + secs > timeVal) {
|
||||
long remaining = timeVal - seconds;
|
||||
_timevalue->tm_hour = hour - 1;
|
||||
_timevalue->tm_min = remaining / 60;
|
||||
_timevalue->tm_sec = remaining % 60; // can be 60 on a leap second, ignore that
|
||||
_timevalue->tm_wday = day_of_week(*timep); // oh shit
|
||||
_timevalue->tm_yday = (*timep - year_sec) / SEC_DAY;
|
||||
_timevalue->tm_isdst = 0; // never because UTC
|
||||
_timevalue->tm_sec = remaining % 60;
|
||||
_timevalue->tm_wday = day_of_week(timeVal);
|
||||
_timevalue->tm_yday = (timeVal - year_sec) / SEC_DAY;
|
||||
_timevalue->tm_isdst = 0;
|
||||
return _timevalue;
|
||||
} else {
|
||||
seconds += secs;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Failed but this is definitely the right day, returning NULL (seconds = %dbut need %d)\n", seconds, *timep);
|
||||
return NULL;
|
||||
} else {
|
||||
seconds += secs;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Failed but this is definitely the right month, returning NULL\n");
|
||||
return NULL;
|
||||
} else {
|
||||
seconds += secs;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Failed but this is definitely the right year, returning NULL\n");
|
||||
return NULL;
|
||||
} else {
|
||||
seconds += secs;
|
||||
}
|
||||
}
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Uh, no?\n");
|
||||
return (void *)0; /// uh what
|
||||
#define HOURS 3600
|
||||
#define MINUTES 60
|
||||
|
||||
static char * get_timezone(void) {
|
||||
char * tzEnv = getenv("TZ");
|
||||
if (!tzEnv || strlen(tzEnv) != 3) return "UTC";
|
||||
return tzEnv;
|
||||
}
|
||||
|
||||
static int get_timezone_offset(void) {
|
||||
char * tzOff = getenv("TZ_OFFSET");
|
||||
if (!tzOff) return 0;
|
||||
char * endptr;
|
||||
int out = strtol(tzOff,&endptr,10);
|
||||
if (*endptr) return 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
struct tm *localtime_r(const time_t *timep, struct tm * _timevalue) {
|
||||
return fill_time(timep, _timevalue, get_timezone(), get_timezone_offset());
|
||||
}
|
||||
|
||||
struct tm * gmtime_r(const time_t * timep, struct tm * tm) {
|
||||
return fill_time(timep, tm, "UTC", 0);
|
||||
}
|
||||
|
||||
struct tm * localtime(const time_t *timep) {
|
||||
return fill_time(timep, &_timevalue, get_timezone(), get_timezone_offset());
|
||||
}
|
||||
|
||||
struct tm *gmtime(const time_t *timep) {
|
||||
return fill_time(timep, &_timevalue, "UTC", 0);
|
||||
}
|
||||
|
||||
static unsigned int secs_of_years(int years) {
|
||||
@ -147,19 +173,7 @@ time_t mktime(struct tm *tm) {
|
||||
(tm->tm_mday - 1) * 86400 +
|
||||
(tm->tm_hour) * 3600 +
|
||||
(tm->tm_min) * 60 +
|
||||
(tm->tm_sec);
|
||||
|
||||
(tm->tm_sec) - tm->_tm_zone_offset;
|
||||
}
|
||||
|
||||
struct tm * gmtime_r(const time_t * timep, struct tm * tm) {
|
||||
return localtime_r(timep, tm);
|
||||
}
|
||||
|
||||
struct tm * localtime(const time_t *timep) {
|
||||
return localtime_r(timep, &_timevalue);
|
||||
}
|
||||
|
||||
struct tm *gmtime(const time_t *timep) {
|
||||
return localtime(timep);
|
||||
}
|
||||
|
||||
|
@ -142,6 +142,9 @@ size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tm) {
|
||||
tm->tm_hour,
|
||||
tm->tm_min);
|
||||
break;
|
||||
case 's':
|
||||
b += sprintf(b, "%ld", mktime((struct tm*)tm));
|
||||
break;
|
||||
case 'S':
|
||||
b += sprintf(b, "%02d", tm->tm_sec);
|
||||
break;
|
||||
@ -176,17 +179,20 @@ size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tm) {
|
||||
b += sprintf(b, "%04d", tm->tm_year + 1900);
|
||||
break;
|
||||
case 'z':
|
||||
b += sprintf(b, "+0000");
|
||||
if (tm->_tm_zone_offset >= 0) {
|
||||
b += sprintf(b, "+%04d", tm->_tm_zone_offset);
|
||||
} else {
|
||||
b += sprintf(b, "-%04d", -tm->_tm_zone_offset);
|
||||
}
|
||||
break;
|
||||
case 'Z':
|
||||
b += sprintf(b, "UTC");
|
||||
b += sprintf(b, tm->_tm_zone_name);
|
||||
break;
|
||||
case '%':
|
||||
b += sprintf(b, "%c", '%');
|
||||
break;
|
||||
case 'V':
|
||||
case 'W':
|
||||
case 's':
|
||||
case 'U':
|
||||
case 'G':
|
||||
case 'g':
|
||||
|
Loading…
x
Reference in New Issue
Block a user