Fix Calendar: No expanded occurrences are returned for a daily recurrences crossing DST
This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use super::{Alarm, AlarmDelta, ArchivedAlarmDelta, ArchivedCalendarEventData};
|
||||
use super::{
|
||||
Alarm, AlarmDelta, ArchivedAlarmDelta, ArchivedCalendarEventData, expand::resolve_local,
|
||||
};
|
||||
use calcard::{
|
||||
common::timezone::Tz,
|
||||
icalendar::{
|
||||
@@ -12,7 +14,6 @@ use calcard::{
|
||||
ICalendarRelated, ICalendarValue,
|
||||
},
|
||||
};
|
||||
use chrono::{DateTime, TimeZone};
|
||||
use std::str::FromStr;
|
||||
use store::write::bitpack::BitpackIterator;
|
||||
use utils::codec::leb128::Leb128Reader;
|
||||
@@ -74,18 +75,12 @@ impl ArchivedCalendarEventData {
|
||||
for start_offset in unpacker {
|
||||
let start_date_naive = start_offset as i64 + base_offset;
|
||||
let end_date_naive = start_date_naive + duration;
|
||||
let start = start_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(start_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let end = end_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(end_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let (Some(start), Some(end)) = (
|
||||
resolve_local(start_tz, start_date_naive),
|
||||
resolve_local(end_tz, end_date_naive),
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(alarm_time) = alarm.delta.to_timestamp(start, end, default_tz)
|
||||
&& alarm_time > start_time
|
||||
@@ -124,18 +119,12 @@ impl ArchivedCalendarEventData {
|
||||
// Single event
|
||||
let start_date_naive = offset_or_count as i64 + base_offset;
|
||||
let end_date_naive = start_date_naive + duration;
|
||||
let start = start_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(start_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let end = end_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(end_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let (Some(start), Some(end)) = (
|
||||
resolve_local(start_tz, start_date_naive),
|
||||
resolve_local(end_tz, end_date_naive),
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(alarm_time) = alarm.delta.to_timestamp(start, end, default_tz)
|
||||
&& alarm_time > start_time
|
||||
@@ -265,10 +254,7 @@ impl AlarmDelta {
|
||||
AlarmDelta::Start(delta) => Some(start + delta),
|
||||
AlarmDelta::End(delta) => Some(end + delta),
|
||||
AlarmDelta::FixedUtc(timestamp) => Some(*timestamp),
|
||||
AlarmDelta::FixedFloating(timestamp) => default_tz
|
||||
.from_local_datetime(&DateTime::from_timestamp(*timestamp, 0)?.naive_local())
|
||||
.single()
|
||||
.map(|dt| dt.timestamp()),
|
||||
AlarmDelta::FixedFloating(timestamp) => resolve_local(default_tz, *timestamp),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,12 +265,9 @@ impl ArchivedAlarmDelta {
|
||||
ArchivedAlarmDelta::Start(delta) => Some(start + delta.to_native()),
|
||||
ArchivedAlarmDelta::End(delta) => Some(end + delta.to_native()),
|
||||
ArchivedAlarmDelta::FixedUtc(timestamp) => Some(timestamp.to_native()),
|
||||
ArchivedAlarmDelta::FixedFloating(timestamp) => default_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(timestamp.to_native(), 0)?.naive_local(),
|
||||
)
|
||||
.single()
|
||||
.map(|dt| dt.timestamp()),
|
||||
ArchivedAlarmDelta::FixedFloating(timestamp) => {
|
||||
resolve_local(default_tz, timestamp.to_native())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,18 +55,13 @@ impl ArchivedCalendarEventData {
|
||||
for start_offset in unpacker {
|
||||
let start_date_naive = start_offset as i64 + base_offset;
|
||||
let end_date_naive = start_date_naive + duration;
|
||||
let start = start_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(start_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let end = end_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(end_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let (Some(start), Some(end)) = (
|
||||
resolve_local(start_tz, start_date_naive),
|
||||
resolve_local(end_tz, end_date_naive),
|
||||
) else {
|
||||
expansion_id += 1;
|
||||
continue;
|
||||
};
|
||||
|
||||
if limit.is_in_range(is_todo, start, end) {
|
||||
expansion.push(CalendarEventExpansion {
|
||||
@@ -85,20 +80,11 @@ impl ArchivedCalendarEventData {
|
||||
// Single event
|
||||
let start_date_naive = offset_or_count as i64 + base_offset;
|
||||
let end_date_naive = start_date_naive + duration;
|
||||
let start = start_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(start_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let end = end_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(end_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
|
||||
if limit.is_in_range(is_todo, start, end) {
|
||||
if let (Some(start), Some(end)) = (
|
||||
resolve_local(start_tz, start_date_naive),
|
||||
resolve_local(end_tz, end_date_naive),
|
||||
) && limit.is_in_range(is_todo, start, end)
|
||||
{
|
||||
expansion.push(CalendarEventExpansion {
|
||||
comp_id,
|
||||
expansion_id: base_expansion_id,
|
||||
@@ -157,25 +143,17 @@ impl CalendarEventData {
|
||||
if expansion_ids.remove(&expansion_id) {
|
||||
let start_date_naive = start_offset as i64 + base_offset;
|
||||
let end_date_naive = start_date_naive + range.duration as i64;
|
||||
let start = start_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(start_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let end = end_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(end_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
|
||||
expansion.push(CalendarEventExpansion {
|
||||
comp_id: range.id as u32,
|
||||
expansion_id,
|
||||
start,
|
||||
end,
|
||||
});
|
||||
if let (Some(start), Some(end)) = (
|
||||
resolve_local(start_tz, start_date_naive),
|
||||
resolve_local(end_tz, end_date_naive),
|
||||
) {
|
||||
expansion.push(CalendarEventExpansion {
|
||||
comp_id: range.id as u32,
|
||||
expansion_id,
|
||||
start,
|
||||
end,
|
||||
});
|
||||
}
|
||||
|
||||
match_count -= 1;
|
||||
if match_count == 0 {
|
||||
@@ -194,25 +172,17 @@ impl CalendarEventData {
|
||||
// Single event
|
||||
let start_date_naive = offset_or_count as i64 + base_offset;
|
||||
let end_date_naive = start_date_naive + range.duration as i64;
|
||||
let start = start_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(start_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
let end = end_tz
|
||||
.from_local_datetime(
|
||||
&DateTime::from_timestamp(end_date_naive, 0)?.naive_local(),
|
||||
)
|
||||
.single()?
|
||||
.timestamp();
|
||||
|
||||
expansion.push(CalendarEventExpansion {
|
||||
comp_id: range.id as u32,
|
||||
expansion_id: base_expansion_id,
|
||||
start,
|
||||
end,
|
||||
});
|
||||
if let (Some(start), Some(end)) = (
|
||||
resolve_local(start_tz, start_date_naive),
|
||||
resolve_local(end_tz, end_date_naive),
|
||||
) {
|
||||
expansion.push(CalendarEventExpansion {
|
||||
comp_id: range.id as u32,
|
||||
expansion_id: base_expansion_id,
|
||||
start,
|
||||
end,
|
||||
});
|
||||
}
|
||||
|
||||
if expansion_ids.is_empty() {
|
||||
break 'outer;
|
||||
@@ -263,14 +233,8 @@ impl CalendarEventData {
|
||||
};
|
||||
let start_date_naive = start_offset as i64 + self.base_offset;
|
||||
let end_date_naive = start_date_naive + range.duration as i64;
|
||||
let start = start_tz
|
||||
.from_local_datetime(&DateTime::from_timestamp(start_date_naive, 0)?.naive_local())
|
||||
.single()?
|
||||
.timestamp();
|
||||
let end = end_tz
|
||||
.from_local_datetime(&DateTime::from_timestamp(end_date_naive, 0)?.naive_local())
|
||||
.single()?
|
||||
.timestamp();
|
||||
let start = resolve_local(start_tz, start_date_naive)?;
|
||||
let end = resolve_local(end_tz, end_date_naive)?;
|
||||
|
||||
Some(CalendarEventExpansion {
|
||||
comp_id,
|
||||
@@ -297,3 +261,9 @@ impl CalendarEventExpansion {
|
||||
self.comp_id != u32::MAX && self.start != i64::MAX && self.end != i64::MAX
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_local(tz: Tz, naive_secs: i64) -> Option<i64> {
|
||||
tz.from_local_datetime(&DateTime::from_timestamp(naive_secs, 0)?.naive_local())
|
||||
.earliest()
|
||||
.map(|dt| dt.timestamp())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user