You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

102 lines
3.1 KiB

  1. """Translate an ics file's events to a different timezone."""
  2. from optparse import OptionParser
  3. from vobject import icalendar, base
  4. try:
  5. import PyICU
  6. except:
  7. PyICU = None
  8. from datetime import datetime
  9. def change_tz(cal, new_timezone, default, utc_only=False, utc_tz=icalendar.utc):
  10. """
  11. Change the timezone of the specified component.
  12. Args:
  13. cal (Component): the component to change
  14. new_timezone (tzinfo): the timezone to change to
  15. default (tzinfo): a timezone to assume if the dtstart or dtend in cal
  16. doesn't have an existing timezone
  17. utc_only (bool): only convert dates that are in utc
  18. utc_tz (tzinfo): the tzinfo to compare to for UTC when processing
  19. utc_only=True
  20. """
  21. for vevent in getattr(cal, 'vevent_list', []):
  22. start = getattr(vevent, 'dtstart', None)
  23. end = getattr(vevent, 'dtend', None)
  24. for node in (start, end):
  25. if node:
  26. dt = node.value
  27. if (isinstance(dt, datetime) and
  28. (not utc_only or dt.tzinfo == utc_tz)):
  29. if dt.tzinfo is None:
  30. dt = dt.replace(tzinfo=default)
  31. node.value = dt.astimezone(new_timezone)
  32. def main():
  33. options, args = get_options()
  34. if PyICU is None:
  35. print("Failure. change_tz requires PyICU, exiting")
  36. elif options.list:
  37. for tz_string in PyICU.TimeZone.createEnumeration():
  38. print(tz_string)
  39. elif args:
  40. utc_only = options.utc
  41. if utc_only:
  42. which = "only UTC"
  43. else:
  44. which = "all"
  45. print("Converting {0!s} events".format(which))
  46. ics_file = args[0]
  47. if len(args) > 1:
  48. timezone = PyICU.ICUtzinfo.getInstance(args[1])
  49. else:
  50. timezone = PyICU.ICUtzinfo.default
  51. print("... Reading {0!s}".format(ics_file))
  52. cal = base.readOne(open(ics_file))
  53. change_tz(cal, timezone, PyICU.ICUtzinfo.default, utc_only)
  54. out_name = ics_file + '.converted'
  55. print("... Writing {0!s}".format(out_name))
  56. with open(out_name, 'wb') as out:
  57. cal.serialize(out)
  58. print("Done")
  59. version = "0.1"
  60. def get_options():
  61. # Configuration options
  62. usage = """usage: %prog [options] ics_file [timezone]"""
  63. parser = OptionParser(usage=usage, version=version)
  64. parser.set_description("change_tz will convert the timezones in an ics file. ")
  65. parser.add_option("-u", "--only-utc", dest="utc", action="store_true",
  66. default=False, help="Only change UTC events.")
  67. parser.add_option("-l", "--list", dest="list", action="store_true",
  68. default=False, help="List available timezones")
  69. (cmdline_options, args) = parser.parse_args()
  70. if not args and not cmdline_options.list:
  71. print("error: too few arguments given")
  72. print
  73. print(parser.format_help())
  74. return False, False
  75. return cmdline_options, args
  76. if __name__ == "__main__":
  77. try:
  78. main()
  79. except KeyboardInterrupt:
  80. print("Aborted")