Skip to content

feat: add flat string serde support for Date, Time and DateTime #50

Description

@ZialeHub

Summary

Currently, serializing a Date, Time, or DateTime produces a nested JSON object:

{ "date": "2023-10-09" }
{ "time": "12:21:46" }
{ "datetime": "2023-10-09T00:00:00" }

The vast majority of REST APIs, databases, and configuration formats represent temporal values as flat strings:

"2023-10-09"
"2024-10-31 06:32:28"

Without flat serde support, consumers must wrap timeflow types in newtype structs or write fully custom Deserialize impls, which directly undermines the library's goal of reducing boilerplate.


Proposed API

serde(with) modules (recommended)

Expose dedicated modules usable with #[serde(with = "...")]:

use timeflow::prelude::*;

#[derive(Serialize, Deserialize)]
struct Event {
    #[serde(with = "timeflow::serde::flat")]
    begin_at: Date,

    #[serde(with = "timeflow::serde::flat")]
    ends_at: DateTime,
}

Serializes to:

{ "begin_at": "2024-10-31", "ends_at": "2024-10-31 06:32:28" }

A companion flat_opt module should handle Option<Date> / Option<DateTime> fields, serializing None as JSON null.


Implementation Notes

  • The flat deserializer must use the active BASE_*_FORMAT globals so it respects any SpanBuilder configuration set at startup.
  • Both serialize and deserialize functions must be provided inside the module so #[serde(with = "...")] works without splitting into serialize_with / deserialize_with.
  • The existing default (nested-object) serde behaviour must remain unchanged for full backwards compatibility.
  • The existing deserialize_with_format / serialize_with_format custom-format hooks should remain unaffected.

Acceptance Criteria

  • #[serde(with = "timeflow::serde::flat")] compiles and works on Date, Time, and DateTime fields
  • Flat serialization produces a bare JSON string, not a nested object
  • Flat deserialization parses a bare JSON string using the active BASE_*_FORMAT
  • timeflow::serde::flat_opt handles Option<T> fields correctly (Nonenull, Some(t)"string")
  • Existing default (nested) serde behaviour is unchanged — no breaking change
  • Unit tests cover: serialize, deserialize, round-trip, invalid input, and Option variants
  • README and module-level docs updated with a usage example

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-domainbusiness logic / coreB-ideaDiscussion; or implementation attempt, to be reviewed before further work

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions