mirror of
https://github.com/quickwit-oss/tantivy.git
synced 2025-12-22 18:19:58 +00:00
182 lines
6.2 KiB
Rust
182 lines
6.2 KiB
Rust
#![allow(deprecated)]
|
|
|
|
use std::fmt;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use time::format_description::well_known::Rfc3339;
|
|
use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset};
|
|
|
|
/// Precision with which datetimes are truncated when stored in fast fields. This setting is only
|
|
/// relevant for fast fields. In the docstore, datetimes are always saved with nanosecond precision.
|
|
#[derive(
|
|
Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default,
|
|
)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum DateTimePrecision {
|
|
/// Second precision.
|
|
#[default]
|
|
Second,
|
|
/// Millisecond precision.
|
|
Millisecond,
|
|
/// Microsecond precision.
|
|
Microsecond,
|
|
/// Nanosecond precision.
|
|
Nanosecond,
|
|
// TODO: Remove deprecated variants after 2 releases.
|
|
#[deprecated(since = "0.20.0", note = "Use `Second` instead")]
|
|
Seconds,
|
|
#[deprecated(since = "0.20.0", note = "Use `Millisecond` instead")]
|
|
Milliseconds,
|
|
#[deprecated(since = "0.20.0", note = "Use `Microsecond` instead")]
|
|
Microseconds,
|
|
#[deprecated(since = "0.20.0", note = "Use `Nanosecond` instead")]
|
|
Nanoseconds,
|
|
}
|
|
|
|
#[deprecated(since = "0.20.0", note = "Use `DateTimePrecision` instead")]
|
|
pub type DatePrecision = DateTimePrecision;
|
|
|
|
/// A date/time value with nanoseconds precision.
|
|
///
|
|
/// This timestamp does not carry any explicit time zone information.
|
|
/// Users are responsible for applying the provided conversion
|
|
/// functions consistently. Internally the time zone is assumed
|
|
/// to be UTC, which is also used implicitly for JSON serialization.
|
|
///
|
|
/// All constructors and conversions are provided as explicit
|
|
/// functions and not by implementing any `From`/`Into` traits
|
|
/// to prevent unintended usage.
|
|
#[derive(Clone, Default, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub struct DateTime {
|
|
// Timestamp in nanoseconds.
|
|
pub(crate) timestamp_nanos: i64,
|
|
}
|
|
|
|
impl DateTime {
|
|
/// Minimum possible `DateTime` value.
|
|
pub const MIN: DateTime = DateTime {
|
|
timestamp_nanos: i64::MIN,
|
|
};
|
|
|
|
/// Maximum possible `DateTime` value.
|
|
pub const MAX: DateTime = DateTime {
|
|
timestamp_nanos: i64::MAX,
|
|
};
|
|
|
|
/// Create new from UNIX timestamp in seconds
|
|
pub const fn from_timestamp_secs(seconds: i64) -> Self {
|
|
Self {
|
|
timestamp_nanos: seconds * 1_000_000_000,
|
|
}
|
|
}
|
|
|
|
/// Create new from UNIX timestamp in milliseconds
|
|
pub const fn from_timestamp_millis(milliseconds: i64) -> Self {
|
|
Self {
|
|
timestamp_nanos: milliseconds * 1_000_000,
|
|
}
|
|
}
|
|
|
|
/// Create new from UNIX timestamp in microseconds.
|
|
pub const fn from_timestamp_micros(microseconds: i64) -> Self {
|
|
Self {
|
|
timestamp_nanos: microseconds * 1_000,
|
|
}
|
|
}
|
|
|
|
/// Create new from UNIX timestamp in nanoseconds.
|
|
pub const fn from_timestamp_nanos(nanoseconds: i64) -> Self {
|
|
Self {
|
|
timestamp_nanos: nanoseconds,
|
|
}
|
|
}
|
|
|
|
/// Create new from `OffsetDateTime`
|
|
///
|
|
/// The given date/time is converted to UTC and the actual
|
|
/// time zone is discarded.
|
|
pub fn from_utc(dt: OffsetDateTime) -> Self {
|
|
let timestamp_nanos = dt.unix_timestamp_nanos() as i64;
|
|
Self { timestamp_nanos }
|
|
}
|
|
|
|
/// Create new from `PrimitiveDateTime`
|
|
///
|
|
/// Implicitly assumes that the given date/time is in UTC!
|
|
/// Otherwise the original value must only be reobtained with
|
|
/// [`Self::into_primitive()`].
|
|
pub fn from_primitive(dt: PrimitiveDateTime) -> Self {
|
|
Self::from_utc(dt.assume_utc())
|
|
}
|
|
|
|
/// Convert to UNIX timestamp in seconds.
|
|
pub const fn into_timestamp_secs(self) -> i64 {
|
|
self.timestamp_nanos / 1_000_000_000
|
|
}
|
|
|
|
/// Convert to UNIX timestamp in milliseconds.
|
|
pub const fn into_timestamp_millis(self) -> i64 {
|
|
self.timestamp_nanos / 1_000_000
|
|
}
|
|
|
|
/// Convert to UNIX timestamp in microseconds.
|
|
pub const fn into_timestamp_micros(self) -> i64 {
|
|
self.timestamp_nanos / 1_000
|
|
}
|
|
|
|
/// Convert to UNIX timestamp in nanoseconds.
|
|
pub const fn into_timestamp_nanos(self) -> i64 {
|
|
self.timestamp_nanos
|
|
}
|
|
|
|
/// Convert to UTC `OffsetDateTime`
|
|
pub fn into_utc(self) -> OffsetDateTime {
|
|
let utc_datetime = OffsetDateTime::from_unix_timestamp_nanos(self.timestamp_nanos as i128)
|
|
.expect("valid UNIX timestamp");
|
|
debug_assert_eq!(UtcOffset::UTC, utc_datetime.offset());
|
|
utc_datetime
|
|
}
|
|
|
|
/// Convert to `OffsetDateTime` with the given time zone
|
|
pub fn into_offset(self, offset: UtcOffset) -> OffsetDateTime {
|
|
self.into_utc().to_offset(offset)
|
|
}
|
|
|
|
/// Convert to `PrimitiveDateTime` without any time zone
|
|
///
|
|
/// The value should have been constructed with [`Self::from_primitive()`].
|
|
/// Otherwise the time zone is implicitly assumed to be UTC.
|
|
pub fn into_primitive(self) -> PrimitiveDateTime {
|
|
let utc_datetime = self.into_utc();
|
|
// Discard the UTC time zone offset
|
|
debug_assert_eq!(UtcOffset::UTC, utc_datetime.offset());
|
|
PrimitiveDateTime::new(utc_datetime.date(), utc_datetime.time())
|
|
}
|
|
|
|
/// Truncates the microseconds value to the corresponding precision.
|
|
pub fn truncate(self, precision: DateTimePrecision) -> Self {
|
|
let truncated_timestamp_micros = match precision {
|
|
DateTimePrecision::Second | DateTimePrecision::Seconds => {
|
|
(self.timestamp_nanos / 1_000_000_000) * 1_000_000_000
|
|
}
|
|
DateTimePrecision::Millisecond | DateTimePrecision::Milliseconds => {
|
|
(self.timestamp_nanos / 1_000_000) * 1_000_000
|
|
}
|
|
DateTimePrecision::Microsecond | DateTimePrecision::Microseconds => {
|
|
(self.timestamp_nanos / 1_000) * 1_000
|
|
}
|
|
DateTimePrecision::Nanosecond | DateTimePrecision::Nanoseconds => self.timestamp_nanos,
|
|
};
|
|
Self {
|
|
timestamp_nanos: truncated_timestamp_micros,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Debug for DateTime {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
let utc_rfc3339 = self.into_utc().format(&Rfc3339).map_err(|_| fmt::Error)?;
|
|
f.write_str(&utc_rfc3339)
|
|
}
|
|
}
|