Skip to content

Commit

Permalink
Ry jiff round fix (#199)
Browse files Browse the repository at this point in the history
* clean up of the rounding functions

* fix: time span math

* fix: type annotations
  • Loading branch information
jessekrubin authored Feb 13, 2025
1 parent b818c90 commit 60d7601
Show file tree
Hide file tree
Showing 17 changed files with 975 additions and 610 deletions.
521 changes: 320 additions & 201 deletions README.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions crates/ryo3-jiff/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub use crate::ry_zoned::RyZoned;
pub use crate::ry_zoned_difference::RyZonedDifference;

use crate::ry_iso_week_date::RyISOWeekDate;
use crate::ry_zoned_round::RyZonedDateTimeRound;
use pyo3::prelude::*;

pub fn pymod_add(m: &Bound<'_, PyModule>) -> PyResult<()> {
Expand All @@ -41,6 +42,7 @@ pub fn pymod_add(m: &Bound<'_, PyModule>) -> PyResult<()> {

// round
m.add_class::<RyDateTimeRound>()?;
m.add_class::<RyZonedDateTimeRound>()?;
m.add_class::<RyTimestampRound>()?;

// functions
Expand Down
45 changes: 0 additions & 45 deletions crates/ryo3-jiff/src/internal/datetime_round.rs

This file was deleted.

5 changes: 0 additions & 5 deletions crates/ryo3-jiff/src/internal/mod.rs

This file was deleted.

21 changes: 6 additions & 15 deletions crates/ryo3-jiff/src/into_span_arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ pub(crate) enum IntoSpanArithmetic {
Dos((SpanArithmeticTupleIx0, SpanArithmeticTupleIx1)),
}

impl From<IntoSpanArithmetic> for SpanArithmetic<'_> {
fn from<'b>(value: IntoSpanArithmetic) -> Self {
// HERE WE HAVE A TOTAL CLUSTERFUCK OF MATCHING...
impl<'a> From<&'a IntoSpanArithmetic> for SpanArithmetic<'a> {
fn from(value: &'a IntoSpanArithmetic) -> Self {
// HERE WE HAVE A TOTAL CLUSTER-FUCK OF MATCHING...
// BUT I AM NOT SURE HOW TO GET THIS TO PLAY NICE WITH PYTHON + LIFETIMES
match value {
IntoSpanArithmetic::Uno(s) => match s {
Expand All @@ -43,26 +43,17 @@ impl From<IntoSpanArithmetic> for SpanArithmetic<'_> {
},
IntoSpanArithmetic::Dos((s, r)) => match s {
SpanArithmeticTupleIx0::Span(sp) => match r {
// TODO: figure out if this is bad........
SpanArithmeticTupleIx1::Zoned(z) => {
SpanArithmetic::from((sp.0, z.0.datetime()))
}
SpanArithmeticTupleIx1::Zoned(z) => SpanArithmetic::from((&sp.0, &z.0)),
SpanArithmeticTupleIx1::Date(d) => SpanArithmetic::from((sp.0, d.0)),
SpanArithmeticTupleIx1::DateTime(dt) => SpanArithmetic::from((sp.0, dt.0)),
},
SpanArithmeticTupleIx0::Duration(dur) => match r {
// TODO: figure out if this is bad........
SpanArithmeticTupleIx1::Zoned(z) => {
SpanArithmetic::from((dur.0, z.0.datetime()))
}
SpanArithmeticTupleIx1::Zoned(z) => SpanArithmetic::from((dur.0, &z.0)),
SpanArithmeticTupleIx1::Date(d) => SpanArithmetic::from((dur.0, d.0)),
SpanArithmeticTupleIx1::DateTime(dt) => SpanArithmetic::from((dur.0, dt.0)),
},
SpanArithmeticTupleIx0::SignedDuration(dur) => match r {
// TODO: figure out if this is bad........
SpanArithmeticTupleIx1::Zoned(z) => {
SpanArithmetic::from((dur.0, z.0.datetime()))
}
SpanArithmeticTupleIx1::Zoned(z) => SpanArithmetic::from((dur.0, &z.0)),
SpanArithmeticTupleIx1::Date(d) => SpanArithmetic::from((dur.0, d.0)),
SpanArithmeticTupleIx1::DateTime(dt) => SpanArithmetic::from((dur.0, dt.0)),
},
Expand Down
3 changes: 2 additions & 1 deletion crates/ryo3-jiff/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

mod delta_arithmetic_self;
mod dev;
mod internal;
mod jiff_types;
pub use jiff_types::*;
mod deprecations;
Expand Down Expand Up @@ -42,5 +41,7 @@ mod ry_timezone;
mod ry_weekday;
mod ry_zoned;
mod ry_zoned_difference;
mod ry_zoned_round;
mod span_relative_to;

pub use api::*;
33 changes: 29 additions & 4 deletions crates/ryo3-jiff/src/ry_datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::ry_span::RySpan;
use crate::ry_time::RyTime;
use crate::ry_timezone::RyTimeZone;
use crate::ry_zoned::RyZoned;
use crate::{JiffEraYear, JiffRoundMode, JiffUnit, JiffWeekday, RyDate};
use jiff::civil::{DateTime, Weekday};
use crate::{JiffEraYear, JiffRoundMode, JiffUnit, JiffWeekday, RyDate, RyDateTimeRound};
use jiff::civil::{DateTime, DateTimeRound, Weekday};
use jiff::Zoned;
use pyo3::basic::CompareOp;
use pyo3::intern;
Expand Down Expand Up @@ -348,9 +348,34 @@ impl RyDateTime {
Ok(dict)
}

fn round(&self, option: crate::internal::IntoDateTimeRound) -> PyResult<Self> {
#[pyo3(
signature = (smallest=None, *, mode = None, increment = None),
)]
fn round(
&self,
smallest: Option<JiffUnit>,
mode: Option<JiffRoundMode>,
increment: Option<i64>,
) -> PyResult<Self> {
let mut dt_round = DateTimeRound::new();
if let Some(smallest) = smallest {
dt_round = dt_round.smallest(smallest.0);
}
if let Some(mode) = mode {
dt_round = dt_round.mode(mode.0);
}
if let Some(increment) = increment {
dt_round = dt_round.increment(increment);
}
self.0
.round(dt_round)
.map(RyDateTime::from)
.map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(format!("{e}")))
}

fn _round(&self, dt_round: &RyDateTimeRound) -> PyResult<Self> {
self.0
.round(option)
.round(dt_round.round)
.map(RyDateTime::from)
.map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(format!("{e}")))
}
Expand Down
33 changes: 22 additions & 11 deletions crates/ryo3-jiff/src/ry_span.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::errors::{map_py_overflow_err, map_py_value_err};
use crate::internal::RySpanRelativeTo;
use crate::into_span_arithmetic::IntoSpanArithmetic;
use crate::ry_signed_duration::RySignedDuration;
use crate::span_relative_to::RySpanRelativeTo;
use crate::{timespan, JiffRoundMode, JiffSpan, JiffUnit, RyDate, RyDateTime, RyZoned};
use jiff::{Span, SpanArithmetic, SpanRelativeTo, SpanRound};
use pyo3::prelude::PyAnyMethods;
Expand Down Expand Up @@ -395,27 +395,43 @@ impl RySpan {
}
}

#[expect(clippy::needless_pass_by_value)]
fn __add__(&self, other: IntoSpanArithmetic) -> PyResult<Self> {
let span_arithmetic: SpanArithmetic = other.into();
let span_arithmetic: SpanArithmetic = (&other).into();
self.0
.checked_add(span_arithmetic)
.map(RySpan::from)
.map_err(map_py_overflow_err)
}

#[expect(clippy::needless_pass_by_value)]
fn checked_add(&self, other: IntoSpanArithmetic) -> PyResult<Self> {
self.__add__(other)
let span_arithmetic: SpanArithmetic = (&other).into();

self.0
.checked_add(span_arithmetic)
.map(RySpan::from)
.map_err(map_py_overflow_err)
}

#[expect(clippy::needless_pass_by_value)]
fn __sub__(&self, other: IntoSpanArithmetic) -> PyResult<Self> {
let span_arithmetic: SpanArithmetic = other.into();
let span_arithmetic: SpanArithmetic = (&other).into();
self.0
.checked_sub(span_arithmetic)
.map(RySpan::from)
.map_err(map_py_overflow_err)
}

#[expect(clippy::needless_pass_by_value)]
fn checked_sub(&self, other: IntoSpanArithmetic) -> PyResult<Self> {
self.__sub__(other)
let span_arithmetic: SpanArithmetic = (&other).into();
self.0
.checked_sub(span_arithmetic)
.map(RySpan::from)
.map_err(map_py_overflow_err)
}

fn __mul__(&self, rhs: i64) -> PyResult<Self> {
self.0
.checked_mul(rhs)
Expand Down Expand Up @@ -616,12 +632,7 @@ impl RySpan {
.map(RySpan::from)
.map_err(map_py_value_err)
}
// fn round(&self, round: IntoDateTimeRound) -> PyResult<Self> {
// self.0
// .round(round)
// .map(RySpan::from)
// .map_err(map_py_value_err)
// }

fn signum(&self) -> i8 {
self.0.signum()
}
Expand Down
21 changes: 2 additions & 19 deletions crates/ryo3-jiff/src/ry_timestamp_difference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl RyTimestampDifference {
RyTimestampDifference(self.0.increment(increment))
}
}

#[derive(Debug, Clone, FromPyObject)]
pub(crate) enum IntoTimestampDifferenceTuple {
UnitTimestamp(JiffUnit, RyTimestamp),
Expand All @@ -79,30 +80,12 @@ impl From<IntoTimestampDifferenceTuple> for TimestampDifference {
}
}

#[derive(Debug, Clone, FromPyObject)]
pub(crate) enum IntoTimestampDifference {
RyTimestampDifference(RyTimestampDifference),
Zoned(RyZoned),
Timestamp(RyTimestamp),
TimestampDifferenceTuple(IntoTimestampDifferenceTuple),
}

impl From<IntoTimestampDifference> for TimestampDifference {
fn from(val: IntoTimestampDifference) -> Self {
match val {
IntoTimestampDifference::RyTimestampDifference(d_diff) => d_diff.0,
IntoTimestampDifference::Zoned(zoned) => TimestampDifference::from(zoned.0),
IntoTimestampDifference::Timestamp(date) => TimestampDifference::from(date.0),
IntoTimestampDifference::TimestampDifferenceTuple(tuple) => tuple.into(),
}
}
}

#[derive(Debug, Clone, FromPyObject)]
pub(crate) enum TimestampDifferenceArg {
Zoned(RyZoned),
Timestamp(RyTimestamp),
}

impl TimestampDifferenceArg {
pub(crate) fn build(
self,
Expand Down
33 changes: 29 additions & 4 deletions crates/ryo3-jiff/src/ry_zoned.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::delta_arithmetic_self::RyDeltaArithmeticSelf;
use crate::deprecations::deprecation_warning_intz;
use crate::errors::map_py_value_err;
use crate::internal::IntoDateTimeRound;
use crate::pydatetime_conversions::zoned2pyobect;
use crate::ry_datetime::RyDateTime;
use crate::ry_iso_week_date::RyISOWeekDate;
Expand All @@ -11,9 +10,10 @@ use crate::ry_span::RySpan;
use crate::ry_time::RyTime;
use crate::ry_timestamp::RyTimestamp;
use crate::ry_timezone::RyTimeZone;
use crate::ry_zoned_round::RyZonedDateTimeRound;
use crate::{JiffEraYear, JiffRoundMode, JiffUnit, JiffWeekday, JiffZoned, RyDate};
use jiff::civil::Weekday;
use jiff::{Zoned, ZonedDifference};
use jiff::{Zoned, ZonedDifference, ZonedRound};
use pyo3::prelude::*;
use pyo3::pyclass::CompareOp;
use pyo3::types::{PyDate, PyDateTime, PyType};
Expand Down Expand Up @@ -272,9 +272,34 @@ impl RyZoned {
RyTimeZone::from(self.0.time_zone())
}

fn round(&self, option: IntoDateTimeRound) -> PyResult<Self> {
#[pyo3(
signature = (smallest=None, *, mode = None, increment = None),
)]
fn round(
&self,
smallest: Option<JiffUnit>,
mode: Option<JiffRoundMode>,
increment: Option<i64>,
) -> PyResult<Self> {
let mut zdt_round = ZonedRound::new();
if let Some(smallest) = smallest {
zdt_round = zdt_round.smallest(smallest.0);
}
if let Some(mode) = mode {
zdt_round = zdt_round.mode(mode.0);
}
if let Some(increment) = increment {
zdt_round = zdt_round.increment(increment);
}
self.0
.round(zdt_round)
.map(RyZoned::from)
.map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(format!("{e}")))
}

fn _round(&self, dt_round: &RyZonedDateTimeRound) -> PyResult<Self> {
self.0
.round(option)
.round(dt_round.round)
.map(RyZoned::from)
.map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(format!("{e}")))
}
Expand Down
Loading

0 comments on commit 60d7601

Please sign in to comment.