Giter Site home page Giter Site logo

ical2org.py's Introduction

ical2orgpy

This script converts an ical calendar (for instance, as exported from google calendar) into an org-mode document. It is conceived as a replacement of the awk script located here:

http://orgmode.org/worg/org-tutorials/org-google-sync.html

The main difference is that ical2orgpy correctly manages recurring events of "yearly", "daily" and "weekly" types. ical2orgpy duplicates all recurring events falling into a specified time-frame into the exported org-document.

Installation

The command ical2orgpy is provided by means of python package ical2orgpy.

You can install with pip (preferably into its own into virtualenv):

$ pip install ical2orgpy

Installation with pipx is recommended because this will manage the virtualenv for you.

Installing from source code

You can install the package directly from git source like this:

$ cd <to project folder>
$ pip install --user .

To use the script, just call:

$ ~/.local/bin/ical2orgpy

Usage

Simply use the ical2orgpy command:

$ ical2orgpy --help

or, if installed locally from the git repo:

$ ~/.local/bin/ical2orgpy --help

The script requires two files, the input ics and the output org document. Usually, ical2orgpy is called within a script that grabs the ical file from some source (i.e. Google Calendar), and generates the appropriate org document. Such an script would have the following shape:

#!/bin/bash

# customize these
WGET=<path to wget>
ICS2ORG=<path to ical2org>
ICSFILE=$(mktemp)
ORGFILE=<path to orgfile>
URL=<url to your private Google calendar>

# no customization needed below

$WGET -O $ICSFILE $URL
$ICS2ORG $ICSFILE $ORGFILE
rm -f $ICSFILE

See further instructions here:

http://orgmode.org/worg/org-tutorials/org-google-sync.html

Development

Clone the repository and cd into it.

Create a virtualenv and install dependencies:

$ pip install .
$ pip install -r test_requirements.txt

Run tests to check everything is working:

$ pytest

You can also use tox to create the virtualenv e.g.:

$ tox -e py39

Then activate the virtualenv:

$ source .tox/py39/bin/activate
(py39)$

And use the package.

ical2org.py's People

Contributors

asoroa avatar binshengliu avatar joonro avatar olberger avatar sje30 avatar spookylukey avatar tim3z avatar titan-c avatar vlcinsky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ical2org.py's Issues

All-day event is created as incorrect date range

I tried to convert an ICS file with the German bank holidays to org. I have the ical file from here:

https://www.feiertage-deutschland.de/content/kalender-download/force-download.php

The following event

BEGIN:VEVENT
UID:[email protected]
DTSTAMP:20230513T104258Z
LOCATION:Alle Bundesländer
DESCRIPTION:Christi Himmelfahrt ist ganz Deutschland ein gesetzlicher Feiertag
URL;VALUE=URI:https://www.feiertage-deutschland.de/christi-himmelfahrt/
SUMMARY:Christi Himmelfahrt (§)
DTSTART;VALUE=DATE:20230518
END:VEVENT

gets converted to an incorrect date range:

* Christi Himmelfahrt (§) - Alle Bundesländer
  <2023-05-18 Thu>--<2023-05-17 Wed>
Christi Himmelfahrt ist ganz Deutschland ein gesetzlicher Feiertag

All other events have the same issue.

Handle events with RECURRENCE-ID

When you edit an event of series of recurring events, Thunderbird will leave the original event untouched but instead generate a separate, non-recurring (?) VEVENT with the same UID and a property RECURRENCE-ID that specifies which event in the series it replaces. From what I see in my calendar export, this event should then replace the original event. See also here for a more detailed discussion. Currently, in the import, I get both the original event of the series and the changed event. To fix this, ical2org.py would probably need to group events by UID, look for a property "RECURRENCE-ID" and then remove these occurrences in the main event that specifies the recurring event. The link suggests this might be more complicated though. Nevertheless, even a simple handling could already be an improvement.

RRULE events with COUNT

Here is an example snippet of an entry created by google calendar, where the start date and number of repeats is given:

BEGIN:VEVENT
DTSTART;TZID=Europe/London:20130919T154500
DTEND;TZID=Europe/London:20130919T164500
RRULE:FREQ=WEEKLY;COUNT=12;BYDAY=TH

COUNT is not recognised yet by the script, and so this repeats until end_utc

License

It would be great to specify the license under which is this tool provided.

List of throve specifiers for python packages offer bunch of options, short list (many licenses omitted) could be as follows (first two are my favorite ones):

  • OSI Approved :: MIT License
  • OSI Approved :: BSD License
  • OSI Approved :: GNU General Public License (GPL)
  • OSI Approved :: GNU General Public License v2 (GPLv2)
  • OSI Approved :: GNU General Public License v2 or later (GPLv2+)
  • OSI Approved :: GNU General Public License v3 (GPLv3)
  • OSI Approved :: GNU General Public License v3 or later (GPLv3+)
  • OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)
  • OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
  • OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
  • OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
  • OSI Approved :: GNU Library or Lesser General Public License (LGPL)

