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