Skip to content

Commit

Permalink
Merge #450
Browse files Browse the repository at this point in the history
450: Add support for `time` v0.3 types r=jonasbb a=jonasbb

Add support for the `time` crate v0.3.

* Convert `time::Duration` with `Duration*Second`.
* Convert `time::OffsetDateTime` and `time::PrimitiveDateTime` with `Timestamp*Seconds`.
* Turn `Rfc2822` and `Rfc3339` into conversion type, such that they can be used inside collections.
* Add tests for the new functionality

Todo:
* [x] Update Changelog

Co-authored-by: Jonas Bushart <jonas@bushart.org>
  • Loading branch information
bors[bot] and jonasbb committed May 12, 2022
2 parents d935f5f + 64bdb23 commit 4213291
Show file tree
Hide file tree
Showing 13 changed files with 718 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Expand Up @@ -71,7 +71,7 @@ jobs:
# It is good to test more than the MSRV and stable since sometimes
# breakage occurs in intermediate versions.
# IMPORTANT: Synchronize the MSRV with the Cargo.toml values.
rust: ["1.46", "1.50", "1.55", "stable", "beta", "nightly"]
rust: ["1.53", "1.55", "1.60", "stable", "beta", "nightly"]
crate: ["serde_with", "serde_with_macros", "serde_with_test"]
runs-on: ${{ matrix.os }}
steps:
Expand Down
50 changes: 48 additions & 2 deletions serde_with/CHANGELOG.md
Expand Up @@ -7,6 +7,52 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Added

* Add support for `time` crate v0.3 #450

`time::Duration` can now be serialized with the `DurationSeconds` and related converters.

```rust
// Rust
#[serde_as(as = "serde_with::DurationSeconds<u64>")]
value: Duration,

// JSON
"value": 86400,
```

`time::OffsetDateTime` and `time::PrimitiveDateTime` can now be serialized with the `TimestampSeconds` and related converters.


```rust
// Rust
#[serde_as(as = "serde_with::TimestampMicroSecondsWithFrac<String>")]
value: time::PrimitiveDateTime,

// JSON
"value": "1000000",
```

`time::OffsetDateTime` can be serialized in string format in different well-known formats.
Two formats are supported, `time::format_description::well_known::Rfc2822` and `time::format_description::well_known::Rfc3339`.

```rust
// Rust
#[serde_as(as = "time::format_description::well_known::Rfc2822")]
rfc_2822: OffsetDateTime,
#[serde_as(as = "Vec<time::format_description::well_known::Rfc3339>")]
rfc_3339: Vec<OffsetDateTime>,

// JSON
"rfc_2822": "Fri, 21 Nov 1997 09:55:06 -0600",
"rfc_3339": ["1997-11-21T09:55:06-06:00"],
```

### Changed

* Bump MSRV to 1.53, since the new dependency `time` requires that version.

### Fixed

* Make the documentation clearer by stating that the `#[serde_as]` and `#[skip_serializing_none]` attributes must always be places before `#[derive]`.
Expand Down Expand Up @@ -143,9 +189,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

The `#[serde(borrow)]` annotation is automatically added by the `#[serde_as]` attribute.

## Changed
### Changed

* Bump MSRV to 1.46, since the dev-dependency bitflags requires that version now.
* Bump MSRV to 1.46, since the dev-dependency `bitflags` requires that version now.
* `flattened_maybe!` no longer requires the `serde_with` crate to be available with a specific name.
This allows renaming the crate or using `flattened_maybe!` through a re-export without any complications.

Expand Down
8 changes: 7 additions & 1 deletion serde_with/Cargo.toml
Expand Up @@ -5,7 +5,7 @@ authors = [
"Marcin Kaźmierczak",
]
name = "serde_with"
rust-version = "1.46"
rust-version = "1.53"
version = "1.13.0"

categories = ["encoding"]
Expand Down Expand Up @@ -43,6 +43,7 @@ rustversion = "1.0.0"
serde = {version = "1.0.122", features = ["derive"]}
serde_json = {version = "1.0.1", optional = true}
serde_with_macros = {path = "../serde_with_macros", version = "1.5.2", optional = true}
time_0_3 = {package = "time", version = "~0.3", optional = true, features = ["serde-well-known"]}

[dev-dependencies]
expect-test = "1.0.0"
Expand Down Expand Up @@ -89,6 +90,11 @@ name = "serde_as"
path = "tests/serde_as/lib.rs"
required-features = ["macros"]

[[test]]
name = "time_0_3"
path = "tests/time_0_3.rs"
required-features = ["macros", "time_0_3"]

