1use std::fmt;
2use cal::{LocalDate, LocalTime, LocalDateTime, DatePiece, TimePiece};
3use cal::{Offset, OffsetDateTime};
4use util::RangeExt;
5
6
7pub trait ISO: Sized {
8 fn iso(&self) -> ISOString<Self> {
9 ISOString(self)
10 }
11
12 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
13}
14
15#[derive(Debug)]
16pub struct ISOString<'a, T: 'a>(&'a T);
17
18impl<'a, T> fmt::Display for ISOString<'a, T>
19where T: ISO {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 ISO::fmt(self.0, f)
22 }
23}
24
25impl ISO for LocalDate {
26 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27 let year = self.year();
28 if year.is_within(0 .. 9999) {
29 write!(f, "{:04}-{:02}-{:02}", year, self.month() as usize, self.day())
30 }
31 else {
32 write!(f, "{:+05}-{:02}-{:02}", year, self.month() as usize, self.day())
33 }
34 }
35}
36
37impl ISO for LocalTime {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 write!(f, "{:02}:{:02}:{:02}.{:03}", self.hour(), self.minute(), self.second(), self.millisecond())
40 }
41}
42
43impl ISO for LocalDateTime {
44 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45 self.date().fmt(f)?;
46 write!(f, "T")?;
47 self.time().fmt(f)
48 }
49}
50
51impl ISO for Offset {
52 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53 if self.is_utc() {
54 write!(f, "Z")
55 }
56 else {
57 f.write_str(if self.is_negative() { "-" } else { "+" })?;
58
59 match (self.hours(), self.minutes(), self.seconds()) {
60 (h, 0, 0) => write!(f, "{:02}", h.abs()),
61 (h, m, 0) => write!(f, "{:02}:{:02}", h.abs(), m.abs()),
62 (h, m, s) => write!(f, "{:02}:{:02}:{:02}", h.abs(), m.abs(), s.abs()),
63 }
64 }
65 }
66}
67
68impl ISO for OffsetDateTime {
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 write!(f, "{}{}", self.local.iso(), self.offset.iso())
71 }
72}