mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 20:32:48 +00:00
Move ical-related stuff to dedicated rustical_ical crate
This commit is contained in:
19
Cargo.lock
generated
19
Cargo.lock
generated
@@ -3050,6 +3050,7 @@ dependencies = [
|
||||
"quick-xml",
|
||||
"rustical_dav",
|
||||
"rustical_dav_push",
|
||||
"rustical_ical",
|
||||
"rustical_store",
|
||||
"rustical_xml",
|
||||
"serde",
|
||||
@@ -3154,6 +3155,22 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustical_ical"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"derive_more 2.0.1",
|
||||
"ical",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"rustical_xml",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustical_oidc"
|
||||
version = "0.1.0"
|
||||
@@ -3187,6 +3204,7 @@ dependencies = [
|
||||
"rstest",
|
||||
"rstest_reuse",
|
||||
"rustical_dav",
|
||||
"rustical_ical",
|
||||
"rustical_store_sqlite",
|
||||
"rustical_xml",
|
||||
"serde",
|
||||
@@ -3210,6 +3228,7 @@ dependencies = [
|
||||
"password-hash",
|
||||
"pbkdf2",
|
||||
"rand 0.8.5",
|
||||
"rustical_ical",
|
||||
"rustical_store",
|
||||
"serde",
|
||||
"sqlx",
|
||||
|
||||
@@ -100,6 +100,7 @@ rustical_carddav = { path = "./crates/carddav/" }
|
||||
rustical_frontend = { path = "./crates/frontend/" }
|
||||
rustical_xml = { path = "./crates/xml/" }
|
||||
rustical_oidc = { path = "./crates/oidc/" }
|
||||
rustical_ical = { path = "./crates/ical/" }
|
||||
chrono-tz = "0.10"
|
||||
chrono-humanize = "0.2"
|
||||
rand = "0.8"
|
||||
|
||||
@@ -28,3 +28,4 @@ sha2 = { workspace = true }
|
||||
rustical_xml.workspace = true
|
||||
uuid.workspace = true
|
||||
rustical_dav_push.workspace = true
|
||||
rustical_ical.workspace = true
|
||||
|
||||
@@ -3,9 +3,8 @@ use rustical_dav::{
|
||||
resource::Resource,
|
||||
xml::{MultistatusElement, PropfindType},
|
||||
};
|
||||
use rustical_store::{
|
||||
CalendarObject, CalendarStore, auth::User, calendar::UtcDateTime, calendar_store::CalendarQuery,
|
||||
};
|
||||
use rustical_ical::UtcDateTime;
|
||||
use rustical_store::{CalendarObject, CalendarStore, auth::User, calendar_store::CalendarQuery};
|
||||
use rustical_xml::XmlDeserialize;
|
||||
use std::ops::Deref;
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ mod tests {
|
||||
use super::*;
|
||||
use calendar_query::{CompFilterElement, FilterElement, TimeRangeElement};
|
||||
use rustical_dav::xml::{PropElement, PropfindType, Propname};
|
||||
use rustical_store::calendar::UtcDateTime;
|
||||
use rustical_ical::UtcDateTime;
|
||||
use rustical_xml::ValueDeserialize;
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -18,8 +18,8 @@ use rustical_dav::privileges::UserPrivilegeSet;
|
||||
use rustical_dav::resource::{Resource, ResourceService};
|
||||
use rustical_dav::xml::{HrefElement, Resourcetype, ResourcetypeInner};
|
||||
use rustical_dav_push::{DavPushExtension, DavPushExtensionProp};
|
||||
use rustical_ical::CalDateTime;
|
||||
use rustical_store::auth::User;
|
||||
use rustical_store::calendar::CalDateTime;
|
||||
use rustical_store::{Calendar, CalendarStore, SubscriptionStore};
|
||||
use rustical_xml::{EnumUnitVariants, EnumVariants};
|
||||
use rustical_xml::{XmlDeserialize, XmlSerialize};
|
||||
@@ -170,10 +170,10 @@ impl Resource for CalendarResource {
|
||||
self.cal.subscription_url.to_owned().map(HrefElement::from),
|
||||
),
|
||||
CalendarPropName::MinDateTime => {
|
||||
CalendarProp::MinDateTime(CalDateTime::Utc(DateTime::<Utc>::MIN_UTC).format())
|
||||
CalendarProp::MinDateTime(CalDateTime::from(DateTime::<Utc>::MIN_UTC).format())
|
||||
}
|
||||
CalendarPropName::MaxDateTime => {
|
||||
CalendarProp::MaxDateTime(CalDateTime::Utc(DateTime::<Utc>::MAX_UTC).format())
|
||||
CalendarProp::MaxDateTime(CalDateTime::from(DateTime::<Utc>::MAX_UTC).format())
|
||||
}
|
||||
}),
|
||||
CalendarPropWrapperName::SyncToken(prop) => {
|
||||
|
||||
18
crates/ical/Cargo.toml
Normal file
18
crates/ical/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "rustical_ical"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
description.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
chrono.workspace = true
|
||||
chrono-tz.workspace = true
|
||||
thiserror.workspace = true
|
||||
derive_more.workspace = true
|
||||
rustical_xml.workspace = true
|
||||
ical.workspace = true
|
||||
lazy_static.workspace = true
|
||||
regex.workspace = true
|
||||
strum.workspace = true
|
||||
strum_macros.workspace = true
|
||||
9
crates/ical/src/lib.rs
Normal file
9
crates/ical/src/lib.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
pub mod rrule;
|
||||
|
||||
mod property_ext;
|
||||
pub use property_ext::*;
|
||||
|
||||
mod timestamp;
|
||||
mod timezone;
|
||||
pub use timestamp::*;
|
||||
pub use timezone::*;
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::calendar::CalDateTime;
|
||||
use crate::CalDateTime;
|
||||
|
||||
use super::{RecurrenceLimit, RecurrenceRule};
|
||||
|
||||
@@ -7,23 +7,26 @@ impl RecurrenceRule {
|
||||
&self,
|
||||
start: CalDateTime,
|
||||
end: Option<CalDateTime>,
|
||||
) -> impl IntoIterator<Item = CalDateTime> {
|
||||
let start = start.cal_utc();
|
||||
limit: Option<usize>,
|
||||
) -> Vec<CalDateTime> {
|
||||
let start = start;
|
||||
// Terrible code, should clean this up later.
|
||||
let mut end = end.map(|end| CalDateTime::cal_utc(&end));
|
||||
let mut end = end;
|
||||
if let Some(RecurrenceLimit::Until(until)) = &self.limit {
|
||||
let until = until.cal_utc();
|
||||
let mut _end = end.unwrap_or(until.clone());
|
||||
if until.utc() < _end.utc() {
|
||||
_end = until;
|
||||
_end = until.clone();
|
||||
}
|
||||
end = Some(_end);
|
||||
}
|
||||
let count = if let Some(RecurrenceLimit::Count(count)) = &self.limit {
|
||||
let mut count = if let Some(RecurrenceLimit::Count(count)) = &self.limit {
|
||||
*count
|
||||
} else {
|
||||
2048
|
||||
};
|
||||
if let Some(limit) = limit {
|
||||
count = count.min(limit)
|
||||
}
|
||||
|
||||
let mut datetimes = vec![start.clone()];
|
||||
let mut datetime_utc = start.utc();
|
||||
@@ -32,10 +35,22 @@ impl RecurrenceRule {
|
||||
if datetime_utc > end.utc() {
|
||||
break;
|
||||
}
|
||||
datetimes.push(CalDateTime::Utc(datetime_utc));
|
||||
}
|
||||
datetimes.push(datetime_utc.into());
|
||||
}
|
||||
|
||||
datetimes
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{CalDateTime, rrule::RecurrenceRule};
|
||||
|
||||
#[test]
|
||||
fn test_between() {
|
||||
let rrule = RecurrenceRule::parse("FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1").unwrap();
|
||||
let start = CalDateTime::parse("20250516T133000Z", None).unwrap();
|
||||
assert_eq!(rrule.between(start, None, Some(4)), vec![]);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ pub struct RecurrenceRule {
|
||||
pub frequency: RecurrenceFrequency,
|
||||
pub limit: Option<RecurrenceLimit>,
|
||||
// Repeat every n-th time
|
||||
pub interval: Option<usize>,
|
||||
pub interval: usize,
|
||||
|
||||
pub bysecond: Option<Vec<usize>>,
|
||||
pub byminute: Option<Vec<usize>>,
|
||||
@@ -74,7 +74,7 @@ impl RecurrenceRule {
|
||||
pub fn parse(rule: &str) -> Result<Self, ParserError> {
|
||||
let mut frequency = None;
|
||||
let mut limit = None;
|
||||
let mut interval = None;
|
||||
let mut interval = 1;
|
||||
let mut bysecond = None;
|
||||
let mut byminute = None;
|
||||
let mut byhour = None;
|
||||
@@ -98,7 +98,7 @@ impl RecurrenceRule {
|
||||
("UNTIL", val) => {
|
||||
limit = Some(RecurrenceLimit::Until(CalDateTime::parse(val, None)?))
|
||||
}
|
||||
("INTERVAL", val) => interval = Some(val.parse()?),
|
||||
("INTERVAL", val) => interval = val.parse()?,
|
||||
("BYSECOND", val) => {
|
||||
bysecond = Some(
|
||||
val.split(',')
|
||||
@@ -196,7 +196,7 @@ impl RecurrenceRule {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::calendar::{
|
||||
use crate::{
|
||||
CalDateTime,
|
||||
rrule::{RecurrenceFrequency, RecurrenceLimit, Weekday},
|
||||
};
|
||||
@@ -212,7 +212,7 @@ mod tests {
|
||||
limit: Some(RecurrenceLimit::Until(
|
||||
CalDateTime::parse("20250516T133000Z", None).unwrap()
|
||||
)),
|
||||
interval: Some(3),
|
||||
interval: 3,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
@@ -221,7 +221,7 @@ mod tests {
|
||||
RecurrenceRule {
|
||||
frequency: RecurrenceFrequency::Weekly,
|
||||
limit: Some(RecurrenceLimit::Count(4)),
|
||||
interval: Some(2),
|
||||
interval: 2,
|
||||
byday: Some(vec![
|
||||
(None, Weekday::Tu),
|
||||
(None, Weekday::Th),
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::IcalProperty;
|
||||
use crate::IcalProperty;
|
||||
|
||||
use super::timezone::CalTimezone;
|
||||
use chrono::{DateTime, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, Utc};
|
||||
use chrono_tz::Tz;
|
||||
use derive_more::derive::Deref;
|
||||
@@ -65,27 +67,35 @@ impl ValueSerialize for UtcDateTime {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CalDateTime {
|
||||
// Form 1, example: 19980118T230000
|
||||
Local(DateTime<Local>),
|
||||
// Form 2, example: 19980119T070000Z
|
||||
Utc(DateTime<Utc>),
|
||||
// Form 3, example: TZID=America/New_York:19980119T020000
|
||||
// Form 1, example: 19980118T230000 -> Local
|
||||
// Form 2, example: 19980119T070000Z -> UTC
|
||||
// Form 3, example: TZID=America/New_York:19980119T020000 -> Olson
|
||||
// https://en.wikipedia.org/wiki/Tz_database
|
||||
OlsonTZ(DateTime<Tz>),
|
||||
DateTime(DateTime<CalTimezone>),
|
||||
Date(NaiveDate),
|
||||
}
|
||||
|
||||
impl From<DateTime<Local>> for CalDateTime {
|
||||
fn from(value: DateTime<Local>) -> Self {
|
||||
CalDateTime::DateTime(value.with_timezone(&CalTimezone::Local))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DateTime<Utc>> for CalDateTime {
|
||||
fn from(value: DateTime<Utc>) -> Self {
|
||||
CalDateTime::DateTime(value.with_timezone(&CalTimezone::Utc))
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Duration> for CalDateTime {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, duration: Duration) -> Self::Output {
|
||||
match self {
|
||||
Self::Local(datetime) => Self::Local(datetime + duration),
|
||||
Self::Utc(datetime) => Self::Utc(datetime + duration),
|
||||
Self::OlsonTZ(datetime) => Self::OlsonTZ(datetime + duration),
|
||||
Self::Date(date) => Self::Local(
|
||||
Self::DateTime(datetime) => Self::DateTime(datetime + duration),
|
||||
Self::Date(date) => Self::DateTime(
|
||||
date.and_time(NaiveTime::default())
|
||||
.and_local_timezone(Local)
|
||||
.and_local_timezone(CalTimezone::Local)
|
||||
.earliest()
|
||||
.expect("Local timezone has constant offset")
|
||||
+ duration,
|
||||
@@ -142,42 +152,41 @@ impl CalDateTime {
|
||||
|
||||
pub fn format(&self) -> String {
|
||||
match self {
|
||||
Self::Utc(utc) => utc.format(UTC_DATE_TIME).to_string(),
|
||||
Self::DateTime(datetime) => match datetime.timezone() {
|
||||
CalTimezone::Utc => datetime.format(UTC_DATE_TIME).to_string(),
|
||||
_ => datetime.format(LOCAL_DATE_TIME).to_string(),
|
||||
},
|
||||
Self::Date(date) => date.format(LOCAL_DATE).to_string(),
|
||||
Self::Local(datetime) => datetime.format(LOCAL_DATE_TIME).to_string(),
|
||||
Self::OlsonTZ(datetime) => datetime.format(LOCAL_DATE_TIME).to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn date(&self) -> NaiveDate {
|
||||
match self {
|
||||
Self::Utc(utc) => utc.date_naive(),
|
||||
Self::DateTime(datetime) => datetime.date_naive(),
|
||||
Self::Date(date) => date.to_owned(),
|
||||
Self::Local(datetime) => datetime.date_naive(),
|
||||
Self::OlsonTZ(datetime) => datetime.date_naive(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(value: &str, timezone: Option<Tz>) -> Result<Self, CalDateTimeError> {
|
||||
if let Ok(datetime) = NaiveDateTime::parse_from_str(value, LOCAL_DATE_TIME) {
|
||||
if let Some(timezone) = timezone {
|
||||
return Ok(CalDateTime::OlsonTZ(
|
||||
return Ok(CalDateTime::DateTime(
|
||||
datetime
|
||||
.and_local_timezone(timezone)
|
||||
.and_local_timezone(timezone.into())
|
||||
.earliest()
|
||||
.ok_or(CalDateTimeError::LocalTimeGap)?,
|
||||
));
|
||||
}
|
||||
return Ok(CalDateTime::Local(
|
||||
return Ok(CalDateTime::DateTime(
|
||||
datetime
|
||||
.and_local_timezone(chrono::Local)
|
||||
.and_local_timezone(CalTimezone::Local)
|
||||
.earliest()
|
||||
.ok_or(CalDateTimeError::LocalTimeGap)?,
|
||||
));
|
||||
}
|
||||
|
||||
if let Ok(datetime) = NaiveDateTime::parse_from_str(value, UTC_DATE_TIME) {
|
||||
return Ok(CalDateTime::Utc(datetime.and_utc()));
|
||||
return Ok(datetime.and_utc().into());
|
||||
}
|
||||
if let Ok(date) = NaiveDate::parse_from_str(value, LOCAL_DATE) {
|
||||
return Ok(CalDateTime::Date(date));
|
||||
@@ -207,16 +216,10 @@ impl CalDateTime {
|
||||
|
||||
pub fn utc(&self) -> DateTime<Utc> {
|
||||
match &self {
|
||||
CalDateTime::Local(local_datetime) => local_datetime.to_utc(),
|
||||
CalDateTime::Utc(utc_datetime) => utc_datetime.to_owned(),
|
||||
CalDateTime::OlsonTZ(datetime) => datetime.to_utc(),
|
||||
CalDateTime::DateTime(datetime) => datetime.to_utc(),
|
||||
CalDateTime::Date(date) => date.and_time(NaiveTime::default()).and_utc(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cal_utc(&self) -> Self {
|
||||
Self::Utc(self.utc())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CalDateTime> for DateTime<Utc> {
|
||||
@@ -255,6 +258,11 @@ pub fn parse_duration(string: &str) -> Result<Duration, CalDateTimeError> {
|
||||
Ok(duration)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{CalDateTime, parse_duration};
|
||||
use chrono::{Duration, NaiveDate};
|
||||
|
||||
#[test]
|
||||
fn test_parse_duration() {
|
||||
assert_eq!(parse_duration("P12W").unwrap(), Duration::weeks(12));
|
||||
@@ -279,3 +287,4 @@ fn test_vcard_date() {
|
||||
CalDateTime::Date(NaiveDate::from_ymd_opt(1972, 4, 12).unwrap())
|
||||
);
|
||||
}
|
||||
}
|
||||
86
crates/ical/src/timezone.rs
Normal file
86
crates/ical/src/timezone.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
use chrono::{Local, NaiveDate, NaiveDateTime, TimeZone, Utc};
|
||||
use chrono_tz::Tz;
|
||||
use derive_more::{Display, From};
|
||||
|
||||
#[derive(Debug, Clone, From)]
|
||||
pub enum CalTimezone {
|
||||
Local,
|
||||
Utc,
|
||||
Olson(Tz),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Display)]
|
||||
pub enum CalTimezoneOffset {
|
||||
Local(chrono::FixedOffset),
|
||||
Utc(chrono::Utc),
|
||||
Olson(chrono_tz::TzOffset),
|
||||
}
|
||||
|
||||
impl chrono::Offset for CalTimezoneOffset {
|
||||
fn fix(&self) -> chrono::FixedOffset {
|
||||
match self {
|
||||
Self::Local(local) => local.fix(),
|
||||
Self::Utc(utc) => utc.fix(),
|
||||
Self::Olson(olson) => olson.fix(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeZone for CalTimezone {
|
||||
type Offset = CalTimezoneOffset;
|
||||
|
||||
fn from_offset(offset: &Self::Offset) -> Self {
|
||||
match offset {
|
||||
CalTimezoneOffset::Local(_) => Self::Local,
|
||||
CalTimezoneOffset::Utc(_) => Self::Utc,
|
||||
CalTimezoneOffset::Olson(offset) => Self::Olson(Tz::from_offset(offset)),
|
||||
}
|
||||
}
|
||||
|
||||
fn offset_from_local_date(&self, local: &NaiveDate) -> chrono::MappedLocalTime<Self::Offset> {
|
||||
match self {
|
||||
Self::Local => Local
|
||||
.offset_from_local_date(local)
|
||||
.map(CalTimezoneOffset::Local),
|
||||
Self::Utc => Utc
|
||||
.offset_from_local_date(local)
|
||||
.map(CalTimezoneOffset::Utc),
|
||||
Self::Olson(tz) => tz
|
||||
.offset_from_local_date(local)
|
||||
.map(CalTimezoneOffset::Olson),
|
||||
}
|
||||
}
|
||||
|
||||
fn offset_from_local_datetime(
|
||||
&self,
|
||||
local: &NaiveDateTime,
|
||||
) -> chrono::MappedLocalTime<Self::Offset> {
|
||||
match self {
|
||||
Self::Local => Local
|
||||
.offset_from_local_datetime(local)
|
||||
.map(CalTimezoneOffset::Local),
|
||||
Self::Utc => Utc
|
||||
.offset_from_local_datetime(local)
|
||||
.map(CalTimezoneOffset::Utc),
|
||||
Self::Olson(tz) => tz
|
||||
.offset_from_local_datetime(local)
|
||||
.map(CalTimezoneOffset::Olson),
|
||||
}
|
||||
}
|
||||
|
||||
fn offset_from_utc_datetime(&self, utc: &NaiveDateTime) -> Self::Offset {
|
||||
match self {
|
||||
Self::Local => CalTimezoneOffset::Local(Local.offset_from_utc_datetime(utc)),
|
||||
Self::Utc => CalTimezoneOffset::Utc(Utc.offset_from_utc_datetime(utc)),
|
||||
Self::Olson(tz) => CalTimezoneOffset::Olson(tz.offset_from_utc_datetime(utc)),
|
||||
}
|
||||
}
|
||||
|
||||
fn offset_from_utc_date(&self, utc: &NaiveDate) -> Self::Offset {
|
||||
match self {
|
||||
Self::Local => CalTimezoneOffset::Local(Local.offset_from_utc_date(utc)),
|
||||
Self::Utc => CalTimezoneOffset::Utc(Utc.offset_from_utc_date(utc)),
|
||||
Self::Olson(tz) => CalTimezoneOffset::Olson(tz.offset_from_utc_date(utc)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ clap.workspace = true
|
||||
rustical_dav.workspace = true
|
||||
strum.workspace = true
|
||||
strum_macros.workspace = true
|
||||
rustical_ical.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
rstest = { workspace = true }
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use std::{collections::HashMap, io::BufReader};
|
||||
|
||||
use crate::{
|
||||
calendar::{CalDateTime, LOCAL_DATE},
|
||||
CalendarObject, Error,
|
||||
};
|
||||
use crate::{CalendarObject, Error};
|
||||
use chrono::Datelike;
|
||||
use ical::parser::{
|
||||
vcard::{self, component::VcardContact},
|
||||
Component,
|
||||
vcard::{self, component::VcardContact},
|
||||
};
|
||||
use rustical_ical::{CalDateTime, LOCAL_DATE};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::{collections::HashMap, io::BufReader};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AddressObject {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use super::{
|
||||
CalDateTime, parse_duration,
|
||||
rrule::{ParserError, RecurrenceRule},
|
||||
};
|
||||
use crate::{Error, calendar::ComponentMut};
|
||||
use crate::Error;
|
||||
use chrono::Duration;
|
||||
use ical::{
|
||||
generator::IcalEvent,
|
||||
parser::{Component, ical::component::IcalTimeZone},
|
||||
property::Property,
|
||||
};
|
||||
use rustical_ical::{
|
||||
CalDateTime, ComponentMut, parse_duration,
|
||||
rrule::{ParserError, RecurrenceRule},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -71,10 +71,10 @@ impl EventObject {
|
||||
if let Some(rrule) = self.recurrence_rule()? {
|
||||
let mut events = vec![];
|
||||
let first_occurence = self.get_first_occurence()?.unwrap();
|
||||
let dates = rrule.between(first_occurence, None);
|
||||
let dates = rrule.between(first_occurence, None, None);
|
||||
|
||||
for date in dates {
|
||||
let dtstart_utc = date.cal_utc();
|
||||
let dtstart_utc = date;
|
||||
let mut ev = self.event.clone();
|
||||
ev.remove_property("RRULE");
|
||||
ev.set_property(Property {
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
mod calendar;
|
||||
mod event;
|
||||
mod ical;
|
||||
mod journal;
|
||||
mod object;
|
||||
pub mod rrule;
|
||||
mod timestamp;
|
||||
mod todo;
|
||||
|
||||
pub use calendar::*;
|
||||
pub use event::*;
|
||||
pub use ical::*;
|
||||
pub use journal::*;
|
||||
pub use object::*;
|
||||
pub use timestamp::*;
|
||||
pub use todo::*;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{CalDateTime, EventObject, JournalObject, TodoObject};
|
||||
use super::{EventObject, JournalObject, TodoObject};
|
||||
use crate::Error;
|
||||
use ical::{
|
||||
generator::{Emitter, IcalCalendar},
|
||||
parser::{Component, ical::component::IcalTimeZone},
|
||||
};
|
||||
use rustical_ical::CalDateTime;
|
||||
use serde::Serialize;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::{collections::HashMap, io::BufReader};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use actix_web::{ResponseError, http::StatusCode};
|
||||
|
||||
use crate::calendar::CalDateTimeError;
|
||||
use rustical_ical::CalDateTimeError;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
@@ -14,7 +13,7 @@ pub enum Error {
|
||||
InvalidData(String),
|
||||
|
||||
#[error(transparent)]
|
||||
RRuleParserError(#[from] crate::calendar::rrule::ParserError),
|
||||
RRuleParserError(#[from] rustical_ical::rrule::ParserError),
|
||||
|
||||
#[error("Read-only")]
|
||||
ReadOnly,
|
||||
|
||||
@@ -21,3 +21,4 @@ password-hash.workspace = true
|
||||
uuid.workspace = true
|
||||
rand.workspace = true
|
||||
pbkdf2.workspace = true
|
||||
rustical_ical.workspace = true
|
||||
|
||||
@@ -2,7 +2,8 @@ use super::ChangeOperation;
|
||||
use async_trait::async_trait;
|
||||
use chrono::TimeDelta;
|
||||
use derive_more::derive::Constructor;
|
||||
use rustical_store::calendar::{CalDateTime, CalendarObjectType};
|
||||
use rustical_ical::CalDateTime;
|
||||
use rustical_store::calendar::CalendarObjectType;
|
||||
use rustical_store::calendar_store::CalendarQuery;
|
||||
use rustical_store::synctoken::format_synctoken;
|
||||
use rustical_store::{Calendar, CalendarObject, CalendarStore, Error};
|
||||
|
||||
Reference in New Issue
Block a user