Skip to content

Commit c503b50

Browse files
committed
Add feature gated defmt support.
1 parent 334565c commit c503b50

File tree

24 files changed

+204
-2
lines changed

24 files changed

+204
-2
lines changed

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ name = "chrono"
2020
# Don't forget to adjust `ALL_NON_EXCLUSIVE_FEATURES` in CI scripts when adding a feature or an optional dependency.
2121
default = ["clock", "std", "oldtime", "wasmbind"]
2222
alloc = []
23+
defmt = ["dep:defmt", "pure-rust-locales?/defmt"]
2324
libc = []
2425
winapi = ["windows-link"]
2526
std = ["alloc"]
@@ -41,9 +42,10 @@ __internal_bench = []
4142
[dependencies]
4243
num-traits = { version = "0.2", default-features = false }
4344
serde = { version = "1.0.99", default-features = false, optional = true }
44-
pure-rust-locales = { version = "0.8", optional = true }
45+
pure-rust-locales = { version = "0.8.2", optional = true }
4546
rkyv = { version = "0.7.43", optional = true, default-features = false }
4647
arbitrary = { version = "1.0.0", features = ["derive"], optional = true }
48+
defmt = { version = "1.0.1", optional = true }
4749

4850
[target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies]
4951
wasm-bindgen = { version = "0.2", optional = true }

src/date.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,16 @@ where
551551
}
552552
}
553553

554+
#[cfg(feature = "defmt")]
555+
impl<Tz: TimeZone> defmt::Format for Date<Tz>
556+
where
557+
Tz::Offset: defmt::Format,
558+
{
559+
fn format(&self, fmt: defmt::Formatter) {
560+
defmt::write!(fmt, "{}{}", self.naive_local(), self.offset);
561+
}
562+
}
563+
554564
// Note that implementation of Arbitrary cannot be automatically derived for Date<Tz>, due to
555565
// the nontrivial bound <Tz as TimeZone>::Offset: Arbitrary.
556566
#[cfg(all(feature = "arbitrary", feature = "std"))]

src/datetime/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,16 @@ impl<Tz: TimeZone> fmt::Debug for DateTime<Tz> {
18121812
}
18131813
}
18141814

1815+
#[cfg(feature = "defmt")]
1816+
impl<Tz: TimeZone> defmt::Format for DateTime<Tz>
1817+
where
1818+
Tz::Offset: defmt::Format,
1819+
{
1820+
fn format(&self, fmt: defmt::Formatter) {
1821+
defmt::write!(fmt, "{}{}", self.overflowing_naive_local(), self.offset);
1822+
}
1823+
}
1824+
18151825
// `fmt::Debug` is hand implemented for the `rkyv::Archive` variant of `DateTime` because
18161826
// deriving a trait recursively does not propagate trait defined associated types with their own
18171827
// constraints:

src/datetime/serde.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,22 @@ use crate::offset::{FixedOffset, Offset, TimeZone, Utc};
99

1010
#[doc(hidden)]
1111
#[derive(Debug)]
12+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1213
pub struct SecondsTimestampVisitor;
1314

1415
#[doc(hidden)]
1516
#[derive(Debug)]
17+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1618
pub struct NanoSecondsTimestampVisitor;
1719

1820
#[doc(hidden)]
1921
#[derive(Debug)]
22+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2023
pub struct MicroSecondsTimestampVisitor;
2124

2225
#[doc(hidden)]
2326
#[derive(Debug)]
27+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2428
pub struct MilliSecondsTimestampVisitor;
2529

2630
/// Serialize to an RFC 3339 formatted string

