mirror of
https://github.com/Kozea/Radicale.git
synced 2025-09-03 20:00:56 +00:00
commit
19954f162a
5 changed files with 62 additions and 2 deletions
|
@ -15,6 +15,7 @@
|
||||||
* Add: [hook] dryrun: option to disable real hook action for testing, add tests for email+rabbitmq
|
* Add: [hook] dryrun: option to disable real hook action for testing, add tests for email+rabbitmq
|
||||||
* Fix: storage hook path now added to DELETE, MKCOL, MKCALENDAR, MOVE, and PROPPATCH
|
* Fix: storage hook path now added to DELETE, MKCOL, MKCALENDAR, MOVE, and PROPPATCH
|
||||||
* Add: storage hook placeholder now supports "request" and "to_path" (MOVE only)
|
* Add: storage hook placeholder now supports "request" and "to_path" (MOVE only)
|
||||||
|
* Improve: catch items having tzinfo only on dtstart or dtend set for whatever reason, overtake tzinfo from the other one
|
||||||
|
|
||||||
## 3.5.4
|
## 3.5.4
|
||||||
* Improve: item filter enhanced for 3rd level supporting VALARM and honoring TRIGGER (offset or absolute)
|
* Improve: item filter enhanced for 3rd level supporting VALARM and honoring TRIGGER (offset or absolute)
|
||||||
|
|
|
@ -47,7 +47,7 @@ else:
|
||||||
TRIGGER = datetime | None
|
TRIGGER = datetime | None
|
||||||
|
|
||||||
|
|
||||||
def date_to_datetime(d: date) -> datetime:
|
def date_to_datetime(d: date, tzinfo=vobject.icalendar.utc) -> datetime:
|
||||||
"""Transform any date to a UTC datetime.
|
"""Transform any date to a UTC datetime.
|
||||||
|
|
||||||
If ``d`` is a datetime without timezone, return as UTC datetime. If ``d``
|
If ``d`` is a datetime without timezone, return as UTC datetime. If ``d``
|
||||||
|
@ -58,7 +58,7 @@ def date_to_datetime(d: date) -> datetime:
|
||||||
d = datetime.combine(d, datetime.min.time())
|
d = datetime.combine(d, datetime.min.time())
|
||||||
if not d.tzinfo:
|
if not d.tzinfo:
|
||||||
# NOTE: using vobject's UTC as it wasn't playing well with datetime's.
|
# NOTE: using vobject's UTC as it wasn't playing well with datetime's.
|
||||||
d = d.replace(tzinfo=vobject.icalendar.utc)
|
d = d.replace(tzinfo=tzinfo)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
@ -366,6 +366,21 @@ def visit_time_ranges(vobject_item: vobject.base.Component, child_name: str,
|
||||||
dtend = getattr(child, "dtend", None)
|
dtend = getattr(child, "dtend", None)
|
||||||
if dtend is not None:
|
if dtend is not None:
|
||||||
dtend = dtend.value
|
dtend = dtend.value
|
||||||
|
|
||||||
|
# Ensure that both datetime.datetime objects have a timezone or
|
||||||
|
# both do not have one before doing calculations. This is required
|
||||||
|
# as the library does not support performing mathematical operations
|
||||||
|
# on timezone-aware and timezone-naive objects. See #1847
|
||||||
|
if hasattr(dtstart, 'tzinfo') and hasattr(dtend, 'tzinfo'):
|
||||||
|
if dtstart.tzinfo is None and dtend.tzinfo is not None:
|
||||||
|
dtstart_orig = dtstart
|
||||||
|
dtstart = date_to_datetime(dtstart, dtend.astimezone().tzinfo)
|
||||||
|
logger.debug("TRACE/ITEM/FILTER/get_children: overtake missing tzinfo on dtstart from dtend: '%s' -> '%s'", dtstart_orig, dtstart)
|
||||||
|
elif dtstart.tzinfo is not None and dtend.tzinfo is None:
|
||||||
|
dtend_orig = dtend
|
||||||
|
dtend = date_to_datetime(dtend, dtstart.astimezone().tzinfo)
|
||||||
|
logger.debug("TRACE/ITEM/FILTER/get_children: overtake missing tzinfo on dtend from dtstart: '%s' -> '%s'", dtend_orig, dtend)
|
||||||
|
|
||||||
original_duration = (dtend - dtstart).total_seconds()
|
original_duration = (dtend - dtstart).total_seconds()
|
||||||
dtend = date_to_datetime(dtend)
|
dtend = date_to_datetime(dtend)
|
||||||
|
|
||||||
|
|
14
radicale/tests/static/event_issue1847_1.ics
Normal file
14
radicale/tests/static/event_issue1847_1.ics
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
PRODID:-//algoo.fr//NONSGML Open Calendar v0.9//EN
|
||||||
|
BEGIN:VEVENT
|
||||||
|
CREATED:20250814T153429Z
|
||||||
|
LAST-MODIFIED:20250814T153503Z
|
||||||
|
DTSTAMP:20250814T153503Z
|
||||||
|
UID:f91964cb-53ca-4942-8811-c38f076f4328
|
||||||
|
SUMMARY:error
|
||||||
|
DTSTART:20250814T180000
|
||||||
|
DTEND;TZID=Europe/Brussels:20250814T190000
|
||||||
|
TRANSP:OPAQUE
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
14
radicale/tests/static/event_issue1847_2.ics
Normal file
14
radicale/tests/static/event_issue1847_2.ics
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
PRODID:-//algoo.fr//NONSGML Open Calendar v0.9//EN
|
||||||
|
BEGIN:VEVENT
|
||||||
|
CREATED:20250814T153429Z
|
||||||
|
LAST-MODIFIED:20250814T153503Z
|
||||||
|
DTSTAMP:20250814T153503Z
|
||||||
|
UID:f91964cb-53ca-4942-8811-c38f076f4328
|
||||||
|
SUMMARY:error
|
||||||
|
DTSTART;TZID=Europe/Brussels:20250814T180000
|
||||||
|
DTEND:20250814T190000
|
||||||
|
TRANSP:OPAQUE
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
|
@ -306,6 +306,22 @@ permissions: RrWw""")
|
||||||
for uid2 in uids[i + 1:]:
|
for uid2 in uids[i + 1:]:
|
||||||
assert uid1 != uid2
|
assert uid1 != uid2
|
||||||
|
|
||||||
|
def test_add_event_tz_dtend_only(self) -> None:
|
||||||
|
"""Add an event having TZ only on DTEND."""
|
||||||
|
self.mkcalendar("/calendar.ics/")
|
||||||
|
event = get_file_content("event_issue1847_1.ics")
|
||||||
|
path = "/calendar.ics/event_issue1847_1.ics"
|
||||||
|
self.put(path, event)
|
||||||
|
_, headers, answer = self.request("GET", path, check=200)
|
||||||
|
|
||||||
|
def test_add_event_tz_dtstart_only(self) -> None:
|
||||||
|
"""Add an event having TZ only on DTSTART."""
|
||||||
|
self.mkcalendar("/calendar.ics/")
|
||||||
|
event = get_file_content("event_issue1847_2.ics")
|
||||||
|
path = "/calendar.ics/event_issue1847_2.ics"
|
||||||
|
self.put(path, event)
|
||||||
|
_, headers, answer = self.request("GET", path, check=200)
|
||||||
|
|
||||||
def test_verify(self) -> None:
|
def test_verify(self) -> None:
|
||||||
"""Verify the storage."""
|
"""Verify the storage."""
|
||||||
contacts = get_file_content("contact_multiple.vcf")
|
contacts = get_file_content("contact_multiple.vcf")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue