93 lines
2.8 KiB
Python
93 lines
2.8 KiB
Python
"""Translate an ics file's events to a different timezone."""
|
|
|
|
from datetime import datetime
|
|
from optparse import OptionParser
|
|
|
|
import pytz
|
|
from dateutil import tz
|
|
|
|
import vobject
|
|
|
|
version = "0.1"
|
|
|
|
|
|
def change_tz(cal, new_timezone, default, utc_only=False, utc_tz=vobject.icalendar.utc):
|
|
"""
|
|
Change the timezone of the specified component.
|
|
|
|
Args:
|
|
cal (Component): the component to change
|
|
new_timezone (tzinfo): the timezone to change to
|
|
default (tzinfo): a timezone to assume if the dtstart or dtend in cal doesn't have an existing timezone
|
|
utc_only (bool): only convert dates that are in utc
|
|
utc_tz (tzinfo): the tzinfo to compare to for UTC when processing utc_only=True
|
|
"""
|
|
|
|
for vevent in getattr(cal, 'vevent_list', []):
|
|
start = getattr(vevent, 'dtstart', None)
|
|
end = getattr(vevent, 'dtend', None)
|
|
for node in (start, end):
|
|
if node:
|
|
dt = node.value
|
|
if isinstance(dt, datetime) and (not utc_only or dt.tzinfo == utc_tz):
|
|
if dt.tzinfo is None:
|
|
dt = dt.replace(tzinfo=default)
|
|
node.value = dt.astimezone(new_timezone)
|
|
|
|
|
|
def show_timezones():
|
|
for tz_string in pytz.all_timezones:
|
|
print(tz_string)
|
|
|
|
|
|
def convert_events(utc_only, args):
|
|
print("Converting {} events".format('only UTC' if utc_only else 'all'))
|
|
ics_file = args[0]
|
|
_tzone = args[1] if len(args) > 1 else 'UTC'
|
|
|
|
print("... Reading {}".format(ics_file))
|
|
cal = vobject.readOne(open(ics_file))
|
|
change_tz(cal, new_timezone=tz.gettz(_tzone), default=tz.gettz('UTC'), utc_only=utc_only)
|
|
|
|
out_name = "{}.converted".format(ics_file)
|
|
print("... Writing {}".format(out_name))
|
|
with open(out_name, 'wb') as out:
|
|
cal.serialize(out)
|
|
|
|
print("Done")
|
|
|
|
|
|
def main():
|
|
options, args = get_options()
|
|
|
|
if options.list:
|
|
show_timezones()
|
|
elif args:
|
|
convert_events(utc_only=options.utc, args=args)
|
|
|
|
|
|
def get_options():
|
|
# Configuration options
|
|
usage = """usage: %prog [options] ics_file [timezone]"""
|
|
parser = OptionParser(usage=usage, version=vobject.VERSION)
|
|
parser.set_description("change_tz will convert the timezones in an ics file. ")
|
|
|
|
parser.add_option("-u", "--only-utc", dest="utc", action="store_true",
|
|
default=False, help="Only change UTC events.")
|
|
parser.add_option("-l", "--list", dest="list", action="store_true",
|
|
default=False, help="List available timezones")
|
|
|
|
(cmdline_options, args) = parser.parse_args()
|
|
if not (args or cmdline_options.list):
|
|
print("error: too few arguments given")
|
|
print(parser.format_help())
|
|
return cmdline_options, False
|
|
|
|
return cmdline_options, args
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except KeyboardInterrupt:
|
|
print("Aborted")
|