Summary
Add support for the VLOCATION component from RFC 9073 ("Event Publishing Extensions to iCalendar"). This provides structured location data for events, replacing the limitations of the plain-text LOCATION property.
Motivation
The existing RFC 5545 LOCATION property is a single unstructured text string:
LOCATION:123 Main St\, Springfield\, IL 62704
This is inadequate for use cases requiring structured location information (address, geo coordinates, location type). RFC 9073 introduces VLOCATION as a sub-component that provides rich, typed location data:
BEGIN:VEVENT
SUMMARY:Beethoven Piano Sonatas
DTSTART:20250315T150000
DTEND:20250315T163000
BEGIN:VLOCATION
UID:123456-abcdef-98765432
NAME:The venue
DESCRIPTION:Main concert hall, 2nd floor
GEO:40.7651;-73.9799
LOCATION-TYPE:AUDITORIUM
END:VLOCATION
BEGIN:VLOCATION
UID:123456-abcdef-87654321
NAME:Parking for the venue
LOCATION-TYPE:PARKING
END:VLOCATION
END:VEVENT
Why VLOCATION First
RFC 9073 defines three new components (VLOCATION, PARTICIPANT, VRESOURCE) and six new properties. VLOCATION is the best starting point because:
- Simplest component — only 5 optional properties (UID, NAME, DESCRIPTION, GEO, LOCATION-TYPE), no sub-components
- Most directly useful — structured locations with geo coordinates are broadly needed
- Home Assistant relevance — HA already exposes
location as a string attribute on calendar entities; structured VLOCATION data could enable map display and location-based automations
- Low risk — follows the exact same sub-component pattern as VALARM
VLOCATION Specification (RFC 9073 §7.2)
Component Structure
locationc = "BEGIN" ":" "VLOCATION" CRLF
locprop
"END" ":" "VLOCATION" CRLF
Properties
| Property |
Cardinality |
Type |
Notes |
UID |
REQUIRED, once |
TEXT |
Unique identifier |
NAME |
OPTIONAL, once |
TEXT |
Human-readable name (from RFC 7986) |
DESCRIPTION |
OPTIONAL, once |
TEXT |
Longer description |
GEO |
OPTIONAL, once |
GEO |
Lat/lon pair (RFC 5545 §3.8.1.6) |
LOCATION-TYPE |
OPTIONAL, once |
TEXT |
Comma-separated types from RFC 4589 registry |
STRUCTURED-DATA |
OPTIONAL, multi |
TEXT/URI/BINARY |
External references (vCard, schema.org, etc.) |
Where VLOCATION Can Appear
Per RFC 9073 §4:
VEVENT ✅
VTODO ✅
VJOURNAL ✅
VFREEBUSY ✅
PARTICIPANT (defer — PARTICIPANT itself is not yet supported)
LOCATION-TYPE Values
Values come from the RFC 4589 Civic Address Types registry. Common examples:
aircraft, airport, arena, auditorium, bus-station, cafe, classroom, club, convention-center, hospital, hotel, library, office, outdoors, parking, place-of-worship, residence, restaurant, school, shopping-area, stadium, store, street, theater, train-station, warehouse
The registry is extensible, so LOCATION-TYPE should be modeled as Optional[str], not an enum.
Proposed Implementation
New File: ical/location.py
A new Pydantic ComponentModel subclass:
class Location(ComponentModel):
"""A structured location for an event or task (RFC 9073 §7.2)."""
uid: str
name: Optional[str] = None
description: Optional[str] = None
geo: Optional[Geo] = None
location_type: Optional[str] = Field(alias="location-type", default=None)
extras: list[ExtraProperty] = Field(default_factory=list)
Modified Files
Add a locations field to each component that supports VLOCATION, following the existing alarm: list[Alarm] = Field(alias="valarm", ...) pattern:
ical/event.py: Add locations: list[Location] = Field(alias="vlocation", default_factory=list)
ical/todo.py: Same
ical/journal.py: Same
ical/__init__.py: Add "location" to __all__
STRUCTURED-DATA Handling
The STRUCTURED-DATA property is complex — it supports TEXT, BINARY, and URI value types, plus SCHEMA and FMTTYPE parameters. For this initial implementation, any STRUCTURED-DATA properties will be captured in extras. A typed structured_data field could be added in a follow-up.
Design Questions
-
GEO type: Does ical already have a Geo data type? If so, reuse it for Location.geo. If not, a new type needs to be created.
-
LOCATION + VLOCATION coexistence: The existing event.location (string) and new event.locations (list of Location) would both exist. Should we add a convenience property to unify them, or keep them separate? RFC 9073 says both can coexist.
-
STRUCTURED-DATA: Capturing as extras for now. Is a typed StructuredData model needed in this phase?
Test Plan
- Construct a
Location programmatically and verify fields
- Parse an ICS file containing a VEVENT with one VLOCATION
- Parse an ICS file with multiple VLOCATIONs (venue + parking, per RFC example)
- Round-trip: parse ICS → serialize → parse again, verify equality
- Event with both
LOCATION (string) and VLOCATION (structured)
- VLOCATION on VTODO and VJOURNAL
- VLOCATION with GEO coordinates
- VLOCATION with LOCATION-TYPE
- VLOCATION with unknown/extra properties (captured in extras)
What This Does NOT Include (Future Work)
| Deferred Item |
Reason |
| PARTICIPANT component |
Complex: nested VLOCATION/VRESOURCE, schedulability rules, many participant types. Separate issue. |
| VRESOURCE component |
Lower demand than VLOCATION. Separate issue. |
| STYLED-DESCRIPTION property |
Separate concern (rich-text support), complex DERIVED parameter logic |
| STRUCTURED-DATA typed field |
Phase 1 captures as extras; typed support is a follow-up |
| ORDER parameter |
Relevant mainly for PARTICIPANT ordering |
References
Summary
Add support for the
VLOCATIONcomponent from RFC 9073 ("Event Publishing Extensions to iCalendar"). This provides structured location data for events, replacing the limitations of the plain-textLOCATIONproperty.Motivation
The existing RFC 5545
LOCATIONproperty is a single unstructured text string:This is inadequate for use cases requiring structured location information (address, geo coordinates, location type). RFC 9073 introduces
VLOCATIONas a sub-component that provides rich, typed location data:Why VLOCATION First
RFC 9073 defines three new components (VLOCATION, PARTICIPANT, VRESOURCE) and six new properties. VLOCATION is the best starting point because:
locationas a string attribute on calendar entities; structured VLOCATION data could enable map display and location-based automationsVLOCATION Specification (RFC 9073 §7.2)
Component Structure
Properties
UIDNAMEDESCRIPTIONGEOLOCATION-TYPESTRUCTURED-DATAWhere VLOCATION Can Appear
Per RFC 9073 §4:
VEVENT✅VTODO✅VJOURNAL✅VFREEBUSY✅PARTICIPANT(defer — PARTICIPANT itself is not yet supported)LOCATION-TYPE Values
Values come from the RFC 4589 Civic Address Types registry. Common examples:
aircraft,airport,arena,auditorium,bus-station,cafe,classroom,club,convention-center,hospital,hotel,library,office,outdoors,parking,place-of-worship,residence,restaurant,school,shopping-area,stadium,store,street,theater,train-station,warehouseThe registry is extensible, so
LOCATION-TYPEshould be modeled asOptional[str], not an enum.Proposed Implementation
New File:
ical/location.pyA new Pydantic
ComponentModelsubclass:Modified Files
Add a
locationsfield to each component that supports VLOCATION, following the existingalarm: list[Alarm] = Field(alias="valarm", ...)pattern:ical/event.py: Addlocations: list[Location] = Field(alias="vlocation", default_factory=list)ical/todo.py: Sameical/journal.py: Sameical/__init__.py: Add"location"to__all__STRUCTURED-DATA Handling
The
STRUCTURED-DATAproperty is complex — it supports TEXT, BINARY, and URI value types, plus SCHEMA and FMTTYPE parameters. For this initial implementation, any STRUCTURED-DATA properties will be captured inextras. A typedstructured_datafield could be added in a follow-up.Design Questions
GEO type: Does
icalalready have aGeodata type? If so, reuse it forLocation.geo. If not, a new type needs to be created.LOCATION + VLOCATION coexistence: The existing
event.location(string) and newevent.locations(list ofLocation) would both exist. Should we add a convenience property to unify them, or keep them separate? RFC 9073 says both can coexist.STRUCTURED-DATA: Capturing as
extrasfor now. Is a typedStructuredDatamodel needed in this phase?Test Plan
Locationprogrammatically and verify fieldsLOCATION(string) andVLOCATION(structured)What This Does NOT Include (Future Work)
References