Skip to content

Commit 5d8d861

Browse files
authored
Custom serde serializer for datetime (#153)
* feat: custom serde serializer for datetime * feat: use custom serde serializer for datetime for all DateTime<Utc> fields * review: rename datetime serializer to datetime_rfc3339
1 parent b119054 commit 5d8d861

14 files changed

+47
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ v2_0_1 = []
2626

2727
[dependencies]
2828
serde = { version = "1", default-features = false, features = ["derive"] }
29-
chrono = { version = "0.4.39", default-features = false, features = ["serde"] }
29+
chrono = { version = "0.4.39", default-features = false, features = ["serde", "alloc"] }
3030
uuid = { version = "1", default-features = false, features = ["v4"] }
3131
validator = { version = "0.19.0", default-features = false, features = ["derive"] }
3232
regex = "1.11.1"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use chrono::{DateTime, SecondsFormat, Utc};
2+
use serde::{Deserialize, Deserializer, Serializer};
3+
pub fn serialize<S>(date: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
4+
where
5+
S: Serializer,
6+
{
7+
serializer.serialize_str(&date.to_rfc3339_opts(SecondsFormat::Millis, true))
8+
}
9+
10+
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
11+
where
12+
D: Deserializer<'de>,
13+
{
14+
let s: String = Deserialize::deserialize(deserializer)?;
15+
DateTime::parse_from_rfc3339(&s)
16+
.map(|dt| dt.with_timezone(&Utc))
17+
.map_err(serde::de::Error::custom)
18+
}

src/v2_0_1/helpers/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
/// validators
22
pub mod validator;
3+
4+
/// serializers
5+
pub mod datetime_rfc3339;

src/v2_0_1/messages/boot_notification.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::v2_0_1::datatypes::charging_station_type::ChargingStationType;
1717
use crate::v2_0_1::datatypes::status_info_type::StatusInfoType;
1818
use crate::v2_0_1::enumerations::boot_reason_enum_type::BootReasonEnumType;
1919
use crate::v2_0_1::enumerations::registration_status_enum_type::RegistrationStatusEnumType;
20+
use crate::v2_0_1::helpers::datetime_rfc3339;
2021

2122
/// `BootNotificationRequest`, sent by the Charging Station to the CSMS when booting.
2223
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Default)]
@@ -33,6 +34,7 @@ pub struct BootNotificationRequest {
3334
#[serde(rename_all = "camelCase")]
3435
pub struct BootNotificationResponse {
3536
/// This contains the CSMS’s current time.
37+
#[serde(with = "datetime_rfc3339 ")]
3638
pub current_time: DateTime<Utc>,
3739
/// When [status](BootNotificationResponse::status) is Accepted, this contains the
3840
/// heartbeat interval in seconds.

src/v2_0_1/messages/heartbeat.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
use chrono::DateTime;
44
use chrono::Utc;
55

6+
use crate::v2_0_1::helpers::datetime_rfc3339;
7+
68
/// HeartbeatRequest, sent by the Charging Station to the CSMS. No fields are defined.
79
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Default)]
810
#[serde(rename_all = "camelCase")]
@@ -15,5 +17,6 @@ pub struct HeartbeatRequest {
1517
#[serde(rename_all = "camelCase")]
1618
pub struct HeartbeatResponse {
1719
/// Contains the current time of the CSMS.
20+
#[serde(with = "datetime_rfc3339 ")]
1821
pub current_time: DateTime<Utc>,
1922
}

src/v2_0_1/messages/notify_customer_information.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use chrono::DateTime;
22
use chrono::Utc;
33

4+
use crate::v2_0_1::helpers::datetime_rfc3339;
5+
46
/// This contains the field definition of the NotifyCustomerInformationRequest PDU sent by the Charging Station to the CSMS.
57
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Default)]
68
#[serde(rename_all = "camelCase")]
@@ -9,6 +11,7 @@ pub struct NotifyCustomerInformationRequest {
911
#[serde(skip_serializing_if = "Option::is_none")]
1012
pub tbc: Option<bool>,
1113
pub seq_no: i32,
14+
#[serde(with = "datetime_rfc3339 ")]
1215
pub generated_at: DateTime<Utc>,
1316
pub request_id: i32,
1417
}

src/v2_0_1/messages/notify_ev_charging_schedule.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ use chrono::Utc;
44
use crate::v2_0_1::datatypes::charging_schedule_type::ChargingScheduleType;
55
use crate::v2_0_1::datatypes::status_info_type::StatusInfoType;
66
use crate::v2_0_1::enumerations::generic_status_enum_type::GenericStatusEnumType;
7+
use crate::v2_0_1::helpers::datetime_rfc3339;
78

89
/// The Charging Station uses this message to communicate the charging needs as calculated by the EV to the CSMS.
910
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Default)]
1011
#[serde(rename_all = "camelCase")]
1112
pub struct NotifyEVChargingScheduleRequest {
13+
#[serde(with = "datetime_rfc3339 ")]
1214
pub time_base: DateTime<Utc>,
1315
pub evse_id: i32,
1416
pub charging_schedule: ChargingScheduleType,

src/v2_0_1/messages/notify_event.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ use chrono::DateTime;
22
use chrono::Utc;
33

44
use crate::v2_0_1::datatypes::event_data_type::EventDataType;
5+
use crate::v2_0_1::helpers::datetime_rfc3339;
56

67
/// This contains the field definition of the NotifyEventRequest PDU sent by the Charging Station to the CSMS.
78
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Default)]
89
#[serde(rename_all = "camelCase")]
910
pub struct NotifyEventRequest {
11+
#[serde(with = "datetime_rfc3339 ")]
1012
pub generated_at: DateTime<Utc>,
1113
#[serde(skip_serializing_if = "Option::is_none")]
1214
pub tbc: Option<bool>,

src/v2_0_1/messages/notify_monitoring_report.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use chrono::DateTime;
22
use chrono::Utc;
33

44
use crate::v2_0_1::datatypes::monitoring_data_type::MonitoringDataType;
5+
use crate::v2_0_1::helpers::datetime_rfc3339;
56

67
/// This contains the field definition of the NotifyMonitoringRequest PDU sent by the Charging Station to the CSMS.
78
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Default)]
@@ -11,6 +12,7 @@ pub struct NotifyMonitoringReportRequest {
1112
#[serde(skip_serializing_if = "Option::is_none")]
1213
pub tbc: Option<bool>,
1314
pub seq_no: i32,
15+
#[serde(with = "datetime_rfc3339 ")]
1416
pub generated_at: DateTime<Utc>,
1517
#[serde(skip_serializing_if = "Option::is_none")]
1618
pub monitor: Option<Vec<MonitoringDataType>>,

src/v2_0_1/messages/notify_report.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use chrono::DateTime;
22
use chrono::Utc;
33

44
use crate::v2_0_1::datatypes::report_data_type::ReportDataType;
5+
use crate::v2_0_1::helpers::datetime_rfc3339;
56

67
/// This contains the field definition of the NotifyReportRequest PDU sent by the Charging Station to the CSMS.
78
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Default)]
@@ -11,6 +12,7 @@ pub struct NotifyReportRequest {
1112
#[serde(skip_serializing_if = "Option::is_none")]
1213
pub tbc: Option<bool>,
1314
pub seq_no: i32,
15+
#[serde(with = "datetime_rfc3339 ")]
1416
pub generated_at: DateTime<Utc>,
1517
#[serde(skip_serializing_if = "Option::is_none")]
1618
pub report_data: Option<Vec<ReportDataType>>,

0 commit comments

Comments
 (0)