Commit b83d1c7f authored by jD91mZM2's avatar jD91mZM2

strftime :D

parent 37b6cd94
Pipeline #718 failed with stages
in 3 minutes and 39 seconds
sys_includes = ["sys/types.h", "bits/timespec.h", "stdint.h"]
sys_includes = ["sys/types.h", "bits/timespec.h", "stdint.h", "stddef.h"]
include_guard = "_TIME_H"
language = "C"
......
//! time implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html
#![no_std]
#![feature(const_fn)]
#![feature(alloc, const_fn)]
#[macro_use]
extern crate alloc;
extern crate errno;
extern crate platform;
pub mod constants;
mod helpers;
mod strftime;
use constants::*;
use core::mem::transmute;
......@@ -286,7 +289,7 @@ pub unsafe extern "C" fn localtime_r(clock: *const time_t, t: *mut tm) -> *mut t
}
#[no_mangle]
pub unsafe extern "C" fn mktime(t: *mut tm) -> time_t {
pub unsafe extern "C" fn mktime(t: *const 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;
......@@ -331,14 +334,14 @@ pub extern "C" fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int
platform::nanosleep(rqtp, rmtp)
}
// #[no_mangle]
pub extern "C" fn strftime(
#[no_mangle]
pub unsafe extern "C" fn strftime(
s: *mut c_char,
maxsize: usize,
format: *const c_char,
timptr: *const tm,
) -> usize {
unimplemented!();
timeptr: *const tm,
) -> size_t {
strftime::strftime(true, &mut platform::UnsafeStringWriter(s as *mut u8), maxsize, format, timeptr)
}
// #[no_mangle]
......
use alloc::string::String;
use platform::Write;
use platform::types::*;
use tm;
pub unsafe fn strftime<W: Write>(toplevel: bool, mut w: &mut W, maxsize: usize, mut format: *const c_char, t: *const tm) -> size_t {
let mut written = 0;
if toplevel {
// Reserve nul byte
written += 1;
}
macro_rules! w {
(reserve $amount:expr) => {{
if written + $amount > maxsize {
return 0;
}
written += $amount;
}};
(byte $b:expr) => {{
w!(reserve 1);
w.write_u8($b);
}};
(char $chr:expr) => {{
w!(reserve $chr.len_utf8());
w.write_char($chr);
}};
(recurse $fmt:expr) => {{
let mut fmt = String::with_capacity($fmt.len() + 1);
fmt.push_str($fmt);
fmt.push('\0');
let count = strftime(false, w, maxsize - written, fmt.as_ptr() as *mut c_char, t);
if count == 0 {
return 0;
}
written += count;
assert!(written <= maxsize);
}};
($str:expr) => {{
w!(reserve $str.len());
w.write_str($str);
}};
($fmt:expr, $($args:expr),+) => {{
// Would use write!() if I could get the length written
w!(&format!($fmt, $($args),+))
}};
}
const WDAYS: [&'static str; 7] = [
Please register or sign in to reply
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
];
const MONTHS: [&'static str; 12] = [
"January",
"Febuary",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
while *format != 0 {
if *format as u8 != b'%' {
w!(byte *format as u8);
format = format.offset(1);
continue;
}
format = format.offset(1);
if *format == b'E' || *format == b'O' {
// Ignore because these do nothing without locale
format = format.offset(1);
}
match *format as u8 {
b'%' => w!(byte b'%'),
b'n' => w!(byte b'\n'),
b't' => w!(byte b'\t'),
b'a' => w!(&WDAYS[(*t).tm_wday as usize][..3]),
b'A' => w!(WDAYS[(*t).tm_wday as usize]),
b'b' | b'h' => w!(&MONTHS[(*t).tm_mon as usize][..3]),
b'B' => w!(MONTHS[(*t).tm_mon as usize]),
b'C' => {
let mut year = (*t).tm_year / 100;
// Round up
if (*t).tm_year % 100 != 0 {
year += 1;
}
w!("{:02}", year + 19);
},
b'd' => w!("{:02}", (*t).tm_mday),
b'D' => w!(recurse "%m/%d/%y"),
b'e' => w!("{:2}", (*t).tm_mday),
b'F' => w!(recurse "%Y-%m-%d"),
b'H' => w!("{:02}", (*t).tm_hour),
b'I' => w!("{:02}", ((*t).tm_hour + 12 - 1) % 12 + 1),
b'j' => w!("{:03}", (*t).tm_yday),
b'k' => w!("{:2}", (*t).tm_hour),
b'l' => w!("{:2}", ((*t).tm_hour + 12 - 1) % 12 + 1),
b'm' => w!("{:02}", (*t).tm_mon + 1),
b'M' => w!("{:02}", (*t).tm_min),
b'p' => w!(if (*t).tm_hour < 12 { "AM" } else { "PM" }),
b'P' => w!(if (*t).tm_hour < 12 { "am" } else { "pm" }),
b'r' => w!(recurse "%I:%M:%S %p"),
b'R' => w!(recurse "%H:%M"),
b's' => w!("{}", ::mktime(t)),
b'S' => w!("{:02}", (*t).tm_sec),
b'T' => w!(recurse "%H:%M:%S"),
b'u' => w!("{}", ((*t).tm_wday + 7 - 1) % 7 + 1),
// I'm kinda confused. This is the musl code. For me this returns
// week 28 even though it's week 29. In fact, how *would* this even
  • Weeks are apparently 0 indexed

    writes week of the year as a decimal number (Sunday is the first day of the week) (range [00,53])

  • Oh, that explains it. Thanks!

Please register or sign in to reply
// work if it's restricted by tm_yday and tm_wday (see the man
Please register or sign in to reply
// page), considering years can start at different days of the
// week???
b'U' => w!("{}", ((*t).tm_yday + 7 - (*t).tm_wday) / 7),
b'w' => w!("{}", (*t).tm_wday),
b'W' => w!("{}", ((*t).tm_yday + 7 - ((*t).tm_wday + 6) % 7) / 7),
b'y' => w!("{:02}", (*t).tm_year % 100),
b'Y' => w!("{}", (*t).tm_year + 1900),
b'z' => w!("+0000"), // TODO
b'Z' => w!("UTC"), // TODO
b'+' => w!(recurse "%a %b %d %T %Z %Y"),
_ => return 0
}
format = format.offset(1);
}
if toplevel {
// nul byte is already counted in written
w.write_u8(0);
}
written
}
......@@ -56,6 +56,7 @@ string/strspn
string/strstr
string/strtok
string/strtok_r
strftime
strings
system
time
......
......@@ -29,6 +29,7 @@ EXPECT_BINS=\
setjmp \
sleep \
sprintf \
strftime \
strings \
stdio/fwrite \
stdio/all \
......
21: Tue Tuesday Jul July
17: The 21st century
12: 06:25:42 AM
12: 03:00:00 PM
6: 15:00
16: 15 1531839600 2
7: 197 28
29: Tue Jul 17 15:00:00 UTC 2018
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void print(time_t timestamp, char* fmt) {
char* out = malloc(50);
size_t n = strftime(out, 50, fmt, localtime(&timestamp));
printf("%zu: %s\n", n, out);
free(out);
}
int main() {
print(1531808742, "%a %A %b %B");
print(1531808742, "The %Cst century");
print(1531808742, "%I:%M:%S %p");
print(1531839600, "%r");
print(1531839600, "%R");
print(1531839600, "%H %s %u");
print(1531839600, "%j %U");
print(1531839600, "%+");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment