use arrow::temporal_conversions::{MICROSECONDS, MILLISECONDS, NANOSECONDS, SECONDS_IN_DAY};
use super::*;
const NANOSECONDS_IN_MILLISECOND: i64 = 1_000_000;
const SECONDS_IN_HOUR: i64 = 3600;
pub trait DurationMethods {
fn days(&self) -> Int64Chunked;
fn days_fractional(&self) -> Float64Chunked;
fn hours(&self) -> Int64Chunked;
fn hours_fractional(&self) -> Float64Chunked;
fn minutes(&self) -> Int64Chunked;
fn minutes_fractional(&self) -> Float64Chunked;
fn seconds(&self) -> Int64Chunked;
fn seconds_fractional(&self) -> Float64Chunked;
fn milliseconds(&self) -> Int64Chunked;
fn milliseconds_fractional(&self) -> Float64Chunked;
fn microseconds(&self) -> Int64Chunked;
fn microseconds_fractional(&self) -> Float64Chunked;
fn nanoseconds(&self) -> Int64Chunked;
fn nanoseconds_fractional(&self) -> Float64Chunked;
}
impl DurationMethods for DurationChunked {
fn hours(&self) -> Int64Chunked {
let t = time_units_in_second(self.time_unit());
(&self.phys).wrapping_trunc_div_scalar(t * SECONDS_IN_HOUR)
}
fn hours_fractional(&self) -> Float64Chunked {
let t = time_units_in_second(self.time_unit());
num_of_unit_fractional(self, t as f64 * SECONDS_IN_HOUR as f64)
}
fn days(&self) -> Int64Chunked {
let t = time_units_in_second(self.time_unit());
(&self.phys).wrapping_trunc_div_scalar(t * SECONDS_IN_DAY)
}
fn days_fractional(&self) -> Float64Chunked {
let t = time_units_in_second(self.time_unit());
num_of_unit_fractional(self, t as f64 * SECONDS_IN_DAY as f64)
}
fn minutes(&self) -> Int64Chunked {
let t = time_units_in_second(self.time_unit());
(&self.phys).wrapping_trunc_div_scalar(t * 60)
}
fn minutes_fractional(&self) -> Float64Chunked {
let t = time_units_in_second(self.time_unit());
num_of_unit_fractional(self, t as f64 * 60.0)
}
fn seconds(&self) -> Int64Chunked {
let t = time_units_in_second(self.time_unit());
(&self.phys).wrapping_trunc_div_scalar(t)
}
fn seconds_fractional(&self) -> Float64Chunked {
let t = time_units_in_second(self.time_unit());
num_of_unit_fractional(self, t as f64)
}
fn milliseconds(&self) -> Int64Chunked {
let t = match self.time_unit() {
TimeUnit::Milliseconds => return self.phys.clone(),
TimeUnit::Microseconds => 1000,
TimeUnit::Nanoseconds => NANOSECONDS_IN_MILLISECOND,
};
(&self.phys).wrapping_trunc_div_scalar(t)
}
fn milliseconds_fractional(&self) -> Float64Chunked {
let t = time_units_in_second(self.time_unit());
num_of_unit_fractional(self, t as f64 / MILLISECONDS as f64)
}
fn microseconds(&self) -> Int64Chunked {
match self.time_unit() {
TimeUnit::Milliseconds => &self.phys * 1000,
TimeUnit::Microseconds => self.phys.clone(),
TimeUnit::Nanoseconds => (&self.phys).wrapping_trunc_div_scalar(1000),
}
}
fn microseconds_fractional(&self) -> Float64Chunked {
let t = time_units_in_second(self.time_unit());
num_of_unit_fractional(self, t as f64 / MICROSECONDS as f64)
}
fn nanoseconds(&self) -> Int64Chunked {
match self.time_unit() {
TimeUnit::Milliseconds => &self.phys * NANOSECONDS_IN_MILLISECOND,
TimeUnit::Microseconds => &self.phys * 1000,
TimeUnit::Nanoseconds => self.phys.clone(),
}
}
fn nanoseconds_fractional(&self) -> Float64Chunked {
let t = time_units_in_second(self.time_unit());
num_of_unit_fractional(self, t as f64 / NANOSECONDS as f64)
}
}
fn time_units_in_second(tu: TimeUnit) -> i64 {
match tu {
TimeUnit::Milliseconds => MILLISECONDS,
TimeUnit::Microseconds => MICROSECONDS,
TimeUnit::Nanoseconds => NANOSECONDS,
}
}
fn num_of_unit_fractional(ca: &DurationChunked, unit_ns: f64) -> Float64Chunked {
ca.physical()
.cast(&DataType::Float64)
.expect("cast failed")
.f64()
.unwrap()
/ unit_ns
}