Created
July 31, 2026 15:35
-
-
Save htlin222/94a4a6ea11c3bdfc6e0707cdce956dff to your computer and use it in GitHub Desktop.
Generate ICS calendar files from CSV; auto-sets timezone, event duration, reminders. Usage: python csv_to_ics.py events.csv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import csv | |
| import os | |
| import sys | |
| import pytz | |
| from ics import Calendar, Event | |
| from datetime import datetime, timedelta | |
| # Adjust this to your local timezone | |
| local_timezone = pytz.timezone("Asia/Taipei") | |
| before_minutes = 10 # minutes 行前通知時間 | |
| event_duration = 30 # minutes 行程持續時間 | |
| # 主辦人 email,設在環境變數即可,例如 ORGANIZER_EMAIL=you@example.com python csv_to_ics.py events.csv | |
| # 沒設就不寫入 ORGANIZER 欄位 | |
| organizer_email = os.environ.get("ORGANIZER_EMAIL", "") | |
| def create_ics_file( | |
| name, title, start_date, start_time, formatted_remark, url, location | |
| ): | |
| cal = Calendar() | |
| # Convert date and time to a datetime object in local timezone | |
| start_datetime = local_timezone.localize( | |
| datetime.strptime(f"{start_date} {start_time}", "%Y-%m-%d %H:%M") | |
| ) | |
| end_datetime = start_datetime + timedelta(minutes=event_duration) | |
| # Create an event | |
| event = Event() | |
| event.name = title | |
| event.begin = start_datetime | |
| event.end = end_datetime | |
| event.description = formatted_remark | |
| event.url = url | |
| event.location = location | |
| cal.events.add(event) | |
| # Serialize the calendar to a string | |
| ics_content = cal.serialize() | |
| # Manually add an alarm to the event by manipulating the ICS string | |
| alarm_component = f"BEGIN:VALARM\nACTION:DISPLAY\nDESCRIPTION:Reminder\nTRIGGER:-PT{before_minutes}M\nEND:VALARM" | |
| injected = alarm_component | |
| if organizer_email: | |
| injected = ( | |
| f"ORGANIZER;CN=Organizer:mailto:{organizer_email}\n{alarm_component}" | |
| ) | |
| # Save the calendar to an ICS file | |
| ics_content_with_alarm = ics_content.replace( | |
| "END:VEVENT", f"{injected}\nEND:VEVENT" | |
| ) | |
| # Save the calendar to an ICS file | |
| with open(f"行程_{name}.ics", "w") as ics_file: | |
| ics_file.write(ics_content_with_alarm) | |
| print(f"created 行程_{name}.ics") | |
| # Check for the CSV file argument | |
| if len(sys.argv) < 2: | |
| print("Usage: python rent.py <path_to_csv_file>") | |
| sys.exit(1) | |
| csv_file_path = sys.argv[1] | |
| # Read the CSV file and create ICS files | |
| row_count = 0 | |
| with open(csv_file_path, newline="", encoding="utf-8") as csvfile: | |
| reader = csv.DictReader(csvfile) | |
| for row in reader: | |
| title = f"🦎{row['姓名']},{row['備註']}" | |
| name = row["姓名"] # for file name, no blank, e.g. my_name_is_lizard | |
| start_date = row["日期"] # YYYY-MM-DD | |
| start_time = row["開始時間"] # HH:MM | |
| formatted_remark = f"姓名: {row['姓名']},\nPhone: {row['電話']},\n備註: {row['備註']}" | |
| url = row["連結"] | |
| location = row["地點"] | |
| create_ics_file( | |
| name, title, start_date, start_time, formatted_remark, url, location | |
| ) | |
| row_count = row_count + 1 | |
| print(f"Total {row_count} ICS files created successfully.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment