1use std::convert::TryFrom;
11use std::num::TryFromIntError;
12use std::time::Duration;
13
14use dec::TryFromDecimalError;
15use mz_proto::{RustType, TryFromProtoError};
16use mz_timely_util::temporal::BucketTimestamp;
17#[cfg(any(test, feature = "proptest"))]
18use proptest_derive::Arbitrary;
19use serde::{Deserialize, Serialize, Serializer};
20
21use chrono::{DateTime, Utc};
22
23use crate::adt::numeric::Numeric;
24use crate::adt::timestamp::CheckedTimestamp;
25use crate::refresh_schedule::RefreshSchedule;
26use crate::strconv::{ParseError, parse_timestamptz, parse_timestamptz_legacy};
27
28include!(concat!(env!("OUT_DIR"), "/mz_repr.timestamp.rs"));
29
30#[derive(
32 Clone,
33 Copy,
35 PartialEq,
36 Eq,
37 PartialOrd,
38 Ord,
39 Hash,
40 Default,
41 bytemuck::AnyBitPattern,
42 bytemuck::NoUninit,
43)]
44#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
45#[repr(transparent)]
46pub struct Timestamp {
47 internal: u64,
49}
50
51impl PartialEq<&Timestamp> for Timestamp {
52 fn eq(&self, other: &&Timestamp) -> bool {
53 self.eq(*other)
54 }
55}
56
57impl PartialEq<Timestamp> for &Timestamp {
58 fn eq(&self, other: &Timestamp) -> bool {
59 self.internal.eq(&other.internal)
60 }
61}
62
63impl RustType<ProtoTimestamp> for Timestamp {
64 fn into_proto(&self) -> ProtoTimestamp {
65 ProtoTimestamp {
66 internal: self.into(),
67 }
68 }
69
70 fn from_proto(proto: ProtoTimestamp) -> Result<Self, TryFromProtoError> {
71 Ok(Timestamp::new(proto.internal))
72 }
73}
74
75mod columnar_timestamp {
76 use crate::Timestamp;
77 use columnar::Columnar;
78 use mz_ore::cast::CastFrom;
79 use std::ops::Range;
80
81 #[derive(Clone, Copy, Default, Debug)]
83 pub struct Timestamps<T>(T);
84 impl<D, T: columnar::Push<D>> columnar::Push<D> for Timestamps<T> {
85 #[inline(always)]
86 fn push(&mut self, item: D) {
87 self.0.push(item)
88 }
89 }
90 impl<T: columnar::Clear> columnar::Clear for Timestamps<T> {
91 #[inline(always)]
92 fn clear(&mut self) {
93 self.0.clear()
94 }
95 }
96 impl<T: columnar::Len> columnar::Len for Timestamps<T> {
97 #[inline(always)]
98 fn len(&self) -> usize {
99 self.0.len()
100 }
101 }
102 impl<'a> columnar::Index for Timestamps<&'a [Timestamp]> {
103 type Ref = Timestamp;
104
105 #[inline(always)]
106 fn get(&self, index: usize) -> Self::Ref {
107 self.0[index]
108 }
109 }
110
111 impl Columnar for Timestamp {
112 #[inline(always)]
113 fn into_owned<'a>(other: columnar::Ref<'a, Self>) -> Self {
114 other
115 }
116 type Container = Timestamps<Vec<Timestamp>>;
117 #[inline(always)]
118 fn reborrow<'b, 'a: 'b>(thing: columnar::Ref<'a, Self>) -> columnar::Ref<'b, Self>
119 where
120 Self: 'a,
121 {
122 thing
123 }
124 }
125
126 impl columnar::Borrow for Timestamps<Vec<Timestamp>> {
127 type Ref<'a> = Timestamp;
128 type Borrowed<'a>
129 = Timestamps<&'a [Timestamp]>
130 where
131 Self: 'a;
132 #[inline(always)]
133 fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
134 Timestamps(self.0.as_slice())
135 }
136 #[inline(always)]
137 fn reborrow<'b, 'a: 'b>(item: Self::Borrowed<'a>) -> Self::Borrowed<'b>
138 where
139 Self: 'a,
140 {
141 Timestamps(item.0)
142 }
143
144 #[inline(always)]
145 fn reborrow_ref<'b, 'a: 'b>(item: Self::Ref<'a>) -> Self::Ref<'b>
146 where
147 Self: 'a,
148 {
149 item
150 }
151 }
152
153 impl columnar::Container for Timestamps<Vec<Timestamp>> {
154 #[inline(always)]
155 fn extend_from_self(&mut self, other: Self::Borrowed<'_>, range: Range<usize>) {
156 self.0.extend_from_self(other.0, range)
157 }
158 #[inline(always)]
159 fn reserve_for<'a, I>(&mut self, selves: I)
160 where
161 Self: 'a,
162 I: Iterator<Item = Self::Borrowed<'a>> + Clone,
163 {
164 self.0.reserve_for(selves.map(|s| s.0));
165 }
166 }
167
168 impl<'a> columnar::AsBytes<'a> for Timestamps<&'a [Timestamp]> {
169 const SLICE_COUNT: usize = 1;
170 #[inline(always)]
171 fn get_byte_slice(&self, index: usize) -> (u64, &'a [u8]) {
172 debug_assert!(index < Self::SLICE_COUNT);
173 (
174 u64::cast_from(align_of::<Timestamp>()),
175 bytemuck::cast_slice(self.0),
176 )
177 }
178 #[inline(always)]
179 fn as_bytes(&self) -> impl Iterator<Item = (u64, &'a [u8])> {
180 std::iter::once((
181 u64::cast_from(align_of::<Timestamp>()),
182 bytemuck::cast_slice(self.0),
183 ))
184 }
185 }
186 impl<'a> columnar::FromBytes<'a> for Timestamps<&'a [Timestamp]> {
187 const SLICE_COUNT: usize = 1;
188 #[inline(always)]
189 fn from_bytes(bytes: &mut impl Iterator<Item = &'a [u8]>) -> Self {
190 Timestamps(bytemuck::cast_slice(
191 bytes.next().expect("Iterator exhausted prematurely"),
192 ))
193 }
194 }
195}
196
197impl BucketTimestamp for Timestamp {
198 fn advance_by_power_of_two(&self, exponent: u32) -> Option<Self> {
199 let rhs = 1_u64.checked_shl(exponent)?;
200 Some(self.internal.checked_add(rhs)?.into())
201 }
202}
203
204pub trait TimestampManipulation:
205 timely::progress::Timestamp
206 + timely::order::TotalOrder
207 + differential_dataflow::lattice::Lattice
208 + std::fmt::Debug
209 + mz_persist_types::StepForward
210 + Sync
211{
212 fn step_forward(&self) -> Self;
215
216 fn step_forward_by(&self, amount: &Self) -> Self;
218
219 fn try_step_forward_by(&self, amount: &Self) -> Option<Self>;
221
222 fn try_step_forward(&self) -> Option<Self>;
225
226 fn step_back(&self) -> Option<Self>;
230
231 fn maximum() -> Self;
233
234 fn round_up(&self, schedule: &RefreshSchedule) -> Option<Self>;
237
238 fn round_down_minus_1(&self, schedule: &RefreshSchedule) -> Option<Self>;
242}
243
244impl TimestampManipulation for Timestamp {
245 fn step_forward(&self) -> Self {
246 self.step_forward()
247 }
248
249 fn step_forward_by(&self, amount: &Self) -> Self {
250 self.step_forward_by(amount)
251 }
252
253 fn try_step_forward(&self) -> Option<Self> {
254 self.try_step_forward()
255 }
256
257 fn try_step_forward_by(&self, amount: &Self) -> Option<Self> {
258 self.try_step_forward_by(amount)
259 }
260
261 fn step_back(&self) -> Option<Self> {
262 self.step_back()
263 }
264
265 fn maximum() -> Self {
266 Self::MAX
267 }
268
269 fn round_up(&self, schedule: &RefreshSchedule) -> Option<Self> {
270 schedule.round_up_timestamp(*self)
271 }
272
273 fn round_down_minus_1(&self, schedule: &RefreshSchedule) -> Option<Self> {
274 schedule.round_down_timestamp_m1(*self)
275 }
276}
277
278impl mz_persist_types::StepForward for Timestamp {
279 fn step_forward(&self) -> Self {
280 self.step_forward()
281 }
282}
283
284impl Timestamp {
285 pub const MAX: Self = Self { internal: u64::MAX };
286 pub const MIN: Self = Self { internal: u64::MIN };
287
288 pub const fn new(timestamp: u64) -> Self {
289 Self {
290 internal: timestamp,
291 }
292 }
293
294 pub fn to_bytes(&self) -> [u8; 8] {
295 self.internal.to_le_bytes()
296 }
297
298 pub fn from_bytes(bytes: [u8; 8]) -> Self {
299 Self {
300 internal: u64::from_le_bytes(bytes),
301 }
302 }
303
304 pub fn saturating_sub<I: Into<Self>>(self, rhs: I) -> Self {
305 Self {
306 internal: self.internal.saturating_sub(rhs.into().internal),
307 }
308 }
309
310 pub fn saturating_add<I: Into<Self>>(self, rhs: I) -> Self {
311 Self {
312 internal: self.internal.saturating_add(rhs.into().internal),
313 }
314 }
315
316 pub fn saturating_mul<I: Into<Self>>(self, rhs: I) -> Self {
317 Self {
318 internal: self.internal.saturating_mul(rhs.into().internal),
319 }
320 }
321
322 pub fn checked_add<I: Into<Self>>(self, rhs: I) -> Option<Self> {
323 self.internal
324 .checked_add(rhs.into().internal)
325 .map(|internal| Self { internal })
326 }
327
328 pub fn checked_sub<I: Into<Self>>(self, rhs: I) -> Option<Self> {
329 self.internal
330 .checked_sub(rhs.into().internal)
331 .map(|internal| Self { internal })
332 }
333
334 pub fn step_forward(&self) -> Self {
337 match self.checked_add(1) {
338 Some(ts) => ts,
339 None => panic!("could not step forward"),
340 }
341 }
342
343 pub fn step_forward_by(&self, amount: &Self) -> Self {
345 match self.checked_add(*amount) {
346 Some(ts) => ts,
347 None => panic!("could not step {self} forward by {amount}"),
348 }
349 }
350
351 pub fn try_step_forward(&self) -> Option<Self> {
354 self.checked_add(1)
355 }
356
357 pub fn try_step_forward_by(&self, amount: &Self) -> Option<Self> {
359 self.checked_add(*amount)
360 }
361
362 pub fn step_back(&self) -> Option<Self> {
366 self.checked_sub(1)
367 }
368}
369
370impl From<u64> for Timestamp {
371 fn from(internal: u64) -> Self {
372 Self { internal }
373 }
374}
375
376impl From<Timestamp> for u64 {
377 fn from(ts: Timestamp) -> Self {
378 ts.internal
379 }
380}
381
382impl From<Timestamp> for u128 {
383 fn from(ts: Timestamp) -> Self {
384 u128::from(ts.internal)
385 }
386}
387
388impl TryFrom<Timestamp> for i64 {
389 type Error = TryFromIntError;
390
391 fn try_from(value: Timestamp) -> Result<Self, Self::Error> {
392 value.internal.try_into()
393 }
394}
395
396impl From<&Timestamp> for u64 {
397 fn from(ts: &Timestamp) -> Self {
398 ts.internal
399 }
400}
401
402impl From<Timestamp> for Numeric {
403 fn from(ts: Timestamp) -> Self {
404 ts.internal.into()
405 }
406}
407
408impl From<Timestamp> for Duration {
409 fn from(ts: Timestamp) -> Self {
410 Duration::from_millis(ts.internal)
411 }
412}
413
414impl std::ops::Rem<Timestamp> for Timestamp {
415 type Output = Timestamp;
416
417 fn rem(self, rhs: Timestamp) -> Self::Output {
418 Self {
419 internal: self.internal % rhs.internal,
420 }
421 }
422}
423
424impl Serialize for Timestamp {
425 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
426 where
427 S: Serializer,
428 {
429 self.internal.serialize(serializer)
430 }
431}
432
433impl<'de> Deserialize<'de> for Timestamp {
434 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
435 where
436 D: serde::Deserializer<'de>,
437 {
438 Ok(Self {
439 internal: u64::deserialize(deserializer)?,
440 })
441 }
442}
443
444impl timely::order::PartialOrder for Timestamp {
445 fn less_equal(&self, other: &Self) -> bool {
446 self.internal.less_equal(&other.internal)
447 }
448}
449
450impl timely::order::PartialOrder<&Timestamp> for Timestamp {
451 fn less_equal(&self, other: &&Self) -> bool {
452 self.internal.less_equal(&other.internal)
453 }
454}
455
456impl timely::order::PartialOrder<Timestamp> for &Timestamp {
457 fn less_equal(&self, other: &Timestamp) -> bool {
458 self.internal.less_equal(&other.internal)
459 }
460}
461
462impl timely::order::TotalOrder for Timestamp {}
463
464impl timely::progress::Timestamp for Timestamp {
465 type Summary = Timestamp;
466
467 fn minimum() -> Self {
468 Self::MIN
469 }
470}
471
472impl timely::progress::PathSummary<Timestamp> for Timestamp {
473 #[inline]
474 fn results_in(&self, src: &Timestamp) -> Option<Timestamp> {
475 self.internal
476 .checked_add(src.internal)
477 .map(|internal| Self { internal })
478 }
479 #[inline]
480 fn followed_by(&self, other: &Timestamp) -> Option<Timestamp> {
481 self.internal
482 .checked_add(other.internal)
483 .map(|internal| Self { internal })
484 }
485}
486
487impl timely::progress::timestamp::Refines<()> for Timestamp {
488 fn to_inner(_: ()) -> Timestamp {
489 Default::default()
490 }
491 fn to_outer(self) -> () {
492 ()
493 }
494 fn summarize(_: <Timestamp as timely::progress::timestamp::Timestamp>::Summary) -> () {
495 ()
496 }
497}
498
499impl differential_dataflow::lattice::Lattice for Timestamp {
500 #[inline]
501 fn join(&self, other: &Self) -> Self {
502 ::std::cmp::max(*self, *other)
503 }
504 #[inline]
505 fn meet(&self, other: &Self) -> Self {
506 ::std::cmp::min(*self, *other)
507 }
508}
509
510impl mz_persist_types::Codec64 for Timestamp {
511 fn codec_name() -> String {
512 u64::codec_name()
513 }
514
515 fn encode(&self) -> [u8; 8] {
516 self.internal.encode()
517 }
518
519 fn decode(buf: [u8; 8]) -> Self {
520 Self {
521 internal: u64::decode(buf),
522 }
523 }
524}
525
526impl std::fmt::Display for Timestamp {
527 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
528 std::fmt::Display::fmt(&self.internal, f)
529 }
530}
531
532impl std::fmt::Debug for Timestamp {
533 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
534 std::fmt::Debug::fmt(&self.internal, f)
535 }
536}
537
538impl std::str::FromStr for Timestamp {
539 type Err = String;
540
541 fn from_str(s: &str) -> Result<Self, Self::Err> {
542 Self::parse_with(s, parse_timestamptz)
543 }
544}
545
546impl Timestamp {
547 pub fn from_str_legacy(s: &str) -> Result<Self, String> {
552 Self::parse_with(s, parse_timestamptz_legacy)
553 }
554
555 fn parse_with(
556 s: &str,
557 parse_fallback: fn(&str) -> Result<CheckedTimestamp<DateTime<Utc>>, ParseError>,
558 ) -> Result<Self, String> {
559 Ok(Self {
560 internal: s
561 .parse::<u64>()
562 .map_err(|_| "could not parse as number of milliseconds since epoch".to_string())
563 .or_else(|err_num_of_millis| {
564 parse_fallback(s)
565 .map_err(|parse_error| {
566 format!(
567 "{}; could not parse as date and time: {}",
568 err_num_of_millis, parse_error
569 )
570 })?
571 .timestamp_millis()
572 .try_into()
573 .map_err(|_| "out of range for mz_timestamp".to_string())
574 })
575 .map_err(|e: String| format!("could not parse mz_timestamp: {}", e))?,
576 })
577 }
578}
579
580impl TryFrom<Duration> for Timestamp {
581 type Error = TryFromIntError;
582
583 fn try_from(value: Duration) -> Result<Self, Self::Error> {
584 Ok(Self {
585 internal: value.as_millis().try_into()?,
586 })
587 }
588}
589
590impl TryFrom<u128> for Timestamp {
591 type Error = TryFromIntError;
592
593 fn try_from(value: u128) -> Result<Self, Self::Error> {
594 Ok(Self {
595 internal: value.try_into()?,
596 })
597 }
598}
599
600impl TryFrom<i64> for Timestamp {
601 type Error = TryFromIntError;
602
603 fn try_from(value: i64) -> Result<Self, Self::Error> {
604 Ok(Self {
605 internal: value.try_into()?,
606 })
607 }
608}
609
610impl TryFrom<Numeric> for Timestamp {
611 type Error = TryFromDecimalError;
612
613 fn try_from(value: Numeric) -> Result<Self, Self::Error> {
614 Ok(Self {
615 internal: value.try_into()?,
616 })
617 }
618}
619
620impl columnation::Columnation for Timestamp {
621 type InnerRegion = columnation::CopyRegion<Timestamp>;
622}