@@ -22,11 +22,11 @@ use crate::{
22
22
validation:: ExactlyOne ,
23
23
} ;
24
24
use async_trait:: async_trait;
25
+ use chrono:: { LocalResult , TimeZone , Utc } ;
25
26
use std:: {
26
27
ops:: { ControlFlow , Deref , Range } ,
27
28
sync:: Arc ,
28
29
} ;
29
- use time:: OffsetDateTime ;
30
30
use tokio:: sync:: Mutex ;
31
31
use tracing:: { error, info} ;
32
32
@@ -540,7 +540,7 @@ fn build_produce_request(
540
540
ProtocolRecord {
541
541
key : record. key ,
542
542
value : record. value ,
543
- timestamp_delta : ( record. timestamp - first_timestamp) . whole_milliseconds ( ) as i64 ,
543
+ timestamp_delta : ( record. timestamp - first_timestamp) . num_milliseconds ( ) as i64 ,
544
544
offset_delta : offset_delta as i32 ,
545
545
headers : record
546
546
. headers
@@ -573,8 +573,8 @@ fn build_produce_request(
573
573
timestamp_type: RecordBatchTimestampType :: CreateTime ,
574
574
producer_id: -1 ,
575
575
producer_epoch: -1 ,
576
- first_timestamp: ( first_timestamp. unix_timestamp_nanos ( ) / 1_000_000 ) as i64 ,
577
- max_timestamp: ( max_timestamp. unix_timestamp_nanos ( ) / 1_000_000 ) as i64 ,
576
+ first_timestamp: first_timestamp. timestamp_millis ( ) ,
577
+ max_timestamp: max_timestamp. timestamp_millis ( ) ,
578
578
records: ControlBatchOrRecords :: Records ( records) ,
579
579
} ] ) ,
580
580
} ;
@@ -730,12 +730,29 @@ fn extract_records(
730
730
continue ;
731
731
}
732
732
733
- let timestamp = OffsetDateTime :: from_unix_timestamp_nanos (
734
- ( batch. first_timestamp + record. timestamp_delta ) as i128 * 1_000_000 ,
735
- )
736
- . map_err ( |e| {
737
- Error :: InvalidResponse ( format ! ( "Cannot parse timestamp: {}" , e) )
738
- } ) ?;
733
+ let timestamp_millis =
734
+ match batch. first_timestamp . checked_add ( record. timestamp_delta ) {
735
+ Some ( ts) => ts,
736
+ None => {
737
+ return Err ( Error :: InvalidResponse ( format ! (
738
+ "Timestamp overflow (first_timestamp={}, delta={}" ,
739
+ batch. first_timestamp, record. timestamp_delta
740
+ ) ) ) ;
741
+ }
742
+ } ;
743
+ let timestamp = match Utc . timestamp_millis_opt ( timestamp_millis) {
744
+ LocalResult :: None => {
745
+ return Err ( Error :: InvalidResponse ( format ! (
746
+ "Not a valid timestamp ({timestamp_millis})"
747
+ ) ) ) ;
748
+ }
749
+ LocalResult :: Single ( ts) => ts,
750
+ LocalResult :: Ambiguous ( a, b) => {
751
+ return Err ( Error :: InvalidResponse ( format ! (
752
+ "Ambiguous timestamp ({timestamp_millis}): {a} or {b}"
753
+ ) ) ) ;
754
+ }
755
+ } ;
739
756
740
757
records. push ( RecordAndOffset {
741
758
record : Record {
0 commit comments