Skip to content

Commit

Permalink
Add optional defmt support
Browse files Browse the repository at this point in the history
  • Loading branch information
DBLouis committed Jan 23, 2025
1 parent 4c42ee5 commit 3b7b3f9
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ name = "chrono"
# Don't forget to adjust `ALL_NON_EXCLUSIVE_FEATURES` in CI scripts when adding a feature or an optional dependency.
default = ["clock", "std", "oldtime", "wasmbind"]
alloc = []
defmt = ["dep:defmt"]
libc = []
winapi = ["windows-targets"]
std = ["alloc"]
Expand All @@ -43,6 +44,7 @@ serde = { version = "1.0.99", default-features = false, optional = true }
pure-rust-locales = { version = "0.8", optional = true }
rkyv = { version = "0.7.43", optional = true, default-features = false }
arbitrary = { version = "1.0.0", features = ["derive"], optional = true }
defmt = { version = "0.3", optional = true }

[target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies]
wasm-bindgen = { version = "0.2", optional = true }
Expand Down
10 changes: 10 additions & 0 deletions src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,16 @@ where
}
}

#[cfg(feature = "defmt")]
impl<Tz: TimeZone> defmt::Format for Date<Tz>
where
Tz::Offset: defmt::Format,
{
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{}{}", self.naive_local(), self.offset);
}
}

// Note that implementation of Arbitrary cannot be automatically derived for Date<Tz>, due to
// the nontrivial bound <Tz as TimeZone>::Offset: Arbitrary.
#[cfg(all(feature = "arbitrary", feature = "std"))]
Expand Down
10 changes: 10 additions & 0 deletions src/datetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1761,6 +1761,16 @@ impl<Tz: TimeZone> fmt::Debug for DateTime<Tz> {
}
}

#[cfg(feature = "defmt")]
impl<Tz: TimeZone> defmt::Format for DateTime<Tz>
where
Tz::Offset: defmt::Format,
{
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{}{}", self.overflowing_naive_local(), self.offset);
}
}

// `fmt::Debug` is hand implemented for the `rkyv::Archive` variant of `DateTime` because
// deriving a trait recursively does not propagate trait defined associated types with their own
// constraints:
Expand Down
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,13 @@ impl fmt::Debug for OutOfRange {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for OutOfRange {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "out of range");
}
}

#[cfg(feature = "std")]
impl std::error::Error for OutOfRange {}

Expand Down
7 changes: 7 additions & 0 deletions src/month.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,13 @@ impl fmt::Debug for ParseMonthError {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for ParseMonthError {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "ParseMonthError {{ .. }}")
}
}

