rbdc_mysql/types/
datetime.rs1use crate::types::date::decode_date_buf;
2use crate::types::time::decode_time;
3use crate::types::{Decode, Encode};
4use crate::value::{MySqlValue, MySqlValueFormat};
5use rbdc::datetime::DateTime;
6use rbdc::Error;
7
8impl Encode for DateTime {
9 fn encode(self, buf: &mut Vec<u8>) -> Result<usize, Error> {
10 let datetime = self.0;
11 let datetime_size = date_time_size_hint(
12 datetime.hour(),
13 datetime.minute(),
14 datetime.sec(),
15 datetime.nano(),
16 );
17 buf.push(datetime_size as u8);
18 let date = rbdc::date::Date(fastdate::Date {
19 day: datetime.day(),
20 mon: datetime.mon(),
21 year: datetime.year(),
22 });
23 let mut size = date.encode(buf)?;
24 buf.remove(buf.len() - (size + 1));
25 if datetime_size > 4 {
26 let time = fastdate::Time {
27 nano: datetime.nano(),
28 sec: datetime.sec(),
29 minute: datetime.minute(),
30 hour: datetime.hour(),
31 };
32 let before_len = buf.len();
33 let encode_len = time.encode(buf)?;
34 if encode_len > 6 {
35 for _ in 0..6 {
36 buf.remove(before_len);
37 }
38 }
39 let after_len = buf.len();
40 size += after_len - before_len;
41 }
42 Ok(1 + size)
43 }
44}
45
46impl Decode for DateTime {
47 fn decode(value: MySqlValue) -> Result<Self, Error> {
48 Ok(match value.format() {
49 MySqlValueFormat::Text => Self({
50 let s = value.as_str()?;
51 fastdate::DateTime::from_str_default(s, value.option.offset_sec)
52 .map_err(|e| Error::from(e.to_string()))?
53 }),
54 MySqlValueFormat::Binary => {
55 let buf = value.as_bytes()?;
56 let len = buf[0];
57 let date = decode_date_buf(&buf[1..])?;
58 let time = if len > 4 {
59 decode_time(&buf[5..])
60 } else {
61 fastdate::Time {
62 nano: 0,
63 sec: 0,
64 minute: 0,
65 hour: 0,
66 }
67 };
68 let v = fastdate::DateTime::from((date, time, value.option.offset_sec));
69 Self(v)
70 }
71 })
72 }
73}
74
75fn date_time_size_hint(hour: u8, min: u8, sec: u8, nano: u32) -> usize {
76 match (hour, min, sec, nano) {
78 (0, 0, 0, 0) => 4,
81
82 (_, _, _, 0) => 7,
85
86 (_, _, _, _) => 11,
88 }
89}