Personal noctalia plugins collection

Fix timezone drift: use IANA timezone instead of ambiguous abbreviation

strftime("%Z") returns "CST" which ICalGLib cannot resolve, causing
events to be stored with local time values but UTC timezone (8h drift).
Resolve IANA name from /etc/localtime symlink instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+31 -32
+3 -8
weekly-calendar/scripts/create-event.py
··· 3 3 4 4 import argparse 5 5 import json 6 + import os 6 7 import sys 7 8 from datetime import datetime, timezone 8 9 ··· 29 30 ical_time = ICalGLib.Time.new_null_time() 30 31 ical_time.set_date(dt.year, dt.month, dt.day) 31 32 ical_time.set_time(dt.hour, dt.minute, dt.second) 32 - tz_id = dt.strftime("%Z") 33 - builtin_tz = ICalGLib.Timezone.get_builtin_timezone(tz_id) 34 - if builtin_tz: 35 - ical_time.set_timezone(builtin_tz) 36 - else: 37 - ical_time.set_timezone(ICalGLib.Timezone.get_utc_timezone()) 38 - ical_time.set_date(dt.year, dt.month, dt.day) 39 - ical_time.set_time(dt.hour, dt.minute, dt.second) 33 + tz_name = os.path.realpath("/etc/localtime").split("/zoneinfo/")[1] 34 + ical_time.set_timezone(ICalGLib.Timezone.get_builtin_timezone(tz_name)) 40 35 return ical_time 41 36 42 37
+3 -6
weekly-calendar/scripts/create-todo.py
··· 3 3 4 4 import argparse 5 5 import json 6 + import os 6 7 import sys 7 8 from datetime import datetime, timezone 8 9 ··· 28 29 ical_time = ICalGLib.Time.new_null_time() 29 30 ical_time.set_date(dt.year, dt.month, dt.day) 30 31 ical_time.set_time(dt.hour, dt.minute, dt.second) 31 - tz_id = dt.strftime("%Z") 32 - builtin_tz = ICalGLib.Timezone.get_builtin_timezone(tz_id) 33 - if builtin_tz: 34 - ical_time.set_timezone(builtin_tz) 35 - else: 36 - ical_time.set_timezone(ICalGLib.Timezone.get_utc_timezone()) 32 + tz_name = os.path.realpath("/etc/localtime").split("/zoneinfo/")[1] 33 + ical_time.set_timezone(ICalGLib.Timezone.get_builtin_timezone(tz_name)) 37 34 return ical_time 38 35 39 36
+13 -12
weekly-calendar/scripts/update-event.py
··· 3 3 4 4 import argparse 5 5 import json 6 + import os 6 7 import sys 7 8 from datetime import datetime, timezone 8 9 ··· 21 22 if src.get_display_name() == calendar_uid or src.get_uid() == calendar_uid: 22 23 return src 23 24 return None 25 + 26 + 27 + def make_ical_datetime(timestamp): 28 + dt = datetime.fromtimestamp(timestamp, tz=timezone.utc).astimezone() 29 + ical_time = ICalGLib.Time.new_null_time() 30 + ical_time.set_date(dt.year, dt.month, dt.day) 31 + ical_time.set_time(dt.hour, dt.minute, dt.second) 32 + tz_name = os.path.realpath("/etc/localtime").split("/zoneinfo/")[1] 33 + ical_time.set_timezone(ICalGLib.Timezone.get_builtin_timezone(tz_name)) 34 + return ical_time 24 35 25 36 26 37 def remove_property(comp, kind): ··· 78 89 ical.set_description(args.description) 79 90 80 91 if args.start is not None: 81 - dt = datetime.fromtimestamp(args.start, tz=timezone.utc) 82 - t = ICalGLib.Time.new_null_time() 83 - t.set_date(dt.year, dt.month, dt.day) 84 - t.set_time(dt.hour, dt.minute, dt.second) 85 - t.set_timezone(ICalGLib.Timezone.get_utc_timezone()) 86 - ical.set_dtstart(t) 92 + ical.set_dtstart(make_ical_datetime(args.start)) 87 93 88 94 if args.end is not None: 89 - dt = datetime.fromtimestamp(args.end, tz=timezone.utc) 90 - t = ICalGLib.Time.new_null_time() 91 - t.set_date(dt.year, dt.month, dt.day) 92 - t.set_time(dt.hour, dt.minute, dt.second) 93 - t.set_timezone(ICalGLib.Timezone.get_utc_timezone()) 94 - ical.set_dtend(t) 95 + ical.set_dtend(make_ical_datetime(args.end)) 95 96 96 97 client.modify_object_sync(comp, ECal.ObjModType.ALL, ECal.OperationFlags.NONE, None) 97 98 print(json.dumps({"success": True}))
+12 -6
weekly-calendar/scripts/update-todo.py
··· 3 3 4 4 import argparse 5 5 import json 6 + import os 6 7 import sys 7 8 from datetime import datetime, timezone 8 9 ··· 21 22 if src.get_display_name() == task_list_uid or src.get_uid() == task_list_uid: 22 23 return src 23 24 return None 25 + 26 + 27 + def make_ical_datetime(timestamp): 28 + dt = datetime.fromtimestamp(timestamp, tz=timezone.utc).astimezone() 29 + ical_time = ICalGLib.Time.new_null_time() 30 + ical_time.set_date(dt.year, dt.month, dt.day) 31 + ical_time.set_time(dt.hour, dt.minute, dt.second) 32 + tz_name = os.path.realpath("/etc/localtime").split("/zoneinfo/")[1] 33 + ical_time.set_timezone(ICalGLib.Timezone.get_builtin_timezone(tz_name)) 34 + return ical_time 24 35 25 36 26 37 def remove_property(comp, kind): ··· 102 113 if args.description is not None: 103 114 ical.set_description(args.description) 104 115 if args.due is not None: 105 - dt = datetime.fromtimestamp(args.due, tz=timezone.utc) 106 - t = ICalGLib.Time.new_null_time() 107 - t.set_date(dt.year, dt.month, dt.day) 108 - t.set_time(dt.hour, dt.minute, dt.second) 109 - t.set_timezone(ICalGLib.Timezone.get_utc_timezone()) 110 116 remove_property(ical, ICalGLib.PropertyKind.DUE_PROPERTY) 111 - prop = ICalGLib.Property.new_due(t) 117 + prop = ICalGLib.Property.new_due(make_ical_datetime(args.due)) 112 118 ical.add_property(prop) 113 119 if args.priority is not None: 114 120 remove_property(ical, ICalGLib.PropertyKind.PRIORITY_PROPERTY)