// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
use std::time::Duration;
use serde::{Deserialize, Serialize};
use crate::error::{Error, ErrorKind};
/// Different resolutions supported by the time related
/// metric types (e.g. DatetimeMetric).
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all =
"lowercase")]
#[repr(i32)]
// use i32 to be compatible with our JNA definition
pub enum TimeUnit {
/// Truncate to nanosecond precision.
Nanosecond,
/// Truncate to microsecond precision.
Microsecond,
/// Truncate to millisecond precision.
Millisecond,
/// Truncate to second precision.
Second,
/// Truncate to minute precision.
Minute,
/// Truncate to hour precision.
Hour,
/// Truncate to day precision.
Day,
}
impl TimeUnit {
/// Formats the given time unit, truncating the time if needed.
pub fn format_pattern(
self) -> &
'static str {
use TimeUnit::*;
match self {
Nanosecond =>
"%Y-%m-%dT%H:%M:%S%.f%:z",
Microsecond =>
"%Y-%m-%dT%H:%M:%S%.6f%:z",
Millisecond =>
"%Y-%m-%dT%H:%M:%S%.3f%:z",
Second =>
"%Y-%m-%dT%H:%M:%S%:z",
Minute =>
"%Y-%m-%dT%H:%M%:z",
Hour =>
"%Y-%m-%dT%H%:z",
Day =>
"%Y-%m-%d%:z",
}
}
/// Converts a duration to the requested time unit.
///
/// # Arguments
///
/// * `duration` - the duration to convert.
///
/// # Returns
///
/// The integer representation of the converted duration.
pub fn duration_convert(
self, duration: Duration) -> u64 {
use TimeUnit::*;
match self {
Nanosecond => duration.as_nanos()
as u64,
Microsecond => duration.as_micros()
as u64,
Millisecond => duration.as_millis()
as u64,
Second => duration.as_secs(),
Minute => duration.as_secs() /
60,
Hour => duration.as_secs() /
60 /
60,
Day => duration.as_secs() /
60 /
60 /
24,
}
}
/// Converts a duration in the given unit to nanoseconds.
///
/// # Arguments
///
/// * `duration` - the duration to convert.
///
/// # Returns
///
/// The integer representation of the nanosecond duration.
pub fn as_nanos(
self, duration: u64) -> u64 {
use TimeUnit::*;
let duration =
match self {
Nanosecond => Duration::from_nanos(duration),
Microsecond => Duration::from_micros(duration),
Millisecond => Duration::from_millis(duration),
Second => Duration::from_secs(duration),
Minute => Duration::from_secs(duration *
60),
Hour => Duration::from_secs(duration *
60 *
60),
Day => Duration::from_secs(duration *
60 *
60 *
24),
};
duration.as_nanos()
as u64
}
}
/// Trait implementation for converting an integer value to a TimeUnit.
///
/// This is used in the FFI code.
///
/// Please note that values should match the ordering of the
/// platform specific side of things (e.g. Kotlin implementation).
impl TryFrom<i32>
for TimeUnit {
type Error = Error;
fn try_from(value: i32) -> Result<TimeUnit,
Self::Error> {
match value {
0 => Ok(TimeUnit::Nanosecond),
1 => Ok(TimeUnit::Microsecond),
2 => Ok(TimeUnit::Millisecond),
3 => Ok(TimeUnit::Second),
4 => Ok(TimeUnit::Minute),
5 => Ok(TimeUnit::Hour),
6 => Ok(TimeUnit::Day),
e => Err(ErrorKind::TimeUnit(e).into()),
}
}
}