// SPDX-FileCopyrightText: 2026 Kerstin Humm // // SPDX-License-Identifier: AGPL-3.0-or-later import { AnnotatedWrapper, Rule } from "../types.js"; import { buildReference } from "../utils.js"; export default { name: "timezone attribute", validate: (self) => { // This seems to differ slightly between Firefox (Web) and NodeJS. For example the UTC value was only valid in Firefox. // Also this requires Intl to be added to compilerOptions.lib in tsconfig. // There might be better ways to do this. const ianaTimezones = Intl.supportedValuesOf("timeZone"); let result = new AnnotatedWrapper(); if ("timezone" in self) { result.assertString(self, ["timezone"], { kind: "Violation", id: "TimezoneNotAString", text: `The timezone ${self["timezone"]} is not a string`, reference: buildReference({ anchor: "time-zone" }), }); } else { result.annotateAt([], { kind: "Note", id: "NoTimezone", text: "The event might need a timezone", reference: buildReference({ anchor: "time-zone", text: "if the Event is primarily conducted in a single specific time-zone, the application SHOULD set the https://w3id.org/fep/8a8e/timezone", }), }); } if ("timezone" in self && typeof self["timezone"] === "string") { if (ianaTimezones.includes(self["timezone"]!)) { result.annotateAt(["timezone"], { kind: "Correct", text: "Valid timezone", }); } else { result.annotateAt(["timezone"], { kind: "Violation", id: "InvalidTimezone", text: `The timezone ${self["timezone"]} is not a valid IANA timezone`, reference: buildReference({ anchor: "time-zone", text: "In case the https://w3id.org/fep/8a8e/timezone property is specified it MUST be a specific IANA time zone identifier included in the IANA Time Zone Database", }), }); } } else { } return result.value; }, tests: [ { value: { "timezone": null }, result: { annotations: [], object: { "timezone": "TimezoneNotAString" } }, }, { value: {}, result: { annotations: ["NoTimezone"], object: {} }, }, { value: { "timezone": "Pacific/Honolulu" }, result: { annotations: [], object: { "timezone": "Correct" } }, }, { value: { "timezone": "not an actual IANA timezone" }, result: { annotations: [], object: { "timezone": "InvalidTimezone" } }, }, ], } satisfies Rule;