For more see https://choosealicense.com/

Include description

It would be great if ical2org.py also inserts descriptions of the calendar items to org files.

Simplified installation

Current installation has issues such as need to install it into global python interpreter or in case of installation into virtualenv it has broken shebang pointing to global python version.

The solution may be to:

  • make the script proper python package
  • name the package e.g. ical2orgpy (as ical2org is already taken by another tool, working just on Macs)
  • the package would create command ical2orgpy

The package would:

  • include tox.ini for testing (with python 2.7, 3.4+)
  • setup.py
  • other source code

I am installing the packages this way (on Linux):
Assume python and tox are installed.

$ sudo su
# cd /opt
# mkdir ical2orgpy
# cd ical2orgpy
# tox-quickstart
....

Finally the tox.ini looks like:

[tox]
envlist = py35 # use the version which is supported on both system and by the package
skipsdist = True

[testenv]
deps = ical2orgpy

Then continue with installing the script into virtualenv:

# tox

The script shall be now at /opt/ical2orgpy/.tox/py35/bin/ical2orgpy and it shall have all required dependencies available there.

Final step is to make it globally visible, e.g. by symlinking to /usr/local/bin:

# source .tox/py35/bin/activate
(py35)# cd /usr/bin/local
(py35)# ln -s `which ical2orgpy`
(py35)# deactivate
# exit

From now on, the command ical2orgpy shall be available anywhere in the system.

If you feel interested, I may prepare such pull request (but bear with me, it may take a while till I find the time to complete it).

Next actions would be:

  • you agree on package name (my proposal is ical2orgpy)
  • I create pull request with python package (setup.py and all that stuff around)
  • after you accept the PR, you would register the package at pypi.python.org and push the package there (I would provide instructions).

support BYDAY for recurring event

I have a recurring event with:
RRULE:FREQ=MONTHLY;BYDAY=3TU
this is a monthly event on every third Tuesday of the month. ical2org.awk would wrongly put it as monthly event on the day of the first event (+1m), ical2org.py doesn't show it at all as a recurring event (only shows the first one)

Events recurring on multiple days are not treated correctly

Consider this:

BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
X-WR-CALNAME:Self
X-WR-TIMEZONE:America/Chicago

BEGIN:VEVENT
DTSTART;TZID=America/Chicago:20190912T101000
DTEND;TZID=America/Chicago:20190912T132000
RRULE:FREQ=WEEKLY;WKST=MO;UNTIL=20191122T055959Z;BYDAY=TH,TU
DTSTAMP:20190909T202045Z
CREATED:20190829T232009Z
DESCRIPTION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Test
END:VEVENT

END:VCALENDAR

The resulting org file has events recurring only on Thursdays, not on Tuesdays.

Thanks for that great script!

Error: 'unicode' object has no attribute 'params'

After testing the fix to issue #36, I'm now getting this error message:

Error: 'unicode' object has no attribute 'params'

Beyond guessing that it might be related to line 81 (att.params), I have unfortunately no way to debug or fix it.

All day events possibly wrong

When importing from Google Calendar, all day events for me are showing up a day early, for instance a Nov 18 all-day event comes out in org-mode as Nov 17. I made this change to fix it:

               else:  # all day event
                    fh_w.write(u"  {}--{}\n".format(

orgDate(comp_start, self.tz),

orgDate(comp_end - timedelta(days=1), self.tz)))

                        orgDate(comp_start + timedelta(days=1), self.tz),
                        orgDate(comp_end, self.tz)))

The reason is that Google calendar lists an all-day event with the previous day as the start time and the actual day as the end time. I don't know if other calendars do the same, so my patch might not be valid universally. However it's a possible fix for users of Google calendar (only). This should also work for multi-day events.

PytzUsageWarning: The normalize method is no longer necessary

Thank you for this great package.

Sometime in the last few months since I think my system upgraded from Python 3.9 to Python 3.10 I now get some warnings when running ical2orgpy

I don't know if these are worth taking into account yet, but thought I should include them here in case you've not seen them yet.

/home/stephen/.local/lib/python3.10/site-packages/ical2orgpy.py:250: PytzUsageWarning: The normalize method is no longer necessary, as this time zone supports the fold attribute (PEP 495). For more details on migrating to a PEP 495-compliant implementation, see https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html
  event_aux.tzinfo.normalize(event_aux + self.duration), 1)
/
home/stephen/.local/lib/python3.10/site-packages/ical2orgpy.py:48: PytzUsageWarning: The localize method is no longer necessary, as this time zone supports the fold attribute
(PEP 495). For more details on migrating to a PEP 495-compliant implementation, see https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html
  return dt.tzinfo.localize(naive_dt + delta)

Exceptions to recurring events result in two events

