@@ -4,12 +4,12 @@ use std::ops::{Add, Range, Sub};
4
4
5
5
use crate :: coord:: ranged1d:: {
6
6
AsRangedCoord , DefaultFormatting , DiscreteRanged , KeyPointHint , NoDefaultFormatting , Ranged ,
7
- ValueFormatter ,
7
+ ReversibleRanged , ValueFormatter ,
8
8
} ;
9
9
10
10
/// The trait that describe some time value. This is the uniformed abstraction that works
11
11
/// for both Date, DateTime and Duration, etc.
12
- pub trait TimeValue : Eq {
12
+ pub trait TimeValue : Eq + Sized {
13
13
type DateType : Datelike + PartialOrd ;
14
14
15
15
/// Returns the date that is no later than the time
@@ -20,6 +20,8 @@ pub trait TimeValue: Eq {
20
20
fn earliest_after_date ( date : Self :: DateType ) -> Self ;
21
21
/// Returns the duration between two time value
22
22
fn subtract ( & self , other : & Self ) -> Duration ;
23
+ /// Add duration to time value
24
+ fn add ( & self , duration : & Duration ) -> Self ;
23
25
/// Instantiate a date type for current time value;
24
26
fn ymd ( & self , year : i32 , month : u32 , date : u32 ) -> Self :: DateType ;
25
27
/// Cast current date type into this type
@@ -46,6 +48,25 @@ pub trait TimeValue: Eq {
46
48
47
49
( f64:: from ( limit. 1 - limit. 0 ) * value_days / total_days) as i32 + limit. 0
48
50
}
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
+ }
49
70
}
50
71
51
72
impl TimeValue for NaiveDate {
@@ -62,6 +83,9 @@ impl TimeValue for NaiveDate {
62
83
fn subtract ( & self , other : & NaiveDate ) -> Duration {
63
84
* self - * other
64
85
}
86
+ fn add ( & self , other : & Duration ) -> NaiveDate {
87
+ self . clone ( ) + * other
88
+ }
65
89
66
90
fn ymd ( & self , year : i32 , month : u32 , date : u32 ) -> Self :: DateType {
67
91
NaiveDate :: from_ymd ( year, month, date)
@@ -86,6 +110,9 @@ impl<Z: TimeZone> TimeValue for Date<Z> {
86
110
fn subtract ( & self , other : & Date < Z > ) -> Duration {
87
111
self . clone ( ) - other. clone ( )
88
112
}
113
+ fn add ( & self , other : & Duration ) -> Date < Z > {
114
+ self . clone ( ) + other. clone ( )
115
+ }
89
116
90
117
fn ymd ( & self , year : i32 , month : u32 , date : u32 ) -> Self :: DateType {
91
118
self . timezone ( ) . ymd ( year, month, date)
@@ -115,6 +142,9 @@ impl<Z: TimeZone> TimeValue for DateTime<Z> {
115
142
fn subtract ( & self , other : & DateTime < Z > ) -> Duration {
116
143
self . clone ( ) - other. clone ( )
117
144
}
145
+ fn add ( & self , other : & Duration ) -> DateTime < Z > {
146
+ self . clone ( ) + * other
147
+ }
118
148
119
149
fn ymd ( & self , year : i32 , month : u32 , date : u32 ) -> Self :: DateType {
120
150
self . timezone ( ) . ymd ( year, month, date)
@@ -144,6 +174,9 @@ impl TimeValue for NaiveDateTime {
144
174
fn subtract ( & self , other : & NaiveDateTime ) -> Duration {
145
175
* self - * other
146
176
}
177
+ fn add ( & self , other : & Duration ) -> NaiveDateTime {
178
+ * self + * other
179
+ }
147
180
148
181
fn ymd ( & self , year : i32 , month : u32 , date : u32 ) -> Self :: DateType {
149
182
NaiveDate :: from_ymd ( year, month, date)
@@ -663,6 +696,19 @@ where
663
696
}
664
697
}
665
698
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
+
666
712
/// The coordinate that for duration of time
667
713
#[ derive( Clone ) ]
668
714
pub struct RangedDuration ( Duration , Duration ) ;
0 commit comments