33#[ cfg( test) ]
44mod tests;
55
6- use std:: time:: { Duration , SystemTime } ;
7-
86use anyhow:: Context ;
7+ use chrono:: { DateTime , Utc } ;
98
109use crate :: { providers:: CatalystSignedDocumentProvider , CatalystSignedDocument } ;
1110
@@ -16,11 +15,10 @@ pub(crate) struct IdRule;
1615impl IdRule {
1716 /// Validates document `id` field on the timestamps:
1817 /// 1. If `provider.future_threshold()` not `None`, document `id` cannot be too far in
19- /// the future (`future_threshold` arg) from `SystemTime::now()` based on the
20- /// provide threshold
21- /// 2. If `provider.future_threshold()` not `None`, document `id` cannot be too far
22- /// behind (`past_threshold` arg) from `SystemTime::now()` based on the provide
18+ /// the future (`future_threshold` arg) from `Utc::now()` based on the provided
2319 /// threshold
20+ /// 2. If `provider.past_threshold()` not `None`, document `id` cannot be too far
21+ /// behind (`past_threshold` arg) from `Utc::now()` based on the provided threshold
2422 #[ allow( clippy:: unused_async) ]
2523 pub ( crate ) async fn check < Provider > (
2624 & self ,
@@ -46,37 +44,40 @@ impl IdRule {
4644 . ok_or ( anyhow:: anyhow!( "Document `id` field must be a UUIDv7" ) ) ?
4745 . to_unix ( ) ;
4846
49- let Some ( id_time) =
50- SystemTime :: UNIX_EPOCH . checked_add ( Duration :: new ( id_time_secs, id_time_nanos) )
47+ let Some ( id_time) = i64:: try_from ( id_time_secs)
48+ . ok ( )
49+ . and_then ( |id_time_secs| DateTime :: from_timestamp ( id_time_secs, id_time_nanos) )
5150 else {
5251 doc. report ( ) . invalid_value (
5352 "id" ,
5453 & id. to_string ( ) ,
55- "Must a valid duration since `UNIX_EPOCH`" ,
56- "Cannot instantiate a valid `SystemTime ` value from the provided `id` field timestamp." ,
54+ "Must a valid UTC date time since `UNIX_EPOCH`" ,
55+ "Cannot instantiate a valid `DateTime<Utc> ` value from the provided `id` field timestamp." ,
5756 ) ;
5857 return Ok ( false ) ;
5958 } ;
6059
61- let now = SystemTime :: now ( ) ;
60+ let now = Utc :: now ( ) ;
61+ let time_delta = id_time. signed_duration_since ( now) ;
6262
63- if let Ok ( id_age) = id_time . duration_since ( now ) {
63+ if let Ok ( id_age) = time_delta . to_std ( ) {
6464 // `now` is earlier than `id_time`
6565 if let Some ( future_threshold) = provider. future_threshold ( ) {
6666 if id_age > future_threshold {
6767 doc. report ( ) . invalid_value (
6868 "id" ,
6969 & id. to_string ( ) ,
7070 "id < now + future_threshold" ,
71- & format ! ( "Document Version timestamp {id} cannot be too far in future (threshold: {future_threshold:?}) from now: {now:? }" ) ,
71+ & format ! ( "Document ID timestamp {id} cannot be too far in future (threshold: {future_threshold:?}) from now: {now}" ) ,
7272 ) ;
7373 is_valid = false ;
7474 }
7575 }
7676 } else {
7777 // `id_time` is earlier than `now`
78- let id_age = now
79- . duration_since ( id_time)
78+ let id_age = time_delta
79+ . abs ( )
80+ . to_std ( )
8081 . context ( "BUG! `id_time` must be earlier than `now` at this place" ) ?;
8182
8283 if let Some ( past_threshold) = provider. past_threshold ( ) {
@@ -85,7 +86,7 @@ impl IdRule {
8586 "id" ,
8687 & id. to_string ( ) ,
8788 "id > now - past_threshold" ,
88- & format ! ( "Document Version timestamp {id} cannot be too far behind (threshold: {past_threshold:?}) from now: {now:?}" , ) ,
89+ & format ! ( "Document ID timestamp {id} cannot be too far behind (threshold: {past_threshold:?}) from now: {now:?}" , ) ,
8990 ) ;
9091 is_valid = false ;
9192 }
0 commit comments