#! [allow(
// clippy is broken and shows wrong warnings
// clippy on stable does not know yet about the lint name
unknown_lints,
// https://github.com/rust-lang/rust-clippy/issues/8867
clippy::derive_partial_eq_without_eq,
)]
mod utils;
use crate ::utils::{check_deserialization, check_error_deserialization, is_equal};
use expect_test::expect;
use serde::{Deserialize, Serialize};
use serde_with::{
serde_as, DurationMicroSeconds, DurationMicroSecondsWithFrac, DurationMilliSeconds,
DurationMilliSecondsWithFrac, DurationNanoSeconds, DurationNanoSecondsWithFrac,
DurationSeconds, DurationSecondsWithFrac, TimestampMicroSeconds, TimestampMicroSeco
ndsWithFrac,
TimestampMilliSeconds, TimestampMilliSecondsWithFrac, TimestampNanoSeconds,
TimestampNanoSecondsWithFrac, TimestampSeconds, TimestampSecondsWithFrac,
};
use time_0_3::{Duration, OffsetDateTime, PrimitiveDateTime, UtcOffset};
/// Create a [`PrimitiveDateTime`] for the Unix Epoch
fn unix_epoch_primitive() -> PrimitiveDateTime {
PrimitiveDateTime::new(
time_0_3::Date::from_ordinal_date(1970 , 1 ).unwrap(),
time_0_3::Time::from_hms_nano(0 , 0 , 0 , 0 ).unwrap(),
)
}
macro_rules! smoketest {
($($valuety:ty, $adapter:literal, $value:expr, $expect:tt;)*) => {
$({
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S(#[ serde_as(as = $adapter)] $valuety);
#[ allow(unused_braces)]
is_equal(S($value), $expect);
})*
};
}
#[ test]
fn test_duration_smoketest() {
let zero = Duration::seconds(0 );
let one_second = Duration::seconds(1 );
smoketest! {
Duration, "DurationSeconds<i64>" , one_second, {expect![[r#" 1 "#]]};
Duration, "DurationSeconds<f64>" , one_second, {expect![[r#" 1 .0 "#]]};
Duration, "DurationMilliSeconds<i64>" , one_second, {expect![[r#" 1000 "#]]};
Duration, "DurationMilliSeconds<f64>" , one_second, {expect![[r#" 1000 .0 "#]]};
Duration, "DurationMicroSeconds<i64>" , one_second, {expect![[r#" 1000000 "#]]};
Duration, "DurationMicroSeconds<f64>" , one_second, {expect![[r#" 1000000 .0 "#]]};
Duration, "DurationNanoSeconds<i64>" , one_second, {expect![[r#" 1000000000 "#]]};
Duration, "DurationNanoSeconds<f64>" , one_second, {expect![[r#" 1000000000 .0 "#]]};
};
smoketest! {
Duration, "DurationSecondsWithFrac" , one_second, {expect![[r#" 1 .0 "#]]};
Duration, "DurationSecondsWithFrac<String>" , one_second, {expect![[r#" "1" "#]]};
Duration, "DurationMilliSecondsWithFrac" , one_second, {expect![[r#" 1000 .0 "#]]};
Duration, "DurationMilliSecondsWithFrac<String>" , one_second, {expect![[r#" "1000" "#]]};
Duration, "DurationMicroSecondsWithFrac" , one_second, {expect![[r#" 1000000 .0 "#]]};
Duration, "DurationMicroSecondsWithFrac<String>" , one_second, {expect![[r#" "1000000" "#]]};
Duration, "DurationNanoSecondsWithFrac" , one_second, {expect![[r#" 1000000000 .0 "#]]};
Duration, "DurationNanoSecondsWithFrac<String>" , one_second, {expect![[r#" "1000000000" "#]]};
};
smoketest! {
Duration, "DurationSecondsWithFrac" , zero, {expect![[r#" 0 .0 "#]]};
Duration, "DurationSecondsWithFrac" , zero + Duration::nanoseconds(500 _000 _000 ), {expect![[r#" 0 .5 "#]]};
Duration, "DurationSecondsWithFrac" , zero + Duration::seconds(1 ), {expect![[r#" 1 .0 "#]]};
Duration, "DurationSecondsWithFrac" , zero - Duration::nanoseconds(500 _000 _000 ), {expect![[r#" -0 .5 "#]]};
Duration, "DurationSecondsWithFrac" , zero - Duration::seconds(1 ), {expect![[r#" -1 .0 "#]]};
};
}
#[ test]
fn test_datetime_utc_smoketest() {
let zero = OffsetDateTime::UNIX_EPOCH;
let one_second = zero + Duration::seconds(1 );
smoketest! {
OffsetDateTime, "TimestampSeconds<i64>" , one_second, {expect![[r#" 1 "#]]};
OffsetDateTime, "TimestampSeconds<f64>" , one_second, {expect![[r#" 1 .0 "#]]};
OffsetDateTime, "TimestampMilliSeconds<i64>" , one_second, {expect![[r#" 1000 "#]]};
OffsetDateTime, "TimestampMilliSeconds<f64>" , one_second, {expect![[r#" 1000 .0 "#]]};
OffsetDateTime, "TimestampMicroSeconds<i64>" , one_second, {expect![[r#" 1000000 "#]]};
OffsetDateTime, "TimestampMicroSeconds<f64>" , one_second, {expect![[r#" 1000000 .0 "#]]};
OffsetDateTime, "TimestampNanoSeconds<i64>" , one_second, {expect![[r#" 1000000000 "#]]};
OffsetDateTime, "TimestampNanoSeconds<f64>" , one_second, {expect![[r#" 1000000000 .0 "#]]};
};
smoketest! {
OffsetDateTime, "TimestampSecondsWithFrac" , one_second, {expect![[r#" 1 .0 "#]]};
OffsetDateTime, "TimestampSecondsWithFrac<String>" , one_second, {expect![[r#" "1" "#]]};
OffsetDateTime, "TimestampMilliSecondsWithFrac" , one_second, {expect![[r#" 1000 .0 "#]]};
OffsetDateTime, "TimestampMilliSecondsWithFrac<String>" , one_second, {expect![[r#" "1000" "#]]};
OffsetDateTime, "TimestampMicroSecondsWithFrac" , one_second, {expect![[r#" 1000000 .0 "#]]};
OffsetDateTime, "TimestampMicroSecondsWithFrac<String>" , one_second, {expect![[r#" "1000000" "#]]};
OffsetDateTime, "TimestampNanoSecondsWithFrac" , one_second, {expect![[r#" 1000000000 .0 "#]]};
OffsetDateTime, "TimestampNanoSecondsWithFrac<String>" , one_second, {expect![[r#" "1000000000" "#]]};
};
smoketest! {
OffsetDateTime, "TimestampSecondsWithFrac" , zero, {expect![[r#" 0 .0 "#]]};
OffsetDateTime, "TimestampSecondsWithFrac" , zero + Duration::nanoseconds(500 _000 _000 ), {expect![[r#" 0 .5 "#]]};
OffsetDateTime, "TimestampSecondsWithFrac" , zero + Duration::seconds(1 ), {expect![[r#" 1 .0 "#]]};
OffsetDateTime, "TimestampSecondsWithFrac" , zero - Duration::nanoseconds(500 _000 _000 ), {expect![[r#" -0 .5 "#]]};
OffsetDateTime, "TimestampSecondsWithFrac" , zero - Duration::seconds(1 ), {expect![[r#" -1 .0 "#]]};
};
}
#[ test]
fn test_naive_datetime_smoketest() {
let zero = unix_epoch_primitive();
let one_second = zero + Duration::seconds(1 );
smoketest! {
PrimitiveDateTime, "TimestampSeconds<i64>" , one_second, {expect![[r#" 1 "#]]};
PrimitiveDateTime, "TimestampSeconds<f64>" , one_second, {expect![[r#" 1 .0 "#]]};
PrimitiveDateTime, "TimestampMilliSeconds<i64>" , one_second, {expect![[r#" 1000 "#]]};
PrimitiveDateTime, "TimestampMilliSeconds<f64>" , one_second, {expect![[r#" 1000 .0 "#]]};
PrimitiveDateTime, "TimestampMicroSeconds<i64>" , one_second, {expect![[r#" 1000000 "#]]};
PrimitiveDateTime, "TimestampMicroSeconds<f64>" , one_second, {expect![[r#" 1000000 .0 "#]]};
PrimitiveDateTime, "TimestampNanoSeconds<i64>" , one_second, {expect![[r#" 1000000000 "#]]};
PrimitiveDateTime, "TimestampNanoSeconds<f64>" , one_second, {expect![[r#" 1000000000 .0 "#]]};
};
smoketest! {
PrimitiveDateTime, "TimestampSecondsWithFrac" , one_second, {expect![[r#" 1 .0 "#]]};
PrimitiveDateTime, "TimestampSecondsWithFrac<String>" , one_second, {expect![[r#" "1" "#]]};
PrimitiveDateTime, "TimestampMilliSecondsWithFrac" , one_second, {expect![[r#" 1000 .0 "#]]};
PrimitiveDateTime, "TimestampMilliSecondsWithFrac<String>" , one_second, {expect![[r#" "1000" "#]]};
PrimitiveDateTime, "TimestampMicroSecondsWithFrac" , one_second, {expect![[r#" 1000000 .0 "#]]};
PrimitiveDateTime, "TimestampMicroSecondsWithFrac<String>" , one_second, {expect![[r#" "1000000" "#]]};
PrimitiveDateTime, "TimestampNanoSecondsWithFrac" , one_second, {expect![[r#" 1000000000 .0 "#]]};
PrimitiveDateTime, "TimestampNanoSecondsWithFrac<String>" , one_second, {expect![[r#" "1000000000" "#]]};
};
smoketest! {
PrimitiveDateTime, "TimestampSecondsWithFrac" , zero, {expect![[r#" 0 .0 "#]]};
PrimitiveDateTime, "TimestampSecondsWithFrac" , zero + Duration::nanoseconds(500 _000 _000 ), {expect![[r#" 0 .5 "#]]};
PrimitiveDateTime, "TimestampSecondsWithFrac" , zero + Duration::seconds(1 ), {expect![[r#" 1 .0 "#]]};
PrimitiveDateTime, "TimestampSecondsWithFrac" , zero - Duration::nanoseconds(500 _000 _000 ), {expect![[r#" -0 .5 "#]]};
PrimitiveDateTime, "TimestampSecondsWithFrac" , zero - Duration::seconds(1 ), {expect![[r#" -1 .0 "#]]};
};
}
#[ test]
fn test_offset_datetime_rfc2822() {
#[ serde_as]
#[ derive(Debug, PartialEq, Deserialize, Serialize)]
struct S(#[ serde_as(as = "time_0_3::format_description::well_known::Rfc2822" )] OffsetDateTime);
is_equal(
S(OffsetDateTime::UNIX_EPOCH),
expect![[r#" "Thu, 01 Jan 1970 00:00:00 +0000" "#]],
);
check_error_deserialization::<S>(
r#" "Foobar" "#,
expect![[r#" the 'weekday' component could not be parsed at line 1 column 8 "#]],
);
check_error_deserialization::<S>(
r#" "Fri, 2000" "#,
expect![[r#" a character literal was not valid at line 1 column 11 "#]],
);
}
#[ test]
fn test_offset_datetime_rfc3339() {
#[ serde_as]
#[ derive(Debug, PartialEq, Deserialize, Serialize)]
struct S(#[ serde_as(as = "time_0_3::format_description::well_known::Rfc3339" )] OffsetDateTime);
is_equal(
S(OffsetDateTime::UNIX_EPOCH),
expect![[r#" "1970-01-01T00:00:00Z" "#]],
);
check_deserialization::<S>(
S(
OffsetDateTime::from_unix_timestamp_nanos(482 _196 _050 _520 _000 _000 )
.unwrap()
.to_offset(UtcOffset::from_hms(0 , 0 , 0 ).unwrap()),
),
r#" "1985-04-12T23:20:50.52Z" "#,
);
check_deserialization::<S>(
S(OffsetDateTime::from_unix_timestamp(851 _042 _397 )
.unwrap()
.to_offset(UtcOffset::from_hms(-8 , 0 , 0 ).unwrap())),
r#" "1996-12-19T16:39:57-08:00" "#,
);
check_deserialization::<S>(
S(
OffsetDateTime::from_unix_timestamp_nanos(662 _687 _999 _999 _999 _999 )
.unwrap()
.to_offset(UtcOffset::from_hms(0 , 0 , 0 ).unwrap()),
),
r#" "1990-12-31T23:59:60Z" "#,
);
check_deserialization::<S>(
S(
OffsetDateTime::from_unix_timestamp_nanos(662 _687 _999 _999 _999 _999 )
.unwrap()
.to_offset(UtcOffset::from_hms(-8 , 0 , 0 ).unwrap()),
),
r#" "1990-12-31T15:59:60-08:00" "#,
);
check_deserialization::<S>(
S(
OffsetDateTime::from_unix_timestamp_nanos(-1 _041 _337 _172 _130 _000 _000 )
.unwrap()
.to_offset(UtcOffset::from_hms(0 , 20 , 0 ).unwrap()),
),
r#" "1937-01-01T12:00:27.87+00:20" "#,
);
check_error_deserialization::<S>(
r#" "Foobar" "#,
expect![[r#" the 'year' component could not be parsed at line 1 column 8 "#]],
);
check_error_deserialization::<S>(
r#" "2000-AA" "#,
expect![[r#" the 'month' component could not be parsed at line 1 column 9 "#]],
);
}
#[ test]
fn test_offset_datetime_iso8601() {
/// The default configuration for [`Iso8601`].
const DEFAULT_CONFIG: time_0_3::format_description::well_known::iso8601::EncodedConfig =
time_0_3::format_description::well_known::iso8601::Config::DEFAULT.encode();
#[ serde_as]
#[ derive(Debug, PartialEq, Deserialize, Serialize)]
struct S(
#[ serde_as(as = "time_0_3::format_description::well_known::Iso8601<DEFAULT_CONFIG>" )]
OffsetDateTime,
);
is_equal(
S(OffsetDateTime::UNIX_EPOCH),
expect![[r#" "1970-01-01T00:00:00.000000000Z" "#]],
);
check_deserialization::<S>(
S(
OffsetDateTime::from_unix_timestamp_nanos(482 _196 _050 _520 _000 _000 )
.unwrap()
.to_offset(UtcOffset::from_hms(0 , 0 , 0 ).unwrap()),
),
r#" "1985-04-12T23:20:50.52Z" "#,
);
check_deserialization::<S>(
S(OffsetDateTime::from_unix_timestamp(851 _042 _397 )
.unwrap()
.to_offset(UtcOffset::from_hms(-8 , 0 , 0 ).unwrap())),
r#" "1996-12-19T16:39:57-08:00" "#,
);
check_deserialization::<S>(
S(
OffsetDateTime::from_unix_timestamp_nanos(-1 _041 _337 _172 _130 _000 _000 )
.unwrap()
.to_offset(UtcOffset::from_hms(0 , 20 , 0 ).unwrap()),
),
r#" "1937-01-01T12:00:27.87+00:20" "#,
);
check_error_deserialization::<S>(
r#" "Foobar" "#,
expect![[r#" the 'year' component could not be parsed at line 1 column 8 "#]],
);
check_error_deserialization::<S>(
r#" "2000-AA" "#,
expect!["unexpected trailing characters at line 1 column 9" ],
);
}
Messung V0.5 in Prozent C=99 H=100 G=99
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-17)
¤
*© Formatika GbR, Deutschland