src/format/formatting.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ impl OffsetFormat {
474474
///
475475
/// See the `TimeZone::to_rfc3339_opts` function for usage.
476476
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
477+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
477478
#[allow(clippy::manual_non_exhaustive)]
478479
pub enum SecondsFormat {
479480
/// Format whole seconds only, with no decimal point nor subseconds.

src/format/mod.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ enum Void {}
7878

7979
/// Padding characters for numeric items.
8080
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
81+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8182
pub enum Pad {
8283
/// No padding.
8384
None,
@@ -102,6 +103,7 @@ pub enum Pad {
102103
/// parsed with the same formatting items.
103104
#[non_exhaustive]
104105
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
106+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
105107
pub enum Numeric {
106108
/// Full Gregorian year (FW=4, PW=∞).
107109
/// May accept years before 1 BCE or after 9999 CE, given an initial sign (+/-).
@@ -170,12 +172,20 @@ impl fmt::Debug for InternalNumeric {
170172
}
171173
}
172174

175+
#[cfg(feature = "defmt")]
176+
impl defmt::Format for InternalNumeric {
177+
fn format(&self, f: defmt::Formatter) {
178+
defmt::write!(f, "<InternalNumeric>")
179+
}
180+
}
181+
173182
/// Fixed-format item types.
174183
///
175184
/// They have their own rules of formatting and parsing.
176185
/// Otherwise noted, they print in the specified cases but parse case-insensitively.
177186
#[non_exhaustive]
178187
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
188+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
179189
pub enum Fixed {
180190
/// Abbreviated month names.
181191
///
@@ -260,11 +270,13 @@ pub enum Fixed {
260270

261271
/// An opaque type representing fixed-format item types for internal uses only.
262272
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
273+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
263274
pub struct InternalFixed {
264275
val: InternalInternal,
265276
}
266277

267278
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
279+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
268280
enum InternalInternal {
269281
/// Same as [`TimezoneOffsetColonZ`](#variant.TimezoneOffsetColonZ), but
270282
/// allows missing minutes (per [ISO 8601][iso8601]).
@@ -285,6 +297,7 @@ enum InternalInternal {
285297

286298
/// Type for specifying the format of UTC offsets.
287299
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
300+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
288301
pub struct OffsetFormat {
289302
/// See `OffsetPrecision`.
290303
pub precision: OffsetPrecision,
@@ -298,6 +311,7 @@ pub struct OffsetFormat {
298311

299312
/// The precision of an offset from UTC formatting item.
300313
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
314+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
301315
pub enum OffsetPrecision {
302316
/// Format offset from UTC as only hours. Not recommended, it is not uncommon for timezones to
303317
/// have an offset of 30 minutes, 15 minutes, etc.
@@ -319,6 +333,7 @@ pub enum OffsetPrecision {
319333

320334
/// The separator between hours and minutes in an offset.
321335
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
336+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
322337
pub enum Colons {
323338
/// No separator
324339
None,
@@ -350,6 +365,23 @@ pub enum Item<'a> {
350365
Error,
351366
}
352367

368+
#[cfg(feature = "defmt")]
369+
impl<'a> defmt::Format for Item<'a> {
370+
fn format(&self, f: defmt::Formatter) {
371+
match self {
372+
Item::Literal(v) => defmt::write!(f, "Literal {{ {} }}", v),
373+
#[cfg(feature = "alloc")]
374+
Item::OwnedLiteral(_) => {}
375+
Item::Space(v) => defmt::write!(f, "Space {{ {} }}", v),
376+
#[cfg(feature = "alloc")]
377+
Item::OwnedSpace(_) => {}
378+
Item::Numeric(u, v) => defmt::write!(f, "Numeric {{ {}, {} }}", u, v),
379+
Item::Fixed(v) => defmt::write!(f, "Fixed {{ {} }}", v),
380+
Item::Error => defmt::write!(f, "Error"),
381+
}
382+
}
383+
}
384+
353385
const fn num(numeric: Numeric) -> Item<'static> {
354386
Item::Numeric(numeric, Pad::None)
355387
}
@@ -388,6 +420,7 @@ impl Item<'_> {
388420

389421
/// An error from the `parse` function.
390422
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
423+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
391424
pub struct ParseError(ParseErrorKind);
392425

393426
impl ParseError {
@@ -400,6 +433,7 @@ impl ParseError {
400433
/// The category of parse error
401434
#[allow(clippy::manual_non_exhaustive)]
402435
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
436+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
403437
pub enum ParseErrorKind {
404438
/// Given field is out of permitted range.
405439
OutOfRange,

src/format/parsed.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ use crate::{DateTime, Datelike, TimeDelta, Timelike, Weekday};
126126
/// ```
127127
#[allow(clippy::manual_non_exhaustive)]
128128
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
129+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129130
pub struct Parsed {
130131
#[doc(hidden)]
131132
pub year: Option<i32>,

src/format/strftime.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ use alloc::vec::Vec;
189189
/// [`DateTime`]: crate::DateTime
190190
/// [`format::parse()`]: crate::format::parse()
191191
#[derive(Clone, Debug)]
192+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
192193
pub struct StrftimeItems<'a> {
193194
/// Remaining portion of the string.
194195
remainder: &'a str,

src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,13 @@ impl fmt::Debug for OutOfRange {
687687
}
688688
}
689689

690+
#[cfg(feature = "defmt")]
691+
impl defmt::Format for OutOfRange {
692+
fn format(&self, fmt: defmt::Formatter) {
693+
defmt::write!(fmt, "out of range");
694+
}
695+
}
696+
690697
#[cfg(feature = "std")]
691698
impl std::error::Error for OutOfRange {}
692699

src/month.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use crate::naive::NaiveDate;
3838
)]
3939
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
4040
#[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(arbitrary::Arbitrary))]
41+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
4142
pub enum Month {
4243
/// January
4344
January = 0,
@@ -248,6 +249,7 @@ impl num_traits::FromPrimitive for Month {
248249
/// A duration in calendar months
249250
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
250251
#[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(arbitrary::Arbitrary))]
252+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
251253
pub struct Months(pub(crate) u32);
252254

253255
impl Months {
@@ -287,6 +289,13 @@ impl fmt::Debug for ParseMonthError {
287289
}
288290
}
289291

292+
#[cfg(feature = "defmt")]
293+
impl defmt::Format for ParseMonthError {
294+
fn format(&self, fmt: defmt::Formatter) {
295+
defmt::write!(fmt, "ParseMonthError {{ .. }}")
296+
}
297+
}
298+
290299
#[cfg(feature = "serde")]
291300
mod month_serde {
292301
use super::Month;

0 commit comments

Comments
 (0)