use std::io::Write;
use std::time::{SystemTime, UNIX_EPOCH};
pub fn timestamp_prefix() -> String {
let d = match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(d) => d,
Err(_) => return String::new(),
};
let total_secs = d.as_secs() as i64;
let secs_in_day = 86_400i64;
let days = total_secs / secs_in_day;
let mut tod = total_secs % secs_in_day;
if tod < 0 { tod += secs_in_day; }
let hour = tod / 3600;
let min = (tod % 3600) / 60;
let sec = tod % 60;
let z = days + 719_468;
let era = if z >= 0 { z } else { z - 146_096 } / 146_097;
let doe = (z - era * 146_097) as i64;
let yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365;
let y = yoe + era * 400;
let doy = doe - (365*yoe + yoe/4 - yoe/100);
let mp = (5*doy + 2) / 153;
let d_ = doy - (153*mp + 2)/5 + 1;
let m = if mp < 10 { mp + 3 } else { mp - 9 };
let year = if m <= 2 { y + 1 } else { y };
format!("{:04}/{:02}/{:02} {:02}:{:02}:{:02} ", year, m, d_, hour, min, sec)
}
pub fn _log(msg: &str) {
let stamp = timestamp_prefix();
let mut out = std::io::stderr();
let _ = out.write_all(stamp.as_bytes());
let _ = out.write_all(msg.as_bytes());
if !msg.ends_with('\n') {
let _ = out.write_all(b"\n");
}
let _ = out.flush();
}
#[macro_export]
macro_rules! log_Println {
($($arg:expr),* $(,)?) => {{
let parts: Vec<::std::string::String> = vec![ $( format!("{}", $arg) ),* ];
$crate::log::_log(&parts.join(" "));
}};
}
#[macro_export]
macro_rules! log_Printf {
($fmt:expr $(, $arg:expr)* $(,)?) => {{
let out = $crate::fmt::go_format($fmt, &[ $( &$arg as &dyn ::std::fmt::Display ),* ]);
$crate::log::_log(&out);
}};
}
#[macro_export]
macro_rules! log_Fatalf {
($fmt:expr $(, $arg:expr)* $(,)?) => {{
let out = $crate::fmt::go_format($fmt, &[ $( &$arg as &dyn ::std::fmt::Display ),* ]);
$crate::log::_log(&out);
$crate::os::Exit(1);
}};
}
#[macro_export]
macro_rules! log_Panic {
($fmt:expr $(, $arg:expr)* $(,)?) => {{
let out = $crate::fmt::go_format($fmt, &[ $( &$arg as &dyn ::std::fmt::Display ),* ]);
$crate::log::_log(&out);
panic!("{}", out);
}};
}
pub use crate::log_Fatalf as Fatalf;
pub use crate::log_Panic as Panic;
pub use crate::log_Printf as Printf;
pub use crate::log_Println as Println;
#[cfg(test)]
mod tests {
#[test]
fn timestamp_has_expected_shape() {
let ts = super::timestamp_prefix();
assert_eq!(ts.len(), 20);
assert_eq!(&ts[4..5], "/");
assert_eq!(&ts[7..8], "/");
assert_eq!(&ts[10..11], " ");
assert_eq!(&ts[13..14], ":");
assert_eq!(&ts[16..17], ":");
}
#[test]
fn println_and_printf_do_not_panic() {
crate::log::Println!("hello", 42);
crate::log::Printf!("n=%d", 7);
}
}