Skip to content

Feature: RFC 9073 VLOCATION component support #652

Description

@allenporter

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:

  1. Simplest component — only 5 optional properties (UID, NAME, DESCRIPTION, GEO, LOCATION-TYPE), no sub-components
  2. Most directly useful — structured locations with geo coordinates are broadly needed
  3. 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
  4. 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

  1. 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.

  2. 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.

  3. STRUCTURED-DATA: Capturing as extras for now. Is a typed StructuredData model needed in this phase?

Test Plan

  1. Construct a Location programmatically and verify fields
  2. Parse an ICS file containing a VEVENT with one VLOCATION
  3. Parse an ICS file with multiple VLOCATIONs (venue + parking, per RFC example)
  4. Round-trip: parse ICS → serialize → parse again, verify equality
  5. Event with both LOCATION (string) and VLOCATION (structured)
  6. VLOCATION on VTODO and VJOURNAL
  7. VLOCATION with GEO coordinates
  8. VLOCATION with LOCATION-TYPE
  9. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions