@@ -206,6 +206,17 @@ fn get_text_from_value(value: &OdbcValueRef<'_>) -> Result<Option<String>, BoxDy
206206
207207impl < ' r > Decode < ' r , Odbc > for NaiveDate {
208208 fn decode ( value : OdbcValueRef < ' r > ) -> Result < Self , BoxDynError > {
209+ // Handle raw ODBC Date values first
210+ if let Some ( date_val) = value. date ( ) {
211+ // Convert odbc_api::sys::Date to NaiveDate
212+ // The ODBC Date structure typically has year, month, day fields
213+ return Ok ( NaiveDate :: from_ymd_opt (
214+ date_val. year as i32 ,
215+ date_val. month as u32 ,
216+ date_val. day as u32 ,
217+ ) . ok_or_else ( || "ODBC: invalid date values" . to_string ( ) ) ?) ;
218+ }
219+
209220 // Handle text values first (most common for dates)
210221 if let Some ( text) = value. text ( ) {
211222 if let Some ( date) = parse_yyyymmdd_text_as_naive_date ( text) {
@@ -250,6 +261,17 @@ impl<'r> Decode<'r, Odbc> for NaiveDate {
250261
251262impl < ' r > Decode < ' r , Odbc > for NaiveTime {
252263 fn decode ( value : OdbcValueRef < ' r > ) -> Result < Self , BoxDynError > {
264+ // Handle raw ODBC Time values first
265+ if let Some ( time_val) = value. time ( ) {
266+ // Convert odbc_api::sys::Time to NaiveTime
267+ // The ODBC Time structure typically has hour, minute, second fields
268+ return Ok ( NaiveTime :: from_hms_opt (
269+ time_val. hour as u32 ,
270+ time_val. minute as u32 ,
271+ time_val. second as u32 ,
272+ ) . ok_or_else ( || "ODBC: invalid time values" . to_string ( ) ) ?) ;
273+ }
274+
253275 let mut s = <String as Decode < ' r , Odbc > >:: decode ( value) ?;
254276 if s. ends_with ( '\u{0}' ) {
255277 s = s. trim_end_matches ( '\u{0}' ) . to_string ( ) ;
@@ -263,6 +285,25 @@ impl<'r> Decode<'r, Odbc> for NaiveTime {
263285
264286impl < ' r > Decode < ' r , Odbc > for NaiveDateTime {
265287 fn decode ( value : OdbcValueRef < ' r > ) -> Result < Self , BoxDynError > {
288+ // Handle raw ODBC Timestamp values first
289+ if let Some ( ts_val) = value. timestamp ( ) {
290+ // Convert odbc_api::sys::Timestamp to NaiveDateTime
291+ // The ODBC Timestamp structure typically has year, month, day, hour, minute, second fields
292+ let date = NaiveDate :: from_ymd_opt (
293+ ts_val. year as i32 ,
294+ ts_val. month as u32 ,
295+ ts_val. day as u32 ,
296+ ) . ok_or_else ( || "ODBC: invalid date values in timestamp" . to_string ( ) ) ?;
297+
298+ let time = NaiveTime :: from_hms_opt (
299+ ts_val. hour as u32 ,
300+ ts_val. minute as u32 ,
301+ ts_val. second as u32 ,
302+ ) . ok_or_else ( || "ODBC: invalid time values in timestamp" . to_string ( ) ) ?;
303+
304+ return Ok ( NaiveDateTime :: new ( date, time) ) ;
305+ }
306+
266307 let mut s = <String as Decode < ' r , Odbc > >:: decode ( value) ?;
267308 // Some ODBC drivers (e.g. PostgreSQL) may include trailing spaces or NULs
268309 // in textual representations of timestamps. Trim them before parsing.
@@ -285,6 +326,26 @@ impl<'r> Decode<'r, Odbc> for NaiveDateTime {
285326
286327impl < ' r > Decode < ' r , Odbc > for DateTime < Utc > {
287328 fn decode ( value : OdbcValueRef < ' r > ) -> Result < Self , BoxDynError > {
329+ // Handle raw ODBC Timestamp values first
330+ if let Some ( ts_val) = value. timestamp ( ) {
331+ // Convert odbc_api::sys::Timestamp to DateTime<Utc>
332+ // The ODBC Timestamp structure typically has year, month, day, hour, minute, second fields
333+ let naive_dt = NaiveDateTime :: new (
334+ NaiveDate :: from_ymd_opt (
335+ ts_val. year as i32 ,
336+ ts_val. month as u32 ,
337+ ts_val. day as u32 ,
338+ ) . ok_or_else ( || "ODBC: invalid date values in timestamp" . to_string ( ) ) ?,
339+ NaiveTime :: from_hms_opt (
340+ ts_val. hour as u32 ,
341+ ts_val. minute as u32 ,
342+ ts_val. second as u32 ,
343+ ) . ok_or_else ( || "ODBC: invalid time values in timestamp" . to_string ( ) ) ?,
344+ ) ;
345+
346+ return Ok ( DateTime :: < Utc > :: from_naive_utc_and_offset ( naive_dt, Utc ) ) ;
347+ }
348+
288349 let mut s = <String as Decode < ' r , Odbc > >:: decode ( value) ?;
289350 if s. ends_with ( '\u{0}' ) {
290351 s = s. trim_end_matches ( '\u{0}' ) . to_string ( ) ;
@@ -312,6 +373,26 @@ impl<'r> Decode<'r, Odbc> for DateTime<Utc> {
312373
313374impl < ' r > Decode < ' r , Odbc > for DateTime < FixedOffset > {
314375 fn decode ( value : OdbcValueRef < ' r > ) -> Result < Self , BoxDynError > {
376+ // Handle raw ODBC Timestamp values first
377+ if let Some ( ts_val) = value. timestamp ( ) {
378+ // Convert odbc_api::sys::Timestamp to DateTime<FixedOffset>
379+ // The ODBC Timestamp structure typically has year, month, day, hour, minute, second fields
380+ let naive_dt = NaiveDateTime :: new (
381+ NaiveDate :: from_ymd_opt (
382+ ts_val. year as i32 ,
383+ ts_val. month as u32 ,
384+ ts_val. day as u32 ,
385+ ) . ok_or_else ( || "ODBC: invalid date values in timestamp" . to_string ( ) ) ?,
386+ NaiveTime :: from_hms_opt (
387+ ts_val. hour as u32 ,
388+ ts_val. minute as u32 ,
389+ ts_val. second as u32 ,
390+ ) . ok_or_else ( || "ODBC: invalid time values in timestamp" . to_string ( ) ) ?,
391+ ) ;
392+
393+ return Ok ( DateTime :: < Utc > :: from_naive_utc_and_offset ( naive_dt, Utc ) . fixed_offset ( ) ) ;
394+ }
395+
315396 let mut s = <String as Decode < ' r , Odbc > >:: decode ( value) ?;
316397 if s. ends_with ( '\u{0}' ) {
317398 s = s. trim_end_matches ( '\u{0}' ) . to_string ( ) ;
@@ -343,6 +424,26 @@ impl<'r> Decode<'r, Odbc> for DateTime<FixedOffset> {
343424
344425impl < ' r > Decode < ' r , Odbc > for DateTime < Local > {
345426 fn decode ( value : OdbcValueRef < ' r > ) -> Result < Self , BoxDynError > {
427+ // Handle raw ODBC Timestamp values first
428+ if let Some ( ts_val) = value. timestamp ( ) {
429+ // Convert odbc_api::sys::Timestamp to DateTime<Local>
430+ // The ODBC Timestamp structure typically has year, month, day, hour, minute, second fields
431+ let naive_dt = NaiveDateTime :: new (
432+ NaiveDate :: from_ymd_opt (
433+ ts_val. year as i32 ,
434+ ts_val. month as u32 ,
435+ ts_val. day as u32 ,
436+ ) . ok_or_else ( || "ODBC: invalid date values in timestamp" . to_string ( ) ) ?,
437+ NaiveTime :: from_hms_opt (
438+ ts_val. hour as u32 ,
439+ ts_val. minute as u32 ,
440+ ts_val. second as u32 ,
441+ ) . ok_or_else ( || "ODBC: invalid time values in timestamp" . to_string ( ) ) ?,
442+ ) ;
443+
444+ return Ok ( DateTime :: < Utc > :: from_naive_utc_and_offset ( naive_dt, Utc ) . with_timezone ( & Local ) ) ;
445+ }
446+
346447 let mut s = <String as Decode < ' r , Odbc > >:: decode ( value) ?;
347448 if s. ends_with ( '\u{0}' ) {
348449 s = s. trim_end_matches ( '\u{0}' ) . to_string ( ) ;
0 commit comments