#[cfg(test)]
mod test;
use std::sync::Arc;
use vortex_datetime_dtype::{TemporalMetadata, TimeUnit, DATE_ID, TIMESTAMP_ID, TIME_ID};
use vortex_dtype::{DType, ExtDType};
use vortex_error::{vortex_panic, VortexError};
use crate::array::ExtensionArray;
use crate::variants::ExtensionArrayTrait;
use crate::{Array, ArrayDType, IntoArray};
#[derive(Clone, Debug)]
pub struct TemporalArray {
ext: ExtensionArray,
temporal_metadata: TemporalMetadata,
}
macro_rules! assert_width {
($width:ty, $array:expr) => {{
let DType::Primitive(ptype, _) = $array.dtype() else {
panic!("array must have primitive type");
};
assert_eq!(
<$width as vortex_dtype::NativePType>::PTYPE,
*ptype,
"invalid ptype {} for array, expected {}",
<$width as vortex_dtype::NativePType>::PTYPE,
*ptype
);
}};
}
impl TemporalArray {
pub fn new_date(array: Array, time_unit: TimeUnit) -> Self {
match time_unit {
TimeUnit::D => {
assert_width!(i32, array);
}
TimeUnit::Ms => {
assert_width!(i64, array);
}
_ => vortex_panic!("invalid TimeUnit {time_unit} for vortex.date"),
};
let ext_dtype = ExtDType::new(
DATE_ID.clone(),
Arc::new(array.dtype().clone()),
Some(TemporalMetadata::Date(time_unit).into()),
);
Self {
ext: ExtensionArray::new(Arc::new(ext_dtype), array),
temporal_metadata: TemporalMetadata::Date(time_unit),
}
}
pub fn new_time(array: Array, time_unit: TimeUnit) -> Self {
match time_unit {
TimeUnit::S | TimeUnit::Ms => assert_width!(i32, array),
TimeUnit::Us | TimeUnit::Ns => assert_width!(i64, array),
TimeUnit::D => vortex_panic!("invalid unit D for vortex.time data"),
}
let temporal_metadata = TemporalMetadata::Time(time_unit);
Self {
ext: ExtensionArray::new(
Arc::new(ExtDType::new(
TIME_ID.clone(),
Arc::new(array.dtype().clone()),
Some(temporal_metadata.clone().into()),
)),
array,
),
temporal_metadata,
}
}
pub fn new_timestamp(array: Array, time_unit: TimeUnit, time_zone: Option<String>) -> Self {
assert_width!(i64, array);
let temporal_metadata = TemporalMetadata::Timestamp(time_unit, time_zone);
Self {
ext: ExtensionArray::new(
Arc::new(ExtDType::new(
TIMESTAMP_ID.clone(),
Arc::new(array.dtype().clone()),
Some(temporal_metadata.clone().into()),
)),
array,
),
temporal_metadata,
}
}
}
impl TemporalArray {
pub fn temporal_values(&self) -> Array {
self.ext.storage()
}
pub fn temporal_metadata(&self) -> &TemporalMetadata {
&self.temporal_metadata
}
pub fn ext_dtype(&self) -> Arc<ExtDType> {
self.ext.ext_dtype().clone()
}
}
impl From<TemporalArray> for Array {
fn from(value: TemporalArray) -> Self {
value.ext.into_array()
}
}
impl TryFrom<&Array> for TemporalArray {
type Error = VortexError;
fn try_from(value: &Array) -> Result<Self, Self::Error> {
let ext = ExtensionArray::try_from(value)?;
let temporal_metadata = TemporalMetadata::try_from(ext.ext_dtype().as_ref())?;
Ok(Self {
ext,
temporal_metadata,
})
}
}
impl TryFrom<Array> for TemporalArray {
type Error = VortexError;
fn try_from(value: Array) -> Result<Self, Self::Error> {
TemporalArray::try_from(&value)
}
}
impl From<&TemporalArray> for ExtensionArray {
fn from(value: &TemporalArray) -> Self {
value.ext.clone()
}
}
impl From<TemporalArray> for ExtensionArray {
fn from(value: TemporalArray) -> Self {
value.ext
}
}
impl TryFrom<ExtensionArray> for TemporalArray {
type Error = VortexError;
fn try_from(ext: ExtensionArray) -> Result<Self, Self::Error> {
let temporal_metadata = TemporalMetadata::try_from(ext.ext_dtype().as_ref())?;
Ok(Self {
ext,
temporal_metadata,
})
}
}