#!/usr/bin/env python3
"""
Configurable Calendar Generator for ODS format
Usage: python3 generate_calendar.py [year] [output_file]
Example: python3 generate_calendar.py 2026 calendar_2026.ods
"""
from datetime import datetime, timedelta
import zipfile
import sys
def create_calendar_ods(year, output_file):
month_names = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December']
day_headers = ['M', 'T', 'W', 'T', 'F', 'S', 'S']
def get_month_calendar(year, month):
"""Returns list of weeks for a month, each week has 7 days (0 = empty)"""
first_day = datetime(year, month, 1)
first_weekday = first_day.weekday() # 0=Monday, 6=Sunday
if month == 12:
last_day = 31
else:
last_day = (datetime(year, month + 1, 1) - timedelta(days=1)).day
weeks = []
week = [0] * first_weekday
for day in range(1, last_day + 1):
week.append(day)
if len(week) == 7:
weeks.append(week)
week = []
if week:
week.extend([0] * (7 - len(week)))
weeks.append(week)
return weeks
# Generate calendar for all months
month_rows_xml = ""
for row in range(3):
start_month = row * 4 + 1
months_in_row = [start_month, start_month + 1, start_month + 2, start_month + 3]
# Title row
month_rows_xml += ' \n'
for month in months_in_row:
month_rows_xml += f' {month_names[month-1]} {year}\n'
month_rows_xml += ' \n'
month_rows_xml += ' \n'
# Day headers
month_rows_xml += ' \n'
for month in months_in_row:
for day_header in day_headers:
month_rows_xml += f' {day_header}\n'
month_rows_xml += ' \n'
month_rows_xml += ' \n'
# Get calendar data for all months
month_cals = [get_month_calendar(year, m) for m in months_in_row]
max_weeks = max(len(cal) for cal in month_cals)
# Days
for week_idx in range(max_weeks):
month_rows_xml += ' \n'
for month_idx, month in enumerate(months_in_row):
if week_idx < len(month_cals[month_idx]):
week = month_cals[month_idx][week_idx]
for day_idx, day in enumerate(week):
if day == 0:
month_rows_xml += ' \n'
else:
# Weekend is Saturday (day_idx=5) and Sunday (day_idx=6)
if day_idx >= 5:
month_rows_xml += f' {day}\n'
else:
month_rows_xml += f' {day}\n'
else:
for _ in range(7):
month_rows_xml += ' \n'
month_rows_xml += ' \n'
month_rows_xml += ' \n'
month_rows_xml += ' \n'
content_xml = f'''
{month_rows_xml}
'''
manifest_xml = '''
'''
styles_xml = '''
'''
meta_xml = f'''
Calendar {year}
{datetime.now().isoformat()}
'''
with zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED) as ods:
ods.writestr('mimetype', 'application/vnd.oasis.opendocument.spreadsheet', compress_type=zipfile.ZIP_STORED)
ods.writestr('META-INF/manifest.xml', manifest_xml)
ods.writestr('content.xml', content_xml)
ods.writestr('styles.xml', styles_xml)
ods.writestr('meta.xml', meta_xml)
print(f"✓ Calendar for {year} created: {output_file}")
if __name__ == "__main__":
if len(sys.argv) < 2:
year = int(input("Enter year: "))
output = f"calendar_{year}.ods"
else:
year = int(sys.argv[1])
output = sys.argv[2] if len(sys.argv) > 2 else f"calendar_{year}.ods"
try:
create_calendar_ods(year, output)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)