xsd_types/value/duration/
day_time_duration.rs1use crate::{
2 format_nanoseconds,
3 lexical::{duration::InvalidDayTimeDuration, LexicalFormOf},
4 Datatype, DurationDatatype, ParseXsd, XsdValue,
5};
6use core::fmt;
7use std::str::FromStr;
8
9#[derive(Debug, Clone, Copy)]
10pub struct DayTimeDuration {
11 is_negative: bool,
12 seconds: u32,
13 nano_seconds: u32,
14}
15
16impl DayTimeDuration {
17 pub fn new(is_negative: bool, mut seconds: u32, mut nano_seconds: u32) -> Self {
18 let s = nano_seconds / 1_000_000_000;
20 if s > 0 {
21 seconds += s;
22 nano_seconds -= s * 1_000_000_000;
23 }
24
25 Self {
26 is_negative,
27 seconds,
28 nano_seconds,
29 }
30 }
31
32 pub fn into_string(self) -> String {
33 self.to_string()
34 }
35}
36
37impl XsdValue for DayTimeDuration {
38 fn datatype(&self) -> Datatype {
39 Datatype::Duration(DurationDatatype::Duration)
40 }
41}
42
43impl ParseXsd for DayTimeDuration {
44 type LexicalForm = crate::lexical::DayTimeDuration;
45}
46
47impl FromStr for DayTimeDuration {
48 type Err = InvalidDayTimeDuration<String>;
49
50 fn from_str(s: &str) -> Result<Self, Self::Err> {
51 let lexical_value = crate::lexical::DayTimeDuration::new(s)
52 .map_err(|InvalidDayTimeDuration(s)| InvalidDayTimeDuration(s.to_owned()))?;
53 Ok(lexical_value.as_value())
54 }
55}
56
57impl fmt::Display for DayTimeDuration {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 let mut minute = self.seconds / 60;
60 let second = self.seconds - minute * 60;
61
62 let mut hour = minute / 60;
63 minute -= hour * 60;
64
65 let day = hour / 24;
66 hour -= day * 24;
67
68 if self.is_negative {
69 write!(f, "-")?;
70 }
71
72 write!(f, "P")?;
73
74 if day > 0 {
75 write!(f, "{day}D")?;
76 }
77
78 if hour > 0 || minute > 0 || second > 0 || self.nano_seconds > 0 {
79 write!(f, "T")?;
80
81 if hour > 0 {
82 write!(f, "{hour}H")?;
83 }
84
85 if minute > 0 {
86 write!(f, "{minute}M")?;
87 }
88
89 if second > 0 || self.nano_seconds > 0 {
90 if second > 0 {
91 second.fmt(f)?;
92 }
93
94 format_nanoseconds(self.nano_seconds, f)?;
95 write!(f, "S")?;
96 }
97 }
98
99 Ok(())
100 }
101}
102
103#[cfg(feature = "serde")]
104impl serde::Serialize for DayTimeDuration {
105 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
106 where
107 S: serde::Serializer,
108 {
109 self.into_string().serialize(serializer)
110 }
111}
112
113#[cfg(feature = "serde")]
114impl<'de> serde::Deserialize<'de> for DayTimeDuration {
115 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
116 where
117 D: serde::Deserializer<'de>,
118 {
119 struct Visitor;
120
121 impl<'de> serde::de::Visitor<'de> for Visitor {
122 type Value = DayTimeDuration;
123
124 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
125 formatter.write_str("a http://www.w3.org/2001/XMLSchema#dayTimeDuration")
126 }
127
128 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
129 where
130 E: serde::de::Error,
131 {
132 v.parse().map_err(|e| E::custom(e))
133 }
134 }
135
136 deserializer.deserialize_str(Visitor)
137 }
138}