Skip to content

Commit 6bb34ff

Browse files
committed
Fix unmap for small TimeValue periods
1 parent e64880c commit 6bb34ff

File tree

1 file changed

+44
-15
lines changed

1 file changed

+44
-15
lines changed

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

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@ pub trait TimeValue: Eq + Sized {
5656

5757
// Check if nanoseconds fit in i64
5858
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;
6267
return begin.add(&Duration::nanoseconds(nano_seconds));
6368
}
6469
}
@@ -85,7 +90,7 @@ impl TimeValue for NaiveDate {
8590
*self - *other
8691
}
8792
fn add(&self, other: &Duration) -> NaiveDate {
88-
self.clone() + *other
93+
*self + *other
8994
}
9095

9196
fn ymd(&self, year: i32, month: u32, date: u32) -> Self::DateType {
@@ -112,7 +117,7 @@ impl<Z: TimeZone> TimeValue for Date<Z> {
112117
self.clone() - other.clone()
113118
}
114119
fn add(&self, other: &Duration) -> Date<Z> {
115-
self.clone() + other.clone()
120+
self.clone() + *other
116121
}
117122

118123
fn ymd(&self, year: i32, month: u32, date: u32) -> Self::DateType {
@@ -1221,7 +1226,7 @@ mod test {
12211226
let start_time = Utc.ymd(2021, 1, 1).and_hms(8, 0, 0);
12221227
let end_time = Utc.ymd(2023, 1, 1).and_hms(8, 0, 0);
12231228
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();
12251230
let pos = coord.map(&mid, (1000, 2000));
12261231
assert_eq!(pos, 1500);
12271232
let value = coord.unmap(pos, (1000, 2000));
@@ -1230,10 +1235,10 @@ mod test {
12301235

12311236
#[test]
12321237
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();
12371242
let pos = coord.map(&mid, (1000, 2000));
12381243
assert_eq!(pos, 1500);
12391244
let value = coord.unmap(pos, (1000, 2000));
@@ -1245,7 +1250,7 @@ mod test {
12451250
let start_date = Utc.ymd(2021, 1, 1);
12461251
let end_date = Utc.ymd(2023, 1, 1);
12471252
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();
12491254
let pos = coord.map(&mid, (1000, 2000));
12501255
assert_eq!(pos, 1500);
12511256
let value = coord.unmap(pos, (1000, 2000));
@@ -1254,13 +1259,37 @@ mod test {
12541259

12551260
#[test]
12561261
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();
12611266
let pos = coord.map(&mid, (1000, 2000));
12621267
assert_eq!(pos, 1500);
12631268
let value = coord.unmap(pos, (1000, 2000));
12641269
assert_eq!(value, Some(mid));
12651270
}
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+
}
12661295
}

0 commit comments

Comments
 (0)