Browse Source

avoid filename collision for recurring events

Fabian Peter Hammerle 4 years ago
parent
commit
caef0aae18
1 changed files with 23 additions and 1 deletions
  1. 23 1
      ics2vdir/__init__.py

+ 23 - 1
ics2vdir/__init__.py

@@ -16,6 +16,7 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import argparse
+import datetime
 import logging
 import os
 import pathlib
@@ -59,11 +60,31 @@ def _events_equal(event_a: icalendar.cal.Event, event_b: icalendar.cal.Event) ->
     return True
 
 
+def _datetime_basic_isoformat(dt_obj: datetime.datetime) -> str:
+    # .isoformat() inserts unwanted separators
+    return dt_obj.strftime("%Y%m%dT%H%M%S%z")
+
+
+def _event_vdir_filename(event: icalendar.cal.Event) -> str:
+    # > An item should contain a UID property as described by the vCard and iCalendar standards.
+    # > [...] The filename should have similar properties as the UID of the file content.
+    # > However, there is no requirement for these two to be the same.
+    # > Programs may choose to store additional metadata in that filename, [...]
+    # https://vdirsyncer.readthedocs.io/en/stable/vdir.html#basic-structure
+    output_filename = str(event["UID"])
+    if "RECURRENCE-ID" in event:
+        recurrence_id = event["RECURRENCE-ID"]
+        assert isinstance(recurrence_id.dt, datetime.datetime), recurrence_id.dt
+
+        output_filename += "." + _datetime_basic_isoformat(recurrence_id.dt)
+    return output_filename + ".ics"
+
+
 def _export_event(event: icalendar.cal.Event, output_dir_path: pathlib.Path) -> None:
     temp_fd, temp_path = tempfile.mkstemp(prefix="ics2vdir-", suffix=".ics")
     os.write(temp_fd, event.to_ical())
     os.close(temp_fd)
-    output_path = output_dir_path.joinpath("{}.ics".format(event["UID"]))
+    output_path = output_dir_path.joinpath(_event_vdir_filename(event))
     if not output_path.exists():
         _LOGGER.info("creating %s", output_path)
         os.rename(temp_path, output_path)
@@ -81,6 +102,7 @@ def _main():
     logging.basicConfig(
         format="%(message)s",
         # datefmt='%Y-%m-%dT%H:%M:%S%z',
+        # level=logging.DEBUG,
         level=logging.INFO,
     )
     argparser = argparse.ArgumentParser(