xsd_types/value/duration/
day_time_duration.rs

1use 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		// Normalize nanoseconds.
19		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}