xsd_types/value/
date.rs

1use chrono::{Datelike, FixedOffset, NaiveDate};
2
3use crate::{
4	format_timezone,
5	lexical::{InvalidDate, LexicalFormOf},
6	Datatype, DisplayYear, ParseXsd, XsdValue,
7};
8use core::fmt;
9use std::str::FromStr;
10
11#[derive(Debug, thiserror::Error)]
12#[error("invalid date value")]
13pub struct InvalidDateValue;
14
15#[derive(Debug, Clone, Copy)]
16pub struct Date {
17	pub date: NaiveDate,
18	pub offset: Option<FixedOffset>,
19}
20
21impl Date {
22	pub fn new(date: NaiveDate, offset: Option<FixedOffset>) -> Self {
23		Self { date, offset }
24	}
25}
26
27#[derive(Debug, thiserror::Error)]
28pub enum DateFromStrError {
29	#[error("invalid date syntax")]
30	Syntax(#[from] InvalidDate<String>),
31
32	#[error(transparent)]
33	Value(#[from] InvalidDateValue),
34}
35
36impl FromStr for Date {
37	type Err = DateFromStrError;
38
39	fn from_str(s: &str) -> Result<Self, Self::Err> {
40		let lexical_value =
41			crate::lexical::Date::new(s).map_err(|InvalidDate(s)| InvalidDate(s.to_owned()))?;
42		lexical_value.try_as_value().map_err(Into::into)
43	}
44}
45
46impl XsdValue for Date {
47	fn datatype(&self) -> Datatype {
48		Datatype::Date
49	}
50}
51
52impl ParseXsd for Date {
53	type LexicalForm = crate::lexical::Date;
54}
55
56impl fmt::Display for Date {
57	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58		write!(
59			f,
60			"{}-{:02}-{:02}",
61			DisplayYear(self.date.year()),
62			self.date.month(),
63			self.date.day()
64		)?;
65
66		format_timezone(self.offset, f)
67	}
68}