As an example I have a weekly meeting 8:30 Monday. The recurrence is handled very nicely by ical2org. However sometimes there is an exception and the meeting is later, say 10:30 Monday. The way icalendar handles this is to create a VEVENT with the same RECURRENCE-ID to override the recurring event for that day. ical2org doesn't treat it as an override, it treats it as another event, and so two events are created, one at 8:30 and another at 10:30.

I'm looking to resolve this but it doesn't seem very easy as exception events would have to be matched up with the recurrence and an override created. If I come up with anything I'll post further.

Doesnt not import location data

BEGIN:VEVENT
SUMMARY:INFO1113 Laboratory
DTSTART;TZID=Australia/Sydney;VALUE=DATE-TIME:20180914T140000
DTEND;TZID=Australia/Sydney;VALUE=DATE-TIME:20180914T160000
UID:****
LOCATION:SIT Lab 115
END:VEVENT

Exports as:

  • INFO1113 Laboratory
    <2018-08-10 Fri 14:00>--<2018-08-10 Fri 16:00>

Really needs location information to be included next to title as:

  • INFO1113 Laboratory - SIT lab 115
    <2018-08-10 Fri 14:00>--<2018-08-10 Fri 16:00>

Command line options for default local timezone and for windows size

The script (as currently in master) expects user to edit some configuration in the code:

  • window length (in days)
  • default time zone.

I would ignore the default timezone as it is very likely user will succeed installing proper package for this (if there is real chance, it would be a problem, we shall add that switch).

In PR #21 is modified version of the code, which internally already expects parameter for windows length. The only thing missing is to add some command line argument parsing for it (either using argparse, or another package, I personally enjoy using click).

Timezone datetime - nontimezone datetime comparison crash

Not sure what exactly in my events is causing this... Some calendars from the same source work just fine. Probably some events use datetimes without a timezone specification and and others with.

/home/.../.local/lib/python3.6/site-packages/ical2orgpy.py:291: UserWarning: Warning: an exception occured: can't compare offset-naive and offset-aware datetimes
  warnings.warn(msg)
Traceback (most recent call last):
  File "/home/.../bin/ical2orgpy", line 10, in <module>
    sys.exit(main())
  File "/home/.../.local/lib/python3.6/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/home/.../.local/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/home/.../.local/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/.../.local/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/home/.../.local/lib/python3.6/site-packages/ical2orgpy.py", line 351, in main
    convertor(ics_file, org_file)
  File "/home/.../.local/lib/python3.6/site-packages/ical2orgpy.py", line 262, in __call__
    event_iter = generate_event_iterator(comp, start, end, self.tz)
  File "/home/.../.local/lib/python3.6/site-packages/ical2orgpy.py", line 75, in generate_event_iterator
    return EventSingleIter(comp, timeframe_start, timeframe_end, tz)
  File "/home/.../.local/lib/python3.6/site-packages/ical2orgpy.py", line 93, in __init__
    if (self.ev_start < timeframe_end and self.ev_end > timeframe_start):
TypeError: can't compare offset-naive and offset-aware datetimes

Creating Python3 branch

Hi,

I started using Python 3 exclusively a while ago and just created a branch (https://github.com/joonro/ical2org.py/tree/python3) where the code works with python 3. I don't want to create a PR against master because it will break Python 2 compatibility, and I think it would be better to have a new branch for Python 3.

May I ask you to create the branch for this? I will create a PR against the Python 3 branch once it is available in the upstream.

Filter out declined meetings

My ical file (exported from Google Calendar) seems to contain all meetings, even the ones I declined (whether an individual event, or a recurring one). ical2org.py transfers these declined events as-is into the target org file.

This causes a great deal of clutter in my org mode agenda.

I would greatly appreciate the possibility of filtering out events that I have declined.

Please add verbose option which would help diagnose refused elements

By default, the 90 days window can be confusing, as elements can be silently discarded because they're outside the 90 days frame.

It would be interesting to have a verbose option allowing to get messages (on stderr ?) about such discarded elements.

Other cases of useful verbose messages may of course apply.

Hope this sounds useful.

Thanks in advance.

`README.rst` on pypi.python.org does not render properly

I have noticed, that README.rst does not render properly on pypi (this is happing quite often).

I got an idea how to fix it easily (probably adding one line into setup.cfg) and will hopefully do that within following days (for next release).

Add support for DURATION

AFAIU, it seems that when only DTSTART and DURATION are present, the org-mode event has same start and end values, instead of having end calculated by addint DURATION to DTSTART

Hope this helps,

Have no default days window, i.e. parse all items by default ?

I understand that this may break stuff for some use cases, but the default which doesn't parse all elements, and applies a 90 days window seems rather surprising.

By default I would think that no filtering is done, and whenever one has performance or other issues, they may choose a particular window for specific filtering.

Of course the opposite reasoning would probably make sense ;)

Hope this helps,

Many past and future events are missing

I'm trying to use ical2orgpy as it handles repeating events really well, but I find that the created org file has many events missing. The input ics has events from 2015 to 2020, but the resulting org file only has events for 2019. Is it possible to convert all events?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.