#[cfg(feature = "serde")]
mod month_serde {
use super::Month;
Expand Down
19 changes: 19 additions & 0 deletions src/naive/date/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,7 @@ impl From<NaiveDateTime> for NaiveDate {

/// Iterator over `NaiveDate` with a step size of one day.
#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct NaiveDateDaysIterator {
value: NaiveDate,
}
Expand Down Expand Up @@ -2164,6 +2165,7 @@ impl FusedIterator for NaiveDateDaysIterator {}

/// Iterator over `NaiveDate` with a step size of one week.
#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct NaiveDateWeeksIterator {
value: NaiveDate,
}
Expand Down Expand Up @@ -2238,6 +2240,23 @@ impl fmt::Debug for NaiveDate {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for NaiveDate {
fn format(&self, fmt: defmt::Formatter) {
let year = self.year();
let mdf = self.mdf();
if (0..=9999).contains(&year) {
defmt::write!(fmt, "{:02}{:02}", year / 100, year % 100);
} else {
// ISO 8601 requires the explicit sign for out-of-range years
let sign = ['+', '-'][(year < 0) as usize];
defmt::write!(fmt, "{}{:05}", sign, year.abs());
}

defmt::write!(fmt, "-{:02}-{:02}", mdf.month(), mdf.day());
}
}

/// The `Display` output of the naive date `d` is the same as
/// [`d.format("%Y-%m-%d")`](crate::format::strftime).
///
Expand Down
7 changes: 7 additions & 0 deletions src/naive/datetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2053,6 +2053,13 @@ impl fmt::Debug for NaiveDateTime {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for NaiveDateTime {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{}T{}", self.date, self.time);
}
}

/// The `Display` output of the naive date and time `dt` is the same as
/// [`dt.format("%Y-%m-%d %H:%M:%S%.f")`](crate::format::strftime).
///
Expand Down
15 changes: 15 additions & 0 deletions src/naive/isoweek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,21 @@ impl fmt::Debug for IsoWeek {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for IsoWeek {
fn format(&self, fmt: defmt::Formatter) {
let year = self.year();
let week = self.week();
if (0..=9999).contains(&year) {
defmt::write!(fmt, "{:04}-W{:02}", year, week)
} else {
// ISO 8601 requires the explicit sign for out-of-range years
let sign = ['+', '-'][(year < 0) as usize];
defmt::write!(fmt, "{}{:05}-W{:02}", sign, year.abs(), week)
}
}
}

#[cfg(test)]
mod tests {
#[cfg(feature = "rkyv-validation")]
Expand Down
25 changes: 25 additions & 0 deletions src/naive/time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,31 @@ impl fmt::Debug for NaiveTime {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for NaiveTime {
fn format(&self, fmt: defmt::Formatter) {
let (hour, min, sec) = self.hms();
let (sec, nano) = if self.frac >= 1_000_000_000 {
(sec + 1, self.frac - 1_000_000_000)
} else {
(sec, self.frac)
};

let (hour, min, sec) = (hour as u8, min as u8, sec as u8);
defmt::write!(fmt, "{:02}:{:02}:{:02}", hour, min, sec);

if nano == 0 {
return;
} else if nano % 1_000_000 == 0 {
defmt::write!(fmt, ".{:03}", nano / 1_000_000);
} else if nano % 1_000 == 0 {
defmt::write!(fmt, ".{:06}", nano / 1_000);
} else {
defmt::write!(fmt, ".{:09}", nano);
}
}
}

/// The `Display` output of the naive time `t` is the same as
/// [`t.format("%H:%M:%S%.f")`](crate::format::strftime).
///
Expand Down
1 change: 1 addition & 0 deletions src/offset/fixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::naive::{NaiveDate, NaiveDateTime};
archive_attr(derive(Clone, Copy, PartialEq, Eq, Hash, Debug))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FixedOffset {
local_minus_utc: i32,
}
Expand Down
1 change: 1 addition & 0 deletions src/offset/local/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ mod tz_info;
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Local;

impl Local {
Expand Down
1 change: 1 addition & 0 deletions src/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ where
///
/// See: [`DurationRound`]
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum RoundingError {
/// Error when the TimeDelta exceeds the TimeDelta from or until the Unix epoch.
///
Expand Down
2 changes: 2 additions & 0 deletions src/time_delta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const SECS_PER_WEEK: i64 = 604_800;
archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct TimeDelta {
secs: i64,
nanos: i32, // Always 0 <= nanos < NANOS_PER_SEC
Expand Down Expand Up @@ -600,6 +601,7 @@ impl fmt::Display for TimeDelta {
/// *seconds*, while this module supports signed range of up to
/// `i64::MAX` of *milliseconds*.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct OutOfRangeError(());

impl fmt::Display for OutOfRangeError {
Expand Down
8 changes: 8 additions & 0 deletions src/weekday.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use crate::OutOfRange;
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Weekday {
/// Monday.
Mon = 0,
Expand Down Expand Up @@ -257,6 +258,13 @@ impl fmt::Debug for ParseWeekdayError {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for ParseWeekdayError {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "ParseWeekdayError {{ .. }}")
}
}

// the actual `FromStr` implementation is in the `format` module to leverage the existing code

#[cfg(feature = "serde")]
Expand Down

0 comments on commit 3b7b3f9

Please sign in to comment.