@@ -56,9 +56,14 @@ pub trait TimeValue: Eq + Sized {
56
56
57
57
// Check if nanoseconds fit in i64
58
58
if let Some ( total_ns) = total_span. num_nanoseconds ( ) {
59
- let factor = total_ns / ( ( limit. 1 - limit. 0 ) as i64 ) ;
60
- if i64:: MAX / factor > offset. abs ( ) {
61
- let nano_seconds = offset * factor;
59
+ let pixel_span = ( limit. 1 - limit. 0 ) as i64 ;
60
+ let factor = total_ns / pixel_span;
61
+ let remainder = total_ns % pixel_span;
62
+ if factor == 0
63
+ || i64:: MAX / factor > offset. abs ( )
64
+ || ( remainder == 0 && i64:: MAX / factor >= offset. abs ( ) )
65
+ {
66
+ let nano_seconds = offset * factor + ( remainder * offset) / pixel_span;
62
67
return begin. add ( & Duration :: nanoseconds ( nano_seconds) ) ;
63
68
}
64
69
}
@@ -85,7 +90,7 @@ impl TimeValue for NaiveDate {
85
90
* self - * other
86
91
}
87
92
fn add ( & self , other : & Duration ) -> NaiveDate {
88
- self . clone ( ) + * other
93
+ * self + * other
89
94
}
90
95
91
96
fn ymd ( & self , year : i32 , month : u32 , date : u32 ) -> Self :: DateType {
@@ -112,7 +117,7 @@ impl<Z: TimeZone> TimeValue for Date<Z> {
112
117
self . clone ( ) - other. clone ( )
113
118
}
114
119
fn add ( & self , other : & Duration ) -> Date < Z > {
115
- self . clone ( ) + other. clone ( )
120
+ self . clone ( ) + * other
116
121
}
117
122
118
123
fn ymd ( & self , year : i32 , month : u32 , date : u32 ) -> Self :: DateType {
@@ -1221,7 +1226,7 @@ mod test {
1221
1226
let start_time = Utc . ymd ( 2021 , 1 , 1 ) . and_hms ( 8 , 0 , 0 ) ;
1222
1227
let end_time = Utc . ymd ( 2023 , 1 , 1 ) . and_hms ( 8 , 0 , 0 ) ;
1223
1228
let mid = Utc . ymd ( 2022 , 1 , 1 ) . and_hms ( 8 , 0 , 0 ) ;
1224
- let coord: RangedDate < chrono :: DateTime < _ > > = ( start_time..end_time) . into ( ) ;
1229
+ let coord: RangedDateTime < _ > = ( start_time..end_time) . into ( ) ;
1225
1230
let pos = coord. map ( & mid, ( 1000 , 2000 ) ) ;
1226
1231
assert_eq ! ( pos, 1500 ) ;
1227
1232
let value = coord. unmap ( pos, ( 1000 , 2000 ) ) ;
@@ -1230,10 +1235,10 @@ mod test {
1230
1235
1231
1236
#[ test]
1232
1237
fn test_naivedatetime_with_unmap ( ) {
1233
- let start_time = chrono :: NaiveDate :: from_ymd ( 2021 , 1 , 1 ) . and_hms_milli ( 8 , 0 , 0 , 0 ) ;
1234
- let end_time = chrono :: NaiveDate :: from_ymd ( 2023 , 1 , 1 ) . and_hms_milli ( 8 , 0 , 0 , 0 ) ;
1235
- let mid = chrono :: NaiveDate :: from_ymd ( 2022 , 1 , 1 ) . and_hms_milli ( 8 , 0 , 0 , 0 ) ;
1236
- let coord: RangedDate < chrono :: NaiveDateTime > = ( start_time..end_time) . into ( ) ;
1238
+ let start_time = NaiveDate :: from_ymd ( 2021 , 1 , 1 ) . and_hms_milli ( 8 , 0 , 0 , 0 ) ;
1239
+ let end_time = NaiveDate :: from_ymd ( 2023 , 1 , 1 ) . and_hms_milli ( 8 , 0 , 0 , 0 ) ;
1240
+ let mid = NaiveDate :: from_ymd ( 2022 , 1 , 1 ) . and_hms_milli ( 8 , 0 , 0 , 0 ) ;
1241
+ let coord: RangedDateTime < _ > = ( start_time..end_time) . into ( ) ;
1237
1242
let pos = coord. map ( & mid, ( 1000 , 2000 ) ) ;
1238
1243
assert_eq ! ( pos, 1500 ) ;
1239
1244
let value = coord. unmap ( pos, ( 1000 , 2000 ) ) ;
@@ -1245,7 +1250,7 @@ mod test {
1245
1250
let start_date = Utc . ymd ( 2021 , 1 , 1 ) ;
1246
1251
let end_date = Utc . ymd ( 2023 , 1 , 1 ) ;
1247
1252
let mid = Utc . ymd ( 2022 , 1 , 1 ) ;
1248
- let coord: RangedDate < chrono :: Date < _ > > = ( start_date..end_date) . into ( ) ;
1253
+ let coord: RangedDate < Date < _ > > = ( start_date..end_date) . into ( ) ;
1249
1254
let pos = coord. map ( & mid, ( 1000 , 2000 ) ) ;
1250
1255
assert_eq ! ( pos, 1500 ) ;
1251
1256
let value = coord. unmap ( pos, ( 1000 , 2000 ) ) ;
@@ -1254,13 +1259,37 @@ mod test {
1254
1259
1255
1260
#[ test]
1256
1261
fn test_naivedate_with_unmap ( ) {
1257
- let start_date = chrono :: NaiveDate :: from_ymd ( 2021 , 1 , 1 ) ;
1258
- let end_date = chrono :: NaiveDate :: from_ymd ( 2023 , 1 , 1 ) ;
1259
- let mid = chrono :: NaiveDate :: from_ymd ( 2022 , 1 , 1 ) ;
1260
- let coord: RangedDate < chrono :: NaiveDate > = ( start_date..end_date) . into ( ) ;
1262
+ let start_date = NaiveDate :: from_ymd ( 2021 , 1 , 1 ) ;
1263
+ let end_date = NaiveDate :: from_ymd ( 2023 , 1 , 1 ) ;
1264
+ let mid = NaiveDate :: from_ymd ( 2022 , 1 , 1 ) ;
1265
+ let coord: RangedDate < NaiveDate > = ( start_date..end_date) . into ( ) ;
1261
1266
let pos = coord. map ( & mid, ( 1000 , 2000 ) ) ;
1262
1267
assert_eq ! ( pos, 1500 ) ;
1263
1268
let value = coord. unmap ( pos, ( 1000 , 2000 ) ) ;
1264
1269
assert_eq ! ( value, Some ( mid) ) ;
1265
1270
}
1271
+
1272
+ #[ test]
1273
+ fn test_datetime_unmap_for_nanoseconds ( ) {
1274
+ let start_time = Utc . ymd ( 2021 , 1 , 1 ) . and_hms ( 8 , 0 , 0 ) ;
1275
+ let end_time = start_time + Duration :: nanoseconds ( 1900 ) ;
1276
+ let mid = start_time + Duration :: nanoseconds ( 950 ) ;
1277
+ let coord: RangedDateTime < _ > = ( start_time..end_time) . into ( ) ;
1278
+ let pos = coord. map ( & mid, ( 1000 , 2000 ) ) ;
1279
+ assert_eq ! ( pos, 1500 ) ;
1280
+ let value = coord. unmap ( pos, ( 1000 , 2000 ) ) ;
1281
+ assert_eq ! ( value, Some ( mid) ) ;
1282
+ }
1283
+
1284
+ #[ test]
1285
+ fn test_datetime_unmap_for_nanoseconds_small_period ( ) {
1286
+ let start_time = Utc . ymd ( 2021 , 1 , 1 ) . and_hms ( 8 , 0 , 0 ) ;
1287
+ let end_time = start_time + Duration :: nanoseconds ( 400 ) ;
1288
+ let coord: RangedDateTime < _ > = ( start_time..end_time) . into ( ) ;
1289
+ let value = coord. unmap ( 2000 , ( 1000 , 2000 ) ) ;
1290
+ assert_eq ! ( value, Some ( end_time) ) ;
1291
+ let mid = start_time + Duration :: nanoseconds ( 200 ) ;
1292
+ let value = coord. unmap ( 500 , ( 0 , 1000 ) ) ;
1293
+ assert_eq ! ( value, Some ( mid) ) ;
1294
+ }
1266
1295
}
0 commit comments