use vortex_array::ArrayRef;
use vortex_array::ExecutionCtx;
use vortex_array::IntoArray;
use vortex_array::arrays::PrimitiveArray;
use vortex_array::arrays::TemporalArray;
use vortex_array::builtins::ArrayBuiltins;
use vortex_array::dtype::DType;
use vortex_array::dtype::PType;
use vortex_buffer::BufferMut;
use vortex_error::VortexResult;
use crate::timestamp;
pub struct TemporalParts {
pub days: ArrayRef,
pub seconds: ArrayRef,
pub subseconds: ArrayRef,
}
pub fn split_temporal(array: TemporalArray, ctx: &mut ExecutionCtx) -> VortexResult<TemporalParts> {
let temporal_values = array
.temporal_values()
.clone()
.execute::<PrimitiveArray>(ctx)?;
let timestamps = temporal_values
.clone()
.into_array()
.cast(DType::Primitive(
PType::I64,
temporal_values.dtype().nullability(),
))?
.execute::<PrimitiveArray>(ctx)?;
let length = timestamps.len();
let mut days = BufferMut::with_capacity(length);
let mut seconds = BufferMut::with_capacity(length);
let mut subseconds = BufferMut::with_capacity(length);
for &ts in timestamps.as_slice::<i64>() {
let ts_parts = timestamp::split(ts, array.temporal_metadata().time_unit())?;
days.push(ts_parts.days);
seconds.push(ts_parts.seconds);
subseconds.push(ts_parts.subseconds);
}
Ok(TemporalParts {
days: PrimitiveArray::new(days, temporal_values.validity()?).into_array(),
seconds: seconds.into_array(),
subseconds: subseconds.into_array(),
})
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use vortex_array::IntoArray;
use vortex_array::LEGACY_SESSION;
use vortex_array::VortexSessionExecute;
use vortex_array::arrays::PrimitiveArray;
use vortex_array::arrays::TemporalArray;
use vortex_array::extension::datetime::TimeUnit;
use vortex_array::validity::Validity;
use vortex_buffer::buffer;
use vortex_error::VortexExpect;
use crate::TemporalParts;
use crate::split_temporal;
#[rstest]
#[case(Validity::NonNullable)]
#[case(Validity::AllValid)]
#[case(Validity::AllInvalid)]
#[case(Validity::from_iter([true, false, true]))]
fn test_split_temporal(#[case] validity: Validity) {
let mut ctx = LEGACY_SESSION.create_execution_ctx();
let milliseconds = PrimitiveArray::new(
buffer![
86_400i64, 86_400i64 + 1000, 86_400i64 + 1000 + 1, ],
validity.clone(),
)
.into_array();
let temporal_array =
TemporalArray::new_timestamp(milliseconds, TimeUnit::Milliseconds, Some("UTC".into()));
let TemporalParts {
days,
seconds,
subseconds,
} = split_temporal(temporal_array, &mut ctx).unwrap();
let days_prim = days.execute::<PrimitiveArray>(&mut ctx).unwrap();
assert!(
days_prim
.validity()
.vortex_expect("days validity should be derivable")
.mask_eq(&validity, &mut ctx)
.unwrap()
);
let seconds_prim = seconds.execute::<PrimitiveArray>(&mut ctx).unwrap();
assert!(matches!(
seconds_prim
.validity()
.vortex_expect("seconds validity should be derivable"),
Validity::NonNullable
));
let subseconds_prim = subseconds.execute::<PrimitiveArray>(&mut ctx).unwrap();
assert!(matches!(
subseconds_prim
.validity()
.vortex_expect("subseconds validity should be derivable"),
Validity::NonNullable
));
}
}