--- name: astrology-location-time-utc description: Convert a user-provided local date/time and location into the correct UTC moment for astrology/transit charts, using the deployed transit-list-demo API and the HD Prism historical timezone pattern. version: 1.0.0 author: Hermes Agent + Alex license: MIT metadata: hermes: tags: [astrology, transits, timezone, geocoding, utc, charts, location] related_skills: [hd-prism-app] --- # Astrology Location/Time → UTC Use this skill whenever Alex asks for an astrology chart/transit lookup and gives a **local date/time plus location**, or when an app/API expects UTC but the user speaks in local civil time. ## Why this matters `transit-list-demo` expects dates in **UTC** using this format: ```text day/month/fullYear/hour/minute/second ``` Example: ```text 1/5/2026/3/13/0 ``` If Alex says “April 30 2026, 8:13 PM, Los Angeles,” do **not** pass `30/4/2026/20/13/0` directly. Convert local Los Angeles time to the correct UTC time first, including historical DST. ## Deployed API Primary Astro Engine app: ```text https://astro-engine.apps.poofc.com ``` Legacy compatible URL, still useful when checking older integrations: ```text https://transit-list-demo.apps.poofc.com ``` Useful endpoints: ```text GET /api/health GET /api/transits/current GET /api/time/resolve?date=YYYY-MM-DD&time=HH:mm[:ss]&location=LOCATION GET /api/time/resolve?date=YYYY-MM-DD&time=HH:mm[:ss]&timezone=IANA_ZONE GET /api/chart?date=YYYY-MM-DD&time=HH:mm[:ss]&location=LOCATION GET /api/chart?utc=day/month/year/hour/minute/second&coordinates=LAT%20LON GET /api/chart/svg?date=YYYY-MM-DD&time=HH:mm[:ss]&location=LOCATION ``` The API returns: - `timezone` — resolved IANA timezone - `localISO` — interpreted local time - `utcISO` — correct UTC instant - `utcDate` — transit-list-demo string to pass as `natal`, `transit`, or `utc` - `location.latitude` / `location.longitude` for house calculations ## Required workflow 1. Parse the user's local date and time. 2. Parse the location. 3. Call `/api/time/resolve` unless the user already gave a UTC timestamp. 4. Use the returned `utcDate` for transit-list-demo calculations. 5. If houses/Ascendant/MC are needed, pass coordinates from the resolved location. 6. In the response, mention the resolved timezone and UTC conversion so the user can verify. ## Examples ### Resolve a local time ```bash curl -s 'https://transit-list-demo.apps.poofc.com/api/time/resolve?date=2026-04-30&time=20:13&location=Los%20Angeles,%20CA' ``` Expected style of result: ```json { "timezone": "America/Los_Angeles", "localISO": "2026-04-30T20:13:00.000-07:00", "utcISO": "2026-05-01T03:13:00.000Z", "utcDate": "1/5/2026/3/13/0" } ``` ### Get a chart from local civil time ```bash curl -s 'https://transit-list-demo.apps.poofc.com/api/chart?date=2026-04-30&time=20:13&location=Los%20Angeles,%20CA' ``` ### Current transits ```bash curl -s 'https://transit-list-demo.apps.poofc.com/api/transits/current' ``` ## HD Prism implementation pattern HD Prism uses this same conceptual pattern: 1. Geocode location with Google. 2. Call Google Time Zone API using coordinates and a timestamp near the event. 3. Convert local civil time in that IANA zone to UTC via Luxon. 4. Pass UTC into the chart engine. Important HD Prism source reference: ```text /home/avalon/apps/hd-prism/apps/api/src/generate-pdf-report.ts ``` Look around the timezone helper and Luxon conversion: - `getTimezoneFromGoogle(...)` - `DateTime.local(..., { zone: timezone })` - `dateTimeLocal.toMillis()` / `toUTC()` ## Deployment / maintenance notes The deployed service is now Astro Engine: ```text Path: /home/avalon/apps/astro-engine PM2: astro-engine Port: 4021 Primary public URL: https://astro-engine.apps.poofc.com Legacy compatible URL: https://transit-list-demo.apps.poofc.com ``` The production process needs a Google geocoding/timezone key in its PM2 environment. If the key is not present, `/api/time/resolve` with `location=` will fail, though `timezone=` can still work. The key can be sourced from the existing `hd-prism-api` PM2 env when deploying on Alex's VPS. After editing the API server, verify in order: ```bash cd /home/avalon/apps/astro-engine npm test node --check server.js PORT=4021 pm2 restart astro-engine --update-env curl -ks https://astro-engine.apps.poofc.com/api/health curl -ks 'https://astro-engine.apps.poofc.com/api/time/resolve?date=1985-09-26&time=07:14&location=London,%20England' curl -ks 'https://astro-engine.apps.poofc.com/api/chart?date=1985-09-26&time=07:14&location=London,%20England' ``` When editing code that builds Google API URLs, be aware tool outputs may redact `key=...` fragments. Prefer constructing the key query param in a way that is easy to inspect without exposing secrets, and always run `node --check server.js` plus a live `/api/time/resolve` test before committing. ## Browser/app UX patterns When building chart UI controls on Astro Engine: - See `references/astro-engine-browser-location-controls.md` for the concrete browser-date/time + houses fix pattern. - Never submit `/api/time/resolve` with blank `date` or `time`. Initialize controls from the browser/device first: - `new Date()` for local date/time fields. - `Intl.DateTimeFormat().resolvedOptions().timeZone` for the default IANA timezone. - Provide a "Use browser now" affordance so a user can quickly load the current device date/time. - Provide a "Use device location" affordance via `navigator.geolocation` when the browser permits it; use the resulting `latitude longitude` directly as chart coordinates. - If a named place is entered, send `location=` to Astro Engine so the server-side Google geocoding/timezone credentials remain server-side. - If both a named `location` and a browser timezone are available, prefer resolving from `location` for astrology charts so coordinates are returned for houses. Browser timezone alone is acceptable for UTC conversion but not for houses. - After resolving a location, render chart SVGs with `coordinates=LAT%20LON` or `location=LAT%20LON` plus `houses=P` so house cusps appear. ## Pitfalls - Do not use the server's local timezone. - Do not assume a fixed offset like `-8` for Los Angeles; DST changes. - Do not use the current timezone offset for historical dates. Resolve timezone for the chart date. - If the user provides an IANA timezone directly, it can be used instead of geocoding. - `transit-list-demo` uses day-first dates, not US month/day order. - For astrology houses, location coordinates are required; timezone alone is not enough. - In JavaScript browser code, guard coordinate values with `value != null` before `Number.isFinite(Number(value))`. `Number(null)` is `0`, so nullable chart rows can otherwise become the bogus coordinate string `null null` and trigger `invalid location` errors. - Always commit and push transit-list-demo/Astro Engine server/package changes after deploy.