use time;
use time::{Timespec, Tm};
use std::fmt::{Display, Result, Formatter};
pub trait TimeDisplay {
type D: Display;
fn into_local_display(self) -> Self::D;
fn into_utc_display(self) -> Self::D;
}
#[derive(Copy, Clone, Debug)]
pub struct PrettyDisplay(Tm);
pub fn parse_time_str(s: &str) -> Option<Timespec> {
time::strptime(s, "%Y%m%dt%H%M%S%Z").ok().map(|tm| tm.to_timespec())
}
impl TimeDisplay for Timespec {
type D = PrettyDisplay;
fn into_local_display(self) -> Self::D {
PrettyDisplay(time::at(self))
}
fn into_utc_display(self) -> Self::D {
PrettyDisplay(time::at_utc(self))
}
}
impl Display for PrettyDisplay {
fn fmt(&self, f: &mut Formatter) -> Result {
if time::now_utc().tm_year == self.0.tm_year {
write!(f, "{}", time::strftime("%b %d %R", &self.0).unwrap())
} else {
write!(f, "{}", time::strftime("%b %d %Y", &self.0).unwrap())
}
}
}
#[cfg(test)]
mod test {
use super::*;
use time::{self, Tm};
fn time(y: i32, mon: i32, d: i32, h: i32, min: i32, s: i32) -> Tm {
Tm {
tm_sec: s,
tm_min: min,
tm_hour: h,
tm_mday: d,
tm_mon: mon - 1,
tm_year: y - 1900,
tm_wday: 0,
tm_yday: d,
tm_isdst: 0,
tm_utcoff: 0,
tm_nsec: 0,
}
}
fn this_year() -> i32 {
time::now_utc().tm_year
}
fn move_to_this_year(mut tm: Tm) -> Tm {
tm.tm_year = this_year();
tm
}
#[cfg(unix)]
fn set_time_zone(tz: &str) {
use std::env;
env::set_var("TZ", tz);
time::tzset();
}
#[test]
fn parse() {
let time = parse_time_str("19881211t152000z").unwrap();
let tm = time::at_utc(time);
assert_eq!(tm.tm_year, 88);
assert_eq!(tm.tm_mon, 11); assert_eq!(tm.tm_mday, 11);
assert_eq!(tm.tm_hour, 15);
assert_eq!(tm.tm_min, 20);
assert_eq!(tm.tm_sec, 0);
}
#[test]
fn display_utc() {
let time = move_to_this_year(time(1988, 12, 11, 15, 20, 0));
assert_eq!(format!("{}", time.to_timespec().into_utc_display()),
"Dec 11 15:20");
}
#[cfg(unix)]
#[test]
fn display_local() {
let time = move_to_this_year(time(1988, 12, 11, 15, 20, 0));
set_time_zone("Europe/London");
assert_eq!(format!("{}", time.to_timespec().into_local_display()),
"Dec 11 15:20");
set_time_zone("Europe/Rome");
assert_eq!(format!("{}", time.to_timespec().into_local_display()),
"Dec 11 16:20");
}
#[test]
fn display_past_year() {
let time = time(1988, 12, 11, 15, 20, 0);
assert_eq!(format!("{}", time.to_timespec().into_utc_display()),
"Dec 11 1988");
}
#[test]
fn parse_display_past_year() {
let time = parse_time_str("19881211t152000z").unwrap();
assert_eq!(format!("{}", time.into_utc_display()), "Dec 11 1988");
}
}