mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-02-01 08:17:58 +00:00
Fix metrics per day interval calculation.
This fixes the issue where after a from DST to non-DST, the timstamp was not incremented by a full day. As the ts was then truncated to day precision, this would create a never ending loop. Example, incrementing 2022-10-30 00:00:00 by days(1) would result in 2022-10-30 23:00:00, trucated to day precision would result in 2022-10-30 00:00:00. If the date (30) is the same after incrementing by days(1), we increment by days(2), which in the above example results in 2022-10-31 23:00:00, truncated to day precision results in 2022-10-31 00:00:00 which is the desired result.
This commit is contained in:
parent
42d6f62509
commit
6b1cf4f8ba
@ -214,8 +214,18 @@ pub async fn get(
|
||||
while ts.le(&end) {
|
||||
timestamps.push(ts);
|
||||
keys.push(get_key(name, a, ts));
|
||||
// Make sure that the timestamp stays at midnight at daylight saving change.
|
||||
ts = (ts + ChronoDuration::days(1)).date().and_hms(0, 0, 0);
|
||||
ts = {
|
||||
if (ts + ChronoDuration::days(1)).day() == ts.day() {
|
||||
// In case of DST to non-DST transition, the ts is incremented with less
|
||||
// than 24h and we end up with the same day. Therefore we increment by two
|
||||
// days.
|
||||
(ts + ChronoDuration::days(2)).date().and_hms(0, 0, 0)
|
||||
} else {
|
||||
// Make sure that the timestamp stays at midnight in case of non-DST to DST
|
||||
// change.
|
||||
(ts + ChronoDuration::days(1)).date().and_hms(0, 0, 0)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Aggregation::MONTH => {
|
||||
@ -431,6 +441,75 @@ pub mod test {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_day_dst_transition() {
|
||||
let _guard = test::prepare().await;
|
||||
|
||||
let records = vec![
|
||||
Record {
|
||||
time: Local.ymd(2022, 10, 30).and_hms(1, 0, 0),
|
||||
kind: Kind::ABSOLUTE,
|
||||
metrics: [("foo".into(), 1f64), ("bar".into(), 2f64)]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect(),
|
||||
},
|
||||
Record {
|
||||
time: Local.ymd(2022, 10, 30).and_hms(5, 0, 0),
|
||||
kind: Kind::ABSOLUTE,
|
||||
metrics: [("foo".into(), 3f64), ("bar".into(), 4f64)]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect(),
|
||||
},
|
||||
Record {
|
||||
time: Local.ymd(2022, 10, 31).and_hms(1, 0, 0),
|
||||
kind: Kind::ABSOLUTE,
|
||||
metrics: [("foo".into(), 5f64), ("bar".into(), 6f64)]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect(),
|
||||
},
|
||||
];
|
||||
for r in &records {
|
||||
save_for_interval(Aggregation::DAY, "test", r)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let resp = get(
|
||||
"test",
|
||||
Kind::ABSOLUTE,
|
||||
Aggregation::DAY,
|
||||
Local.ymd(2022, 10, 30).and_hms(1, 0, 0),
|
||||
Local.ymd(2022, 10, 31).and_hms(1, 0, 0),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
vec![
|
||||
Record {
|
||||
time: Local.ymd(2022, 10, 30).and_hms(0, 0, 0),
|
||||
kind: Kind::ABSOLUTE,
|
||||
metrics: [("foo".into(), 4f64), ("bar".into(), 6f64)]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect(),
|
||||
},
|
||||
Record {
|
||||
time: Local.ymd(2022, 10, 31).and_hms(0, 0, 0),
|
||||
kind: Kind::ABSOLUTE,
|
||||
metrics: [("foo".into(), 5f64), ("bar".into(), 6f64)]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect(),
|
||||
}
|
||||
],
|
||||
resp
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_month() {
|
||||
let _guard = test::prepare().await;
|
||||
|
Loading…
x
Reference in New Issue
Block a user