Skip to content

Commit

Permalink
format datetime for chrono serde integration
Browse files Browse the repository at this point in the history
  • Loading branch information
reenigneEsrever92 committed May 7, 2024
1 parent 1e65739 commit b4deb74
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ serde = "1.0"
quick-xml = { version = "0.31", features = ["encoding"] }
zip = { version = "1.0", default-features = false, features = ["deflate"] }
chrono = { version = "0.4", features = [
"serde",
"serde", "alloc"
], optional = true, default-features = false }

[dev-dependencies]
Expand Down
30 changes: 30 additions & 0 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,36 @@ impl<'a, 'de> serde::Deserializer<'de> for DataDeserializer<'a> {
}
}

#[cfg(feature = "chrono")]
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.data_type {
Data::String(v) => visitor.visit_str(v),
Data::Empty => visitor.visit_str(""),
Data::Float(v) => visitor.visit_str(&v.to_string()),
Data::Int(v) => visitor.visit_str(&v.to_string()),
Data::Bool(v) => visitor.visit_str(&v.to_string()),
Data::DateTime(v) => {
// format date so that chrono can actually parse it to a date time
let formatted_date = v
.as_datetime()
.map(|datetime| datetime.format("%Y-%m-%dT%H:%M:%S").to_string())
.unwrap_or("".to_string());

visitor.visit_str(&formatted_date)
}
Data::DateTimeIso(v) => visitor.visit_str(v),
Data::DurationIso(v) => visitor.visit_str(v),
Data::Error(ref err) => Err(DeError::CellError {
err: err.clone(),
pos: self.pos,
}),
}
}

#[cfg(not(feature = "chrono"))]
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
Expand Down
55 changes: 53 additions & 2 deletions tests/test.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use calamine::Data::{Bool, DateTime, DateTimeIso, DurationIso, Empty, Error, Float, String};
use calamine::{
open_workbook, open_workbook_auto, DataType, ExcelDateTime, ExcelDateTimeType, Ods, Range,
Reader, Sheet, SheetType, SheetVisible, Xls, Xlsb, Xlsx,
open_workbook, open_workbook_auto, DataType, DeError, ExcelDateTime, ExcelDateTimeType, Ods,
Range, RangeDeserializerBuilder, Reader, Sheet, SheetType, SheetVisible, Xls, Xlsb, Xlsx,
};
use calamine::{CellErrorType::*, Data};
use serde_derive::Deserialize;
use std::collections::BTreeSet;
use std::io::Cursor;
use std::sync::Once;
Expand Down Expand Up @@ -1062,6 +1063,56 @@ fn date_xlsb_1904() {
}
}

#[test]
#[cfg(feature = "dates")]
fn date_row_deserializer() {
use calamine::{open_workbook, Reader, Xlsx};
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};

#[derive(Debug, Clone, Deserialize)]
struct Row {
date: NaiveDateTime,
}

let path = format!("{}/tests/date_1904.xlsx", env!("CARGO_MANIFEST_DIR"));
let mut xls: Xlsx<_> = open_workbook(&path).unwrap();
let range = xls
.worksheet_range_at(0)
.unwrap()
.unwrap()
.range((0, 0), (2, 1));

let rows: Result<Vec<Row>, DeError> = RangeDeserializerBuilder::new()
.has_headers(false)
.from_range(&range)
.unwrap()
.collect();

println!("{rows:?}");
assert!(rows.is_ok());
assert_eq!(
rows.as_ref().unwrap().first().unwrap().date,
NaiveDateTime::new(
NaiveDate::from_ymd_opt(2021, 1, 1).unwrap(),
NaiveTime::default()
)
);
assert_eq!(
rows.as_ref().unwrap().get(1).unwrap().date,
NaiveDateTime::new(
NaiveDate::from_ymd_opt(2021, 1, 2).unwrap(),
NaiveTime::default()
)
);
assert_eq!(
rows.as_ref().unwrap().last().unwrap().date,
NaiveDateTime::new(
NaiveDate::from_ymd_opt(1904, 1, 11).unwrap(),
NaiveTime::from_hms_opt(15, 10, 10).unwrap()
)
);
}

#[test]
fn issue_219() {
setup();
Expand Down

0 comments on commit b4deb74

Please sign in to comment.