The Event model is the central data structure in both the web app and the Android app. In the web app it exists as a plain JavaScript object stored inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/PunctuOwlity/llms.txt
Use this file to discover all available pages before exploring further.
localStorage; in the Android app it is a Java class whose instances are persisted in a SQLite database. Despite the different runtimes, both platforms share the same conceptual fields: a title, a date, a time, and display-ready derivatives of those values.
Web Event Object
Each event in the web app is a plain object that conforms to the following shape. All fields are written bynormalizeEvent before being stored or rendered, so callers can rely on the formats described here.
Unique identifier for the event. For new events created in the browser, this is set to
String(Date.now()). Seed events use human-readable named IDs such as "project", "birthday", "dentist", and "wedding".Three-letter weekday abbreviation in uppercase, derived from
fullDate via toLocaleDateString('en-US', { weekday: 'short' }).toUpperCase(). Examples: "SAT", "MON", "SUN". Falls back to "---" when the date cannot be parsed.Zero-padded two-digit day-of-month number derived from
fullDate. Examples: "05", "12", "14", "20". Falls back to "00" when the date cannot be parsed.ISO 8601 date string in
YYYY-MM-DD format. This is the canonical date field used for sorting events and matching against today’s date for notifications. Example: "2025-04-12".24-hour time string in
HH:MM format. Empty string ("") indicates an all-day event. Example: "18:30". This field is what the <input type="time"> element provides and what is stored in localStorage.12-hour display-ready time string produced by
normalizeEvent. Examples: "06:30PM", "01:30PM", "03:00PM". When rawTime is empty the value is "ALL DAY".The human-readable event name entered by the user. Required — the add-event form will not submit without it.
Event category used for tab filtering on the events screen. One of
"birthday", "appointment", "trip", "general", or "all". Auto-detected from the title by normalizeEvent when no explicit category is provided; see Category Auto-Detection below.Whether a browser notification reminder is enabled for this event. Set by the toggle switch on the add/edit form. When
true and the notification permission is "granted", a Notification is fired on the event’s fullDate if it matches today’s date.Android Event Class
The AndroidEvent class (package com.example.punctuowlityeventtracker) is a simple value object with four private fields. It has two constructors — one for records loaded from the database (which already have an id) and one for new records about to be inserted.
| Member | Type | Notes |
|---|---|---|
id | int | Auto-increment primary key assigned by SQLite. Only present after a row is persisted. |
title | String | Event name. final after construction. |
date | String | Stored as MM/dd/yyyy. final after construction. |
time | String | Display time string as entered by the user. final after construction. |
Returns the SQLite row ID of the event.
Returns the event title.
Returns the stored date string in
MM/dd/yyyy format. Example: "04/12/2025".Returns the time string as stored — typically a 12-hour display value such as
"06:30PM" or "ALL DAY".Parses
date using SimpleDateFormat("MM/dd/yyyy"), then formats the result with SimpleDateFormat("EEE") and calls .toUpperCase(). Returns values like "SAT" or "MON". Returns "---" on any parse failure.Parses
date using SimpleDateFormat("MM/dd/yyyy"), then formats the result with SimpleDateFormat("dd") to extract the zero-padded day number. Returns values like "05" or "12". Returns "00" on any parse failure.Date and Time Formats
The two platforms use different primary date formats, and each has its own storage-to-display conversion path.- Web App
- Android App
Storage format:
fullDate is stored as YYYY-MM-DD (ISO 8601). This is the native value produced by <input type="date">.Input formats accepted by normalizeEvent:YYYY-MM-DD— matched by/^\d{4}-\d{2}-\d{2}$/MM/DD/YYYY— matched by/^\d{2}\/\d{2}\/\d{4}$/, converted toYYYY-MM-DDby splitting on/
rawTime is transformed to a 12-hour display string:- Input regex:
/^\d{1,2}:\d{2}$/ - Hours ≥ 12 → suffix
"PM", otherwise"AM" - Hour displayed as
hours % 12 || 12, zero-padded to two digits - Empty
rawTime→ display value"ALL DAY"
day and date) are computed from fullDate by constructing new Date($T00:00:00) to avoid timezone shifts.Category Auto-Detection
WhennormalizeEvent processes a web event that has no category field (or an empty one), it inspects the lowercased title to assign a category automatically:
| Matched pattern | Assigned category |
|---|---|
title includes "birthday" | "birthday" |
title matches /(appointment|dentist|dental|doctor)/ | "appointment" |
title matches /(trip|travel|vacation)/ | "trip" |
| no match | "general" |
Auto-detection only runs when
event.category is falsy. If a category is already set (including "all" on seed events), it is preserved unchanged. New events created from add-event.html always store existing?.category || "general", so category correction can only come from the normalization path on first load.Seed Events
The following array is hard-coded inapp.js and used as the initial data set when no saved events exist in localStorage, or when the parse of the stored JSON fails.