Metadata-Version: 2.4
Name: larzical
Version: 0.1.0
Summary: iCalendar RFC 5545 build and parse - zero dependencies
Author: larz-scripter
License: MIT
Project-URL: Homepage, https://github.com/larz-scripter/larzical
Project-URL: Repository, https://github.com/larz-scripter/larzical
Project-URL: Issues, https://github.com/larz-scripter/larzical/issues
Keywords: icalendar,ics,calendar,rfc5545,vevent,events,zero-dependency,pure-python
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# larzical

**iCalendar (RFC 5545) — build and parse `.ics` — with zero dependencies.**

Generate calendar invites and feeds that Google Calendar, Apple Calendar and
Outlook accept, and parse the ones they send you. larzical implements the parts
of RFC 5545 that matter in practice — and the details hand-rolled `.ics`
generators get wrong: correct **TEXT escaping**, **75-octet line folding**
(multibyte-safe), UTC date-times, and CRLF endings.

## Install

```bash
pip install larzical
```

## Use

```python
from larzical import Calendar, Event, Alarm
from datetime import datetime, date

cal = Calendar(prodid="-//Acme//App//EN", name="Team")
cal.add(Event(
    summary="Launch call",
    start=datetime(2026, 8, 1, 15, 0),
    end=datetime(2026, 8, 1, 16, 0),
    location="Zoom",
    description="Kickoff; agenda attached.",
    attendees=["a@x.com", "b@x.com"],
    alarms=[Alarm(trigger="-PT15M")],
))
cal.add(Event(summary="Company holiday", start=date(2026, 12, 25)))  # all-day

ics = cal.to_ical()               # a valid .ics string, folded + CRLF
Calendar.parse(ics)               # round-trips back to Events
```

## Why it's correct

`.ics` files fail silently in calendar clients when the low-level rules are
wrong. larzical is anchored to the spec:

- **TEXT escaping** (3.3.11) — `,` `;` `\` and newlines escaped/unescaped.
- **Line folding** (3.1) — content lines folded at **75 octets** with `CRLF `,
  and never split in the middle of a multibyte character.
- **Date-time** (3.3.5) — UTC `YYYYMMDDTHHMMSSZ`; all-day as `VALUE=DATE`.
- **Round-trip** — `Calendar.parse(cal.to_ical())` reconstructs the events.

## Tests

```bash
python -m unittest discover -s tests -v   # 17 tests
```

## The Larz stack

One of 60+ pure-Python, zero-dependency libraries at
[github.com/larz-scripter](https://github.com/larz-scripter). Pairs with
[larzqr](https://github.com/larz-scripter/larzqr) (add a scannable event QR) and
[larzemail](https://github.com/larz-scripter/larzemail) (attach the invite to a
MIME email).

## License

MIT (c) larz-scripter
