mysql_common/value/convert/
chrono.rs
1#![cfg(feature = "chrono")]
12
13use std::convert::TryFrom;
14
15use chrono::{Datelike, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
16
17use crate::value::Value;
18
19use super::{
20 parse_mysql_datetime_string, parse_mysql_time_string, FromValue, FromValueError, ParseIr,
21};
22
23#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
24impl FromValue for NaiveDate {
25 type Intermediate = ParseIr<NaiveDate>;
26}
27
28#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
29impl FromValue for NaiveTime {
30 type Intermediate = ParseIr<NaiveTime>;
31}
32
33#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
34impl FromValue for NaiveDateTime {
35 type Intermediate = ParseIr<NaiveDateTime>;
36}
37
38#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
39impl TryFrom<Value> for ParseIr<NaiveDateTime> {
40 type Error = FromValueError;
41
42 fn try_from(v: Value) -> Result<Self, Self::Error> {
43 match v {
44 Value::Date(year, month, day, hour, minute, second, micros) => {
45 let date = NaiveDate::from_ymd_opt(year.into(), month.into(), day.into());
46 let time = NaiveTime::from_hms_micro_opt(
47 hour.into(),
48 minute.into(),
49 second.into(),
50 micros,
51 );
52 if let Some((date, time)) = date.zip(time) {
53 Ok(ParseIr(NaiveDateTime::new(date, time), v))
54 } else {
55 Err(FromValueError(v))
56 }
57 }
58 Value::Bytes(ref bytes) => {
59 if let Some((year, month, day, hour, minute, second, micros)) =
60 parse_mysql_datetime_string(bytes)
61 {
62 let date = NaiveDate::from_ymd_opt(year as i32, month, day);
63 let time = NaiveTime::from_hms_micro_opt(hour, minute, second, micros);
64 if let Some((date, time)) = date.zip(time) {
65 Ok(ParseIr(NaiveDateTime::new(date, time), v))
66 } else {
67 Err(FromValueError(v))
68 }
69 } else {
70 Err(FromValueError(v))
71 }
72 }
73 _ => Err(FromValueError(v)),
74 }
75 }
76}
77
78#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
79impl TryFrom<Value> for ParseIr<NaiveDate> {
80 type Error = FromValueError;
81
82 fn try_from(v: Value) -> Result<Self, Self::Error> {
83 let result = match v {
84 Value::Date(year, month, day, hour, minute, second, micros) => {
85 let date = NaiveDate::from_ymd_opt(year.into(), month.into(), day.into());
86 Ok((
87 date,
88 Value::Date(year, month, day, hour, minute, second, micros),
89 ))
90 }
91 Value::Bytes(bytes) => {
92 if let Some((y, m, d, _, _, _, _)) = parse_mysql_datetime_string(&*bytes) {
93 let date = NaiveDate::from_ymd_opt(y as i32, m, d);
94 Ok((date, Value::Bytes(bytes)))
95 } else {
96 Err(FromValueError(Value::Bytes(bytes)))
97 }
98 }
99 v => Err(FromValueError(v)),
100 };
101
102 let (date, value) = result?;
103
104 if let Some(output) = date {
105 Ok(ParseIr(output, value))
106 } else {
107 Err(FromValueError(value))
108 }
109 }
110}
111
112#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
113impl TryFrom<Value> for ParseIr<NaiveTime> {
114 type Error = FromValueError;
115
116 fn try_from(v: Value) -> Result<Self, Self::Error> {
117 let result = match v {
118 Value::Time(false, 0, h, m, s, u) => {
119 let time = NaiveTime::from_hms_micro_opt(h.into(), m.into(), s.into(), u);
120 Ok((time, Value::Time(false, 0, h, m, s, u)))
121 }
122 Value::Bytes(bytes) => {
123 if let Some((false, h, m, s, u)) = parse_mysql_time_string(&*bytes) {
124 let time = NaiveTime::from_hms_micro_opt(h, m as u32, s as u32, u);
125 Ok((time, Value::Bytes(bytes)))
126 } else {
127 Err(FromValueError(Value::Bytes(bytes)))
128 }
129 }
130 v => Err(FromValueError(v)),
131 };
132
133 let (time, value) = result?;
134
135 if let Some(output) = time {
136 Ok(ParseIr(output, value))
137 } else {
138 Err(FromValueError(value))
139 }
140 }
141}
142
143#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
144impl From<ParseIr<NaiveDateTime>> for NaiveDateTime {
145 fn from(value: ParseIr<NaiveDateTime>) -> Self {
146 value.commit()
147 }
148}
149
150#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
151impl From<ParseIr<NaiveDate>> for NaiveDate {
152 fn from(value: ParseIr<NaiveDate>) -> Self {
153 value.commit()
154 }
155}
156
157#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
158impl From<ParseIr<NaiveTime>> for NaiveTime {
159 fn from(value: ParseIr<NaiveTime>) -> Self {
160 value.commit()
161 }
162}
163
164#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
165impl From<ParseIr<NaiveDateTime>> for Value {
166 fn from(value: ParseIr<NaiveDateTime>) -> Self {
167 value.rollback()
168 }
169}
170
171#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
172impl From<ParseIr<NaiveDate>> for Value {
173 fn from(value: ParseIr<NaiveDate>) -> Self {
174 value.rollback()
175 }
176}
177
178#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
179impl From<ParseIr<NaiveTime>> for Value {
180 fn from(value: ParseIr<NaiveTime>) -> Self {
181 value.rollback()
182 }
183}
184
185#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
186impl From<NaiveDateTime> for Value {
187 fn from(x: NaiveDateTime) -> Value {
188 if 1000 > x.year() || x.year() > 9999 {
189 panic!("Year `{}` not in supported range [1000, 9999]", x.year())
190 }
191 Value::Date(
192 x.year() as u16,
193 x.month() as u8,
194 x.day() as u8,
195 x.hour() as u8,
196 x.minute() as u8,
197 x.second() as u8,
198 x.nanosecond() / 1000,
199 )
200 }
201}
202
203#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
204impl From<NaiveDate> for Value {
205 fn from(x: NaiveDate) -> Value {
206 if 1000 > x.year() || x.year() > 9999 {
207 panic!("Year `{}` not in supported range [1000, 9999]", x.year())
208 }
209 Value::Date(x.year() as u16, x.month() as u8, x.day() as u8, 0, 0, 0, 0)
210 }
211}
212
213#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
214impl From<NaiveTime> for Value {
215 fn from(x: NaiveTime) -> Value {
216 Value::Time(
217 false,
218 0,
219 x.hour() as u8,
220 x.minute() as u8,
221 x.second() as u8,
222 x.nanosecond() / 1000,
223 )
224 }
225}