[[test]]
name = "derives"
path = "tests/derives/lib.rs"
Expand Down
8 changes: 8 additions & 0 deletions serde_with/src/guide/feature_flags.md
Expand Up @@ -10,6 +10,7 @@ Each entry will explain the feature in more detail.
5. [`indexmap`](#indexmap)
6. [`json`](#json)
7. [`macros`](#macros)
8. [`time_0_3`](#time_0_3)

## `base64`

Expand Down Expand Up @@ -52,3 +53,10 @@ The `macros` features enables all helper macros and derives.
It is enabled by default, since the macros provide a usability benefit, especially for `serde_as`.

This pulls in `serde_with_macros` as a dependency.

## `time_0_3`

The `time_0_3` enables integration of `time` v0.3 specific conversions.
This includes support for the timestamp and duration types.

This pulls in `time` v0.3 as a dependency.
29 changes: 29 additions & 0 deletions serde_with/src/guide/serde_as_transformations.md
Expand Up @@ -23,6 +23,7 @@ This page lists the transformations implemented in this crate and supported by `
19. [Timestamps as seconds since UNIX epoch](#timestamps-as-seconds-since-unix-epoch)
20. [Value into JSON String](#value-into-json-string)
21. [`Vec` of tuples to `Maps`](#vec-of-tuples-to-maps)
22. [Well-known time formats for `OffsetDateTime`](#well-known-time-formats-for-offsetdatetime)

## Base64 encode bytes

Expand Down Expand Up @@ -212,6 +213,8 @@ value: Duration,

The same conversions are also implemented for [`chrono::Duration`] with the `chrono` feature.

The same conversions are also implemented for [`time::Duration`] with the `time_0_3` feature.

## Hex encode bytes

[`Hex`]
Expand Down Expand Up @@ -405,6 +408,8 @@ value: SystemTime,

The same conversions are also implemented for [`chrono::DateTime<Utc>`], [`chrono::DateTime<Local>`], and [`chrono::NaiveDateTime`] with the `chrono` feature.

The conversions are availble for [`time::OffsetDateTime`] and [`time::PrimitiveDateTime`] with the `time_0_3` feature enabled.

## Value into JSON String

Some JSON APIs are weird and return a JSON encoded string in a JSON response
Expand Down Expand Up @@ -446,6 +451,25 @@ This includes `BinaryHeap<(K, V)>`, `BTreeSet<(K, V)>`, `HashSet<(K, V)>`, `Link

The [inverse operation](#maps-to-vec-of-tuples) is also available.

## Well-known time formats for `OffsetDateTime`

[`time::OffsetDateTime`] can be serialized in string format in different well-known formats.
Two formats are supported, [`time::format_description::well_known::Rfc2822`] and [`time::format_description::well_known::Rfc3339`].

```ignore
// Rust
#[serde_as(as = "time::format_description::well_known::Rfc2822")]
rfc_2822: OffsetDateTime,
#[serde_as(as = "time::format_description::well_known::Rfc3339")]
rfc_3339: OffsetDateTime,
// JSON
"rfc_2822": "Fri, 21 Nov 1997 09:55:06 -0600",
"rfc_3339": "1997-11-21T09:55:06-06:00",
```

These conversions are availble with the `time_0_3` feature flag.

[`Base64`]: crate::base64::Base64
[`Bytes`]: crate::Bytes
[`chrono::DateTime<Local>`]: chrono_crate::DateTime
Expand All @@ -464,6 +488,11 @@ The [inverse operation](#maps-to-vec-of-tuples) is also available.
[`NoneAsEmptyString`]: crate::NoneAsEmptyString
[`OneOrMany`]: crate::OneOrMany
[`PickFirst`]: crate::PickFirst
[`time::Duration`]: time_0_3::Duration
[`time::format_description::well_known::Rfc2822`]: time_0_3::format_description::well_known::Rfc2822
[`time::format_description::well_known::Rfc3339`]: time_0_3::format_description::well_known::Rfc3339
[`time::OffsetDateTime`]: time_0_3::OffsetDateTime
[`time::PrimitiveDateTime`]: time_0_3::PrimitiveDateTime
[`TimestampSeconds`]: crate::TimestampSeconds
[`TimestampSecondsWithFrac`]: crate::TimestampSecondsWithFrac
[`TryFromInto`]: crate::TryFromInto
Expand Down
19 changes: 19 additions & 0 deletions serde_with/src/lib.rs
Expand Up @@ -279,6 +279,9 @@ pub mod json;
pub mod rust;
pub mod ser;
mod serde_conv;
#[cfg(feature = "time_0_3")]
#[cfg_attr(docsrs, doc(cfg(feature = "time_0_3")))]
pub mod time_0_3;
mod utils;
#[doc(hidden)]
pub mod with_prefix;
Expand Down Expand Up @@ -746,13 +749,16 @@ pub struct BytesOrString;
/// For example, deserializing `DurationSeconds<f64, Flexible>` will discard any subsecond precision during deserialization from `f64` and will parse a `String` as an integer number.
///
/// This type also supports [`chrono::Duration`] with the `chrono`-[feature flag].
/// This type also supports [`time::Duration`][::time_0_3::Duration] with the `time_0_3`-[feature flag].
///
/// | Duration Type | Converter | Available `FORMAT`s |
/// | --------------------- | ------------------------- | ---------------------- |
/// | `std::time::Duration` | `DurationSeconds` | `u64`, `f64`, `String` |
/// | `std::time::Duration` | `DurationSecondsWithFrac` | `f64`, `String` |
/// | `chrono::Duration` | `DurationSeconds` | `i64`, `f64`, `String` |
/// | `chrono::Duration` | `DurationSecondsWithFrac` | `f64`, `String` |
/// | `time::Duration` | `DurationSeconds` | `i64`, `f64`, `String` |
/// | `time::Duration` | `DurationSecondsWithFrac` | `f64`, `String` |
///
/// # Examples
///
Expand Down Expand Up @@ -886,13 +892,16 @@ pub struct DurationSeconds<
/// For example, deserializing `DurationSeconds<f64, Flexible>` will discard any subsecond precision during deserialization from `f64` and will parse a `String` as an integer number.
///
/// This type also supports [`chrono::Duration`] with the `chrono`-[feature flag].
/// This type also supports [`time::Duration`][::time_0_3::Duration] with the `time_0_3`-[feature flag].
///
/// | Duration Type | Converter | Available `FORMAT`s |
/// | --------------------- | ------------------------- | ---------------------- |
/// | `std::time::Duration` | `DurationSeconds` | `u64`, `f64`, `String` |
/// | `std::time::Duration` | `DurationSecondsWithFrac` | `f64`, `String` |
/// | `chrono::Duration` | `DurationSeconds` | `i64`, `f64`, `String` |
/// | `chrono::Duration` | `DurationSecondsWithFrac` | `f64`, `String` |
/// | `time::Duration` | `DurationSeconds` | `i64`, `f64`, `String` |
/// | `time::Duration` | `DurationSecondsWithFrac` | `f64`, `String` |
///
/// # Examples
///
Expand Down Expand Up @@ -1066,6 +1075,7 @@ pub struct DurationNanoSecondsWithFrac<
/// For example, deserializing `TimestampSeconds<f64, Flexible>` will discard any subsecond precision during deserialization from `f64` and will parse a `String` as an integer number.
///
/// This type also supports [`chrono::DateTime`][DateTime] with the `chrono`-[feature flag].
/// This type also supports [`time::OffsetDateTime`][::time_0_3::OffsetDateTime] and [`time::PrimitiveDateTime`][::time_0_3::PrimitiveDateTime] with the `time_0_3`-[feature flag].
///
/// | Timestamp Type | Converter | Available `FORMAT`s |
/// | ------------------------- | -------------------------- | ---------------------- |
Expand All @@ -1075,6 +1085,10 @@ pub struct DurationNanoSecondsWithFrac<
/// | `chrono::DateTime<Utc>` | `TimestampSecondsWithFrac` | `f64`, `String` |
/// | `chrono::DateTime<Local>` | `TimestampSeconds` | `i64`, `f64`, `String` |
/// | `chrono::DateTime<Local>` | `TimestampSecondsWithFrac` | `f64`, `String` |
/// | `time::OffsetDateTime` | `TimestampSeconds` | `i64`, `f64`, `String` |
/// | `time::OffsetDateTime` | `TimestampSecondsWithFrac` | `f64`, `String` |
/// | `time::PrimitiveDateTime` | `TimestampSeconds` | `i64`, `f64`, `String` |
/// | `time::PrimitiveDateTime` | `TimestampSecondsWithFrac` | `f64`, `String` |
///
/// # Examples
///
Expand Down Expand Up @@ -1209,6 +1223,7 @@ pub struct TimestampSeconds<
/// For example, deserializing `TimestampSeconds<f64, Flexible>` will discard any subsecond precision during deserialization from `f64` and will parse a `String` as an integer number.
///
/// This type also supports [`chrono::DateTime`][DateTime] and [`chrono::NaiveDateTime`][NaiveDateTime] with the `chrono`-[feature flag].
/// This type also supports [`time::OffsetDateTime`][::time_0_3::OffsetDateTime] and [`time::PrimitiveDateTime`][::time_0_3::PrimitiveDateTime] with the `time_0_3`-[feature flag].
///
/// | Timestamp Type | Converter | Available `FORMAT`s |
/// | ------------------------- | -------------------------- | ---------------------- |
Expand All @@ -1220,6 +1235,10 @@ pub struct TimestampSeconds<
/// | `chrono::DateTime<Local>` | `TimestampSecondsWithFrac` | `f64`, `String` |
/// | `chrono::NaiveDateTime` | `TimestampSeconds` | `i64`, `f64`, `String` |
/// | `chrono::NaiveDateTime` | `TimestampSecondsWithFrac` | `f64`, `String` |
/// | `time::OffsetDateTime` | `TimestampSeconds` | `i64`, `f64`, `String` |
/// | `time::OffsetDateTime` | `TimestampSecondsWithFrac` | `f64`, `String` |
/// | `time::PrimitiveDateTime` | `TimestampSeconds` | `i64`, `f64`, `String` |
/// | `time::PrimitiveDateTime` | `TimestampSecondsWithFrac` | `f64`, `String` |
///
/// # Examples
///
Expand Down

0 comments on commit 4213291

Please sign in to comment.