Skip to content

Commit 463c2b8

Browse files
committed
implement ReversibleRanged for TimeValue
1 parent 25a2f86 commit 463c2b8

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

plotters/src/coord/ranged1d/types/datetime.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use std::ops::{Add, Range, Sub};
44

55
use crate::coord::ranged1d::{
66
AsRangedCoord, DefaultFormatting, DiscreteRanged, KeyPointHint, NoDefaultFormatting, Ranged,
7-
ValueFormatter,
7+
ReversibleRanged, ValueFormatter,
88
};
99

1010
/// The trait that describe some time value. This is the uniformed abstraction that works
1111
/// for both Date, DateTime and Duration, etc.
12-
pub trait TimeValue: Eq {
12+
pub trait TimeValue: Eq + Sized {
1313
type DateType: Datelike + PartialOrd;
1414

1515
/// Returns the date that is no later than the time
@@ -20,6 +20,8 @@ pub trait TimeValue: Eq {
2020
fn earliest_after_date(date: Self::DateType) -> Self;
2121
/// Returns the duration between two time value
2222
fn subtract(&self, other: &Self) -> Duration;
23+
/// Add duration to time value
24+
fn add(&self, duration: &Duration) -> Self;
2325
/// Instantiate a date type for current time value;
2426
fn ymd(&self, year: i32, month: u32, date: u32) -> Self::DateType;
2527
/// Cast current date type into this type
@@ -46,6 +48,25 @@ pub trait TimeValue: Eq {
4648

4749
(f64::from(limit.1 - limit.0) * value_days / total_days) as i32 + limit.0
4850
}
51+
52+
/// Map pixel to coord spec
53+
fn unmap_coord(point: i32, begin: &Self, end: &Self, limit: (i32, i32)) -> Self {
54+
let total_span = end.subtract(begin);
55+
let offset = (point - limit.0) as i64;
56+
57+
// Check if nanoseconds fit in i64
58+
if let Some(total_ns) = total_span.num_nanoseconds() {
59+
if i64::MAX/total_ns < offset.abs() {
60+
let nano_seconds = offset*total_ns/((limit.1-limit.0) as i64);
61+
return begin.add(&Duration::nanoseconds(nano_seconds));
62+
}
63+
}
64+
65+
// Otherwise, use days
66+
let total_days = total_span.num_days() as f64;
67+
let days = (((offset as f64)*total_days)/((limit.1-limit.0) as f64)) as i64;
68+
begin.add(&Duration::days(days))
69+
}
4970
}
5071

5172
impl TimeValue for NaiveDate {
@@ -62,6 +83,9 @@ impl TimeValue for NaiveDate {
6283
fn subtract(&self, other: &NaiveDate) -> Duration {
6384
*self - *other
6485
}
86+
fn add(&self, other: &Duration) -> NaiveDate {
87+
self.clone() + *other
88+
}
6589

6690
fn ymd(&self, year: i32, month: u32, date: u32) -> Self::DateType {
6791
NaiveDate::from_ymd(year, month, date)
@@ -86,6 +110,9 @@ impl<Z: TimeZone> TimeValue for Date<Z> {
86110
fn subtract(&self, other: &Date<Z>) -> Duration {
87111
self.clone() - other.clone()
88112
}
113+
fn add(&self, other: &Duration) -> Date<Z> {
114+
self.clone() + other.clone()
115+
}
89116

90117
fn ymd(&self, year: i32, month: u32, date: u32) -> Self::DateType {
91118
self.timezone().ymd(year, month, date)
@@ -115,6 +142,9 @@ impl<Z: TimeZone> TimeValue for DateTime<Z> {
115142
fn subtract(&self, other: &DateTime<Z>) -> Duration {
116143
self.clone() - other.clone()
117144
}
145+
fn add(&self, other: &Duration) -> DateTime<Z> {
146+
self.clone() + *other
147+
}
118148

119149
fn ymd(&self, year: i32, month: u32, date: u32) -> Self::DateType {
120150
self.timezone().ymd(year, month, date)
@@ -144,6 +174,9 @@ impl TimeValue for NaiveDateTime {
144174
fn subtract(&self, other: &NaiveDateTime) -> Duration {
145175
*self - *other
146176
}
177+
fn add(&self, other: &Duration) -> NaiveDateTime {
178+
*self + *other
179+
}
147180

148181
fn ymd(&self, year: i32, month: u32, date: u32) -> Self::DateType {
149182
NaiveDate::from_ymd(year, month, date)
@@ -663,6 +696,19 @@ where
663696
}
664697
}
665698

699+
impl<DT> ReversibleRanged for RangedDateTime<DT>
700+
where
701+
DT: Datelike + Timelike + TimeValue + Clone + PartialOrd,
702+
DT: Add<Duration, Output = DT>,
703+
DT: Sub<DT, Output = Duration>,
704+
RangedDate<DT::DateType>: Ranged<ValueType = DT::DateType>,
705+
{
706+
/// Perform the reverse mapping
707+
fn unmap(&self, input: i32, limit: (i32, i32)) -> Option<Self::ValueType> {
708+
Some(TimeValue::unmap_coord(input, &self.0, &self.1, limit))
709+
}
710+
}
711+
666712
/// The coordinate that for duration of time
667713
#[derive(Clone)]
668714
pub struct RangedDuration(Duration, Duration);

0 commit comments

Comments
 (0)