feat: add Stella Sora, from the wiki's front page rather than its banner list
This wiki publishes the same schedule twice and the fuller surface is the worse one. /wiki/Banner_List has 55 clean rows with full wall clocks and states no timezone anywhere on the page; the front page's Current Banners module emits the same instants as real <time datetime="...-07:00"> elements. The two agree exactly, which is strong evidence the list is UTC and is still only evidence — so we read the surface that says what it means and pay four live banners instead of a full history for it. If an editor ever states the zone on Banner_List, that page becomes the better source immediately. Two ways this could have failed silently. The template writes its BEM underscores as __, so a selector written against the class name a browser shows matches nothing at all; and banner names are red links to ?action=edit&redlink=1, which Miraheze's robots.txt disallows, so a href carrying a query is refused and the page URL stands in. No resetOffsets, and here the source did state an offset: -07:00, which is US Pacific and therefore shifts twice a year. That is the Fate/Grand Order gap arriving through a page that looks like it answered the question. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4dff14087f
commit
ecbf9c0422
@@ -516,3 +516,42 @@ export function parseIsoClockRangeUtc(
|
||||
end: { iso: endIso, precision: "exact" },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* `2026-08-03T21:00-07:00` → 2026-08-04T04:00:00.000Z, exact precision.
|
||||
*
|
||||
* A machine-readable instant, which is rare enough here to be worth naming:
|
||||
* the Stella Sora wiki's front page emits its banner window as real
|
||||
* `<time datetime>` elements, so the offset is stated in the markup rather than
|
||||
* printed for a human to interpret.
|
||||
*
|
||||
* **The offset is required.** `Z` or `±HH:MM` both pass; a bare local datetime
|
||||
* does not, and that is the same call every other reader here makes. It matters
|
||||
* more than usual on this source, because the page's sibling `Banner_List`
|
||||
* prints the identical instants with no zone anywhere — reading those as UTC
|
||||
* would be an assumption that happens to be right today and is unfalsifiable
|
||||
* from the page, which is exactly the kind of fact this file refuses to invent.
|
||||
*
|
||||
* Anchored at both ends: an attribute value is a whole cell, not prose.
|
||||
*/
|
||||
export function parseIsoOffsetInstant(input: string): ParsedInstant | null {
|
||||
const re =
|
||||
/^\s*(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?\s*(Z|[+-]\d{2}:?\d{2})\s*$/i;
|
||||
const m = re.exec(input);
|
||||
if (!m) return null;
|
||||
|
||||
// Validated on the stated local fields before the offset shifts anything:
|
||||
// converting first would quietly turn February 30 into a real March instant.
|
||||
const local = iso(
|
||||
Number(m[1]),
|
||||
Number(m[2]),
|
||||
Number(m[3]),
|
||||
Number(m[4]),
|
||||
Number(m[5]),
|
||||
);
|
||||
if (local === null) return null;
|
||||
|
||||
const value = Date.parse(input.trim());
|
||||
if (Number.isNaN(value)) return null;
|
||||
return { iso: new Date(value).toISOString(), precision: "exact" };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user