# On the Calendar > Turn rows copied from a spreadsheet into calendar events. Paste a table with a header, or plain lines. The page > reads every row into an event, flags the ones it cannot be sure of, notes duplicates and overlaps, draws a month > calendar and writes an .ics file (times in UTC, converted from your time zone by your browser) and a Google > Calendar import CSV. A metered run sees only the unclear rows and settles each from the row's own words, today's > date and the sheet's habits - or asks one plain question about it; the page checks every answer against the row. > Nothing is sent to any calendar. Built on the SkillSafe skill @googleworkspace/recipe-create-events-from-sheet. https://on-the-calendar.skillsafe.ai/ ## What is free - Tables: tab-, comma- or pipe-separated, quotes and line breaks in cells handled; the header row is found by its names (title/event/what, date/day/when, time/start/from, end/until, duration, location/where, notes, guests/emails, all day). Without a header, each line is one event. - Dates: ISO (2026-11-07), numeric (11/7, 7/11/2026 - month-first or day-first, settled by the column's own evidence, else guessed from the time zone and flagged), month names (Nov 7, 7 November 2026), today, tomorrow. A date with no year is the next one on or after 90 days ago. A weekday that contradicts its date is flagged. - Times: 7am, 7:30 pm, 19:00, 6-7:30pm (the pm carries back), noon, midnight, all day; durations like 90 min or 1.5h; the default length you pick when there is no end; an evening event that ends after midnight ends the next day. - Flags: relative days (next Saturday), vague times (morning, after the run, 3ish), TBD, bare hours with no am or pm, early hours, ambiguous day and month, end before start, no title, guests with no email addresses, duplicates, overlaps. - Exports: an RFC 5545 .ics file (UTC times, escaped text, 75-octet folding, stable UIDs, all-day events as dates) and Google Calendar's import CSV (Subject, Start Date, Start Time, End Date, End Time, All Day Event, Description, Location). Unclear rows stay out of both until they are settled. - Three samples (a running club's sheet, a family's plain lines, a conference CSV) replay saved replies at no cost. ## The metered task One task, `tidy`, on gpt-terra, metered per run. Input string fields: `task`, `today`, `timezone`, `sheet` (format, columns, date order and why, default length, a few clean rows), `rows` (only the unclear rows, each with what the page read and why it is unclear) and `facts`. The reply is one JSON object: `verdict` (`ready` or `ask`), `events` (each `row`, `title`, `date`, `start`, `end`, `all_day`, `location`, `why`), `questions` (each `row`, `question`), `skip` and `note`. The page checks that every sent row is answered once, every date is real and agrees with any weekday the row names, "next" and "this" weekdays are counted from today (next = the first such day after it), times are in order, and every title word comes from its row. ## Links - API tutorial: https://on-the-calendar.skillsafe.ai/api.html - Source skill: https://skillsafe.ai/skill/@googleworkspace/recipe-create-events-from-sheet