1#[cfg(feature = "chrono")]
25#[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
26pub mod chrono;
27
28#[cfg(feature = "time")]
29#[cfg_attr(feature = "docs", doc(cfg(feature = "time")))]
30pub mod time;
31
32use crate::{tds::codec::Encode, SqlReadBytes};
33#[cfg(feature = "tds73")]
34use byteorder::{ByteOrder, LittleEndian};
35use bytes::{BufMut, BytesMut};
36#[cfg(feature = "tds73")]
37use futures_util::io::AsyncReadExt;
38
39#[derive(Copy, Clone, Debug, Eq, PartialEq)]
46pub struct DateTime {
47 days: i32,
48 seconds_fragments: u32,
49}
50
51impl DateTime {
52 pub fn new(days: i32, seconds_fragments: u32) -> Self {
54 Self {
55 days,
56 seconds_fragments,
57 }
58 }
59
60 pub fn days(self) -> i32 {
63 self.days
64 }
65
66 pub fn seconds_fragments(self) -> u32 {
68 self.seconds_fragments
69 }
70
71 pub(crate) async fn decode<R>(src: &mut R) -> crate::Result<Self>
72 where
73 R: SqlReadBytes + Unpin,
74 {
75 let days = src.read_i32_le().await?;
76 let seconds_fragments = src.read_u32_le().await?;
77
78 Ok(Self {
79 days,
80 seconds_fragments,
81 })
82 }
83}
84
85impl Encode<BytesMut> for DateTime {
86 fn encode(self, dst: &mut BytesMut) -> crate::Result<()> {
87 dst.put_i32_le(self.days);
88 dst.put_u32_le(self.seconds_fragments);
89
90 Ok(())
91 }
92}
93
94#[derive(Copy, Clone, Debug, Eq, PartialEq)]
102pub struct SmallDateTime {
103 days: u16,
104 seconds_fragments: u16,
105}
106
107impl SmallDateTime {
108 pub fn new(days: u16, seconds_fragments: u16) -> Self {
110 Self {
111 days,
112 seconds_fragments,
113 }
114 }
115 pub fn days(self) -> u16 {
117 self.days
118 }
119
120 pub fn seconds_fragments(self) -> u16 {
122 self.seconds_fragments
123 }
124
125 pub(crate) async fn decode<R>(src: &mut R) -> crate::Result<Self>
126 where
127 R: SqlReadBytes + Unpin,
128 {
129 let days = src.read_u16_le().await?;
130 let seconds_fragments = src.read_u16_le().await?;
131
132 Ok(Self {
133 days,
134 seconds_fragments,
135 })
136 }
137}
138
139impl Encode<BytesMut> for SmallDateTime {
140 fn encode(self, dst: &mut BytesMut) -> crate::Result<()> {
141 dst.put_u16_le(self.days);
142 dst.put_u16_le(self.seconds_fragments);
143
144 Ok(())
145 }
146}
147
148#[derive(Copy, Clone, Debug, Eq, PartialEq)]
155#[cfg(feature = "tds73")]
156#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
157pub struct Date(u32);
158
159#[cfg(feature = "tds73")]
160#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
161impl Date {
162 #[inline]
163 pub fn new(days: u32) -> Date {
168 assert_eq!(days >> 24, 0);
169 Date(days)
170 }
171
172 #[inline]
173 pub fn days(self) -> u32 {
175 self.0
176 }
177
178 pub(crate) async fn decode<R>(src: &mut R) -> crate::Result<Self>
179 where
180 R: SqlReadBytes + Unpin,
181 {
182 let mut bytes = [0u8; 4];
183 src.read_exact(&mut bytes[..3]).await?;
184 Ok(Self::new(LittleEndian::read_u32(&bytes)))
185 }
186}
187
188#[cfg(feature = "tds73")]
189#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
190impl Encode<BytesMut> for Date {
191 fn encode(self, dst: &mut BytesMut) -> crate::Result<()> {
192 let mut tmp = [0u8; 4];
193 LittleEndian::write_u32(&mut tmp, self.days());
194 assert_eq!(tmp[3], 0);
195 dst.extend_from_slice(&tmp[0..3]);
196
197 Ok(())
198 }
199}
200
201#[derive(Copy, Clone, Debug)]
208#[cfg(feature = "tds73")]
209#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
210pub struct Time {
211 increments: u64,
212 scale: u8,
213}
214
215#[cfg(feature = "tds73")]
216#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
217impl PartialEq for Time {
218 fn eq(&self, t: &Time) -> bool {
219 self.increments as f64 / 10f64.powi(self.scale as i32)
220 == t.increments as f64 / 10f64.powi(t.scale as i32)
221 }
222}
223
224#[cfg(feature = "tds73")]
225#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
226impl Time {
227 pub fn new(increments: u64, scale: u8) -> Self {
229 Self { increments, scale }
230 }
231
232 #[inline]
233 pub fn increments(self) -> u64 {
238 self.increments
239 }
240
241 #[inline]
242 pub fn scale(self) -> u8 {
244 self.scale
245 }
246
247 #[inline]
248 pub(crate) fn len(self) -> crate::Result<u8> {
250 Ok(match self.scale {
251 0..=2 => 3,
252 3..=4 => 4,
253 5..=7 => 5,
254 _ => {
255 return Err(crate::Error::Protocol(
256 format!("timen: invalid scale {}", self.scale).into(),
257 ))
258 }
259 })
260 }
261
262 pub(crate) async fn decode<R>(src: &mut R, n: usize, rlen: usize) -> crate::Result<Time>
263 where
264 R: SqlReadBytes + Unpin,
265 {
266 let val = match (n, rlen) {
267 (0..=2, 3) => {
268 let hi = src.read_u16_le().await? as u64;
269 let lo = src.read_u8().await? as u64;
270
271 hi | lo << 16
272 }
273 (3..=4, 4) => src.read_u32_le().await? as u64,
274 (5..=7, 5) => {
275 let hi = src.read_u32_le().await? as u64;
276 let lo = src.read_u8().await? as u64;
277
278 hi | lo << 32
279 }
280 _ => {
281 return Err(crate::Error::Protocol(
282 format!("timen: invalid length {}", n).into(),
283 ))
284 }
285 };
286
287 Ok(Time {
288 increments: val,
289 scale: n as u8,
290 })
291 }
292}
293
294#[cfg(feature = "tds73")]
295#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
296impl Encode<BytesMut> for Time {
297 fn encode(self, dst: &mut BytesMut) -> crate::Result<()> {
298 match self.len()? {
299 3 => {
300 assert_eq!(self.increments >> 24, 0);
301 dst.put_u16_le(self.increments as u16);
302 dst.put_u8((self.increments >> 16) as u8);
303 }
304 4 => {
305 assert_eq!(self.increments >> 32, 0);
306 dst.put_u32_le(self.increments as u32);
307 }
308 5 => {
309 assert_eq!(self.increments >> 40, 0);
310 dst.put_u32_le(self.increments as u32);
311 dst.put_u8((self.increments >> 32) as u8);
312 }
313 _ => unreachable!(),
314 }
315
316 Ok(())
317 }
318}
319
320#[derive(Copy, Clone, Debug, PartialEq)]
321#[cfg(feature = "tds73")]
322#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
323pub struct DateTime2 {
331 date: Date,
332 time: Time,
333}
334
335#[cfg(feature = "tds73")]
336#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
337impl DateTime2 {
338 pub fn new(date: Date, time: Time) -> Self {
340 Self { date, time }
341 }
342
343 pub fn date(self) -> Date {
345 self.date
346 }
347
348 pub fn time(self) -> Time {
350 self.time
351 }
352
353 pub(crate) async fn decode<R>(src: &mut R, n: usize, rlen: usize) -> crate::Result<Self>
354 where
355 R: SqlReadBytes + Unpin,
356 {
357 let time = Time::decode(src, n, rlen).await?;
358
359 let mut bytes = [0u8; 4];
360 src.read_exact(&mut bytes[..3]).await?;
361 let date = Date::new(LittleEndian::read_u32(&bytes));
362
363 Ok(Self::new(date, time))
364 }
365}
366
367#[cfg(feature = "tds73")]
368#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
369impl Encode<BytesMut> for DateTime2 {
370 fn encode(self, dst: &mut BytesMut) -> crate::Result<()> {
371 self.time.encode(dst)?;
372
373 let mut tmp = [0u8; 4];
374 LittleEndian::write_u32(&mut tmp, self.date.days());
375 assert_eq!(tmp[3], 0);
376 dst.extend_from_slice(&tmp[0..3]);
377
378 Ok(())
379 }
380}
381
382#[derive(Copy, Clone, Debug, PartialEq)]
383#[cfg(feature = "tds73")]
384#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
385pub struct DateTimeOffset {
393 datetime2: DateTime2,
394 offset: i16,
395}
396
397#[cfg(feature = "tds73")]
398#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
399impl DateTimeOffset {
400 pub fn new(datetime2: DateTime2, offset: i16) -> Self {
403 Self { datetime2, offset }
404 }
405
406 pub fn datetime2(self) -> DateTime2 {
408 self.datetime2
409 }
410
411 pub fn offset(self) -> i16 {
413 self.offset
414 }
415
416 pub(crate) async fn decode<R>(src: &mut R, n: usize, rlen: u8) -> crate::Result<Self>
417 where
418 R: SqlReadBytes + Unpin,
419 {
420 let datetime2 = DateTime2::decode(src, n, rlen as usize).await?;
421 let offset = src.read_i16_le().await?;
422
423 Ok(Self { datetime2, offset })
424 }
425}
426
427#[cfg(feature = "tds73")]
428#[cfg_attr(feature = "docs", doc(cfg(feature = "tds73")))]
429impl Encode<BytesMut> for DateTimeOffset {
430 fn encode(self, dst: &mut BytesMut) -> crate::Result<()> {
431 self.datetime2.encode(dst)?;
432 dst.put_i16_le(self.offset);
433
434 Ok(())
435 }
436}