Fixup time & support negative & mktime

This commit is contained in:
jD91mZM2
2018-07-13 09:13:46 +02:00
parent 758b437170
commit a9ea2ef64e
9 changed files with 183 additions and 61 deletions
+127 -61
View File
@@ -198,70 +198,136 @@ pub unsafe extern "C" fn localtime(clock: *const time_t) -> *mut tm {
localtime_r(clock, &mut TM)
}
#[no_mangle]
pub unsafe extern "C" fn localtime_r(clock: *const time_t, r: *mut tm) -> *mut tm {
fn leap_year(year: c_int) -> bool {
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
}
let mut clock = *clock;
const MONTH_DAYS: [[c_int; 12]; 2] = [
// Non-leap years:
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
// Leap years:
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
];
if clock < 0 {
unimplemented!("localtime_r with a negative time is to be implemented");
}
let mut days = (clock / (60 * 60 * 24)) as c_int;
// Epoch, Jan 1 1970, was on a thursday.
// Jan 5th was a monday.
(*r).tm_wday = (days + 4) % 7;
(*r).tm_year = 1970;
loop {
let days_in_year = if leap_year((*r).tm_year) { 366 } else { 365 };
if days < days_in_year {
break;
}
days -= days_in_year;
(*r).tm_year += 1;
}
(*r).tm_yday = days;
(*r).tm_sec = (clock % 60) as c_int;
(*r).tm_min = ((clock % (60 * 60)) / 60) as c_int;
(*r).tm_hour = (clock / (60 * 60)) as c_int;
const MONTH_DAYS: [[c_int; 12]; 2] = [
// Non-leap years:
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
// Leap years:
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
];
let leap = if leap_year((*r).tm_year) { 1 } else { 0 };
loop {
let days_in_month = MONTH_DAYS[leap][(*r).tm_mon as usize];
if days < (*r).tm_mon {
break;
}
days -= days_in_month;
(*r).tm_mon += 1;
}
(*r).tm_mday = days as c_int;
(*r).tm_isdst = 0;
r
fn leap_year(year: c_int) -> bool {
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
}
// #[no_mangle]
pub extern "C" fn mktime(timeptr: *mut tm) -> time_t {
unimplemented!();
#[no_mangle]
pub unsafe extern "C" fn localtime_r(clock: *const time_t, t: *mut tm) -> *mut tm {
let clock = *clock;
let mut day = (clock / (60 * 60 * 24)) as c_int;
if clock < 0 && clock % (60 * 60 * 24) != 0 {
// -1 because for negative values round upwards
// -0.3 == 0, but we want -1
day -= 1;
}
(*t).tm_sec = (clock % 60) as c_int;
(*t).tm_min = ((clock / 60) % 60) as c_int;
(*t).tm_hour = ((clock / (60 * 60)) % 24) as c_int;
while (*t).tm_sec < 0 {
(*t).tm_sec += 60;
(*t).tm_min -= 1;
}
while (*t).tm_min < 0 {
(*t).tm_min += 60;
(*t).tm_hour -= 1;
}
while (*t).tm_hour < 0 {
(*t).tm_hour += 24;
}
// Jan 1th was a thursday, 4th of a zero-indexed week.
(*t).tm_wday = (day + 4) % 7;
if (*t).tm_wday < 0 {
(*t).tm_wday += 7;
}
let mut year = 1970;
if day < 0 {
while day < 0 {
let days_in_year = if leap_year(year) { 366 } else { 365 };
day += days_in_year;
year -= 1;
}
(*t).tm_year = year - 1900;
(*t).tm_yday = day + 1;
} else {
loop {
let days_in_year = if leap_year(year) { 366 } else { 365 };
if day < days_in_year {
break;
}
day -= days_in_year;
year += 1;
}
(*t).tm_year = year - 1900;
(*t).tm_yday = day;
}
let leap = if leap_year(year) { 1 } else { 0 };
(*t).tm_mon = 0;
loop {
let days_in_month = MONTH_DAYS[leap][(*t).tm_mon as usize];
if day < days_in_month {
break;
}
day -= days_in_month;
(*t).tm_mon += 1;
}
(*t).tm_mday = 1 + day as c_int;
(*t).tm_isdst = 0;
t
}
#[no_mangle]
pub unsafe extern "C" fn mktime(t: *mut tm) -> time_t {
let mut year = (*t).tm_year + 1900;
let mut month = (*t).tm_mon;
let mut day = (*t).tm_mday as i64 - 1;
if year < 1970 {
day = MONTH_DAYS[if leap_year(year) { 1 } else { 0 }][(*t).tm_mon as usize] as i64 - day;
while year < 1969 {
year += 1;
day += if leap_year(year) { 366 } else { 365 };
}
let leap = if leap_year(year) { 1 } else { 0 };
while month < 11 {
month += 1;
day += MONTH_DAYS[leap][month as usize] as i64;
}
-(day * (60 * 60 * 24)
- (((*t).tm_hour as i64) * (60 * 60)
+ ((*t).tm_min as i64) * 60
+ (*t).tm_sec as i64))
} else {
while year > 1970 {
day += if leap_year(year) { 366 } else { 365 };
year -= 1;
}
let leap = if leap_year(year) { 1 } else { 0 };
while month > 0 {
day += MONTH_DAYS[leap][month as usize] as i64;
month -= 1;
}
(day * (60 * 60 * 24)
+ ((*t).tm_hour as i64) * (60 * 60)
+ ((*t).tm_min as i64) * 60
+ (*t).tm_sec as i64)
}
}
#[no_mangle]
+2
View File
@@ -21,8 +21,10 @@
/getid
/link
/locale
/localtime
/math
/mem
/mktime
/pipe
/printf
/rmdir
+2
View File
@@ -16,8 +16,10 @@ EXPECT_BINS=\
ftruncate \
getc_unget \
locale \
localtime \
math \
mem \
mktime \
pipe \
printf \
rename \
View File
+6
View File
@@ -0,0 +1,6 @@
Year 69, Day of year: 333, Month 10, Day of month: 29, Day of week: 6, 0:0:0
Year 69, Day of year: 365, Month 11, Day of month: 31, Day of week: 3, 0:0:0
Year 69, Day of year: 365, Month 11, Day of month: 31, Day of week: 3, 23:51:40
Year 70, Day of year: 0, Month 0, Day of month: 1, Day of week: 4, 0:0:0
Year 118, Day of year: 193, Month 6, Day of month: 13, Day of week: 5, 4:9:10
Fri Jul 13 06:03:43 2018
View File
+6
View File
@@ -0,0 +1,6 @@
31536000
-2851200 = -2851200
-86400 = -86400
-500 = -500
0 = 0
1531454950 = 1531454950
+18
View File
@@ -0,0 +1,18 @@
#include <stdio.h>
#include <time.h>
int main() {
int day = 60 * 60 * 24;
time_t inputs[] = { -(day * 33), -day, -500, 0, 1531454950 };
for (int i = 0; i < 5; i += 1) {
struct tm* t = localtime(&inputs[i]);
printf(
"Year %d, Day of year: %d, Month %d, Day of month: %d, Day of week: %d, %d:%d:%d\n",
t->tm_year, t->tm_yday, t->tm_mon, t->tm_mday, t->tm_wday, t->tm_hour, t->tm_min, t->tm_sec
);
}
time_t input = 1531461823;
fputs(ctime(&input), stdout); // Omit newline
}
+22
View File
@@ -0,0 +1,22 @@
#include <stdio.h>
#include <time.h>
int main() {
struct tm t = {};
t.tm_year = 71;
t.tm_mday = 1;
printf("%ld\n", mktime(&t));
int day = 60 * 60 * 24;
time_t inputs[] = { -(day * 33), -day, -500, 0, 1531454950 };
for (int i = 0; i < 5; i += 1) {
struct tm* t2 = localtime(&inputs[i]);
printf("%ld = %ld\n", inputs[i], mktime(t2));
if (inputs[i] != mktime(t2)) {
puts("Failed!");
}
}
}