# Pathrule Pattern: Dates, Time Zones, and Calendars (1.0.0)
# ::pathrule:package:dates-timezones-calendars

### [RULE] Choose the temporal type from the business meaning  (path: /src/domain)
<!-- scope: folder | priority: high | strict -->

A universal timestamp preserves one moment but destroys other meanings. Date-only and wall-clock values can shift when forced through UTC, while an instant without its scheduling zone cannot reproduce the intended local recurrence.

- Use an instant for an event that happened at one point on the global timeline, such as creation, payment authorization, or log time.
- Use a date-only value for birthdays, holidays, and due dates whose meaning is a calendar day independent of timezone.
- Use a local date-time plus an IANA timezone identifier for future appointments and recurring schedules whose wall-clock time must remain stable in that place.
- Use a duration for elapsed time and explicit calendar operations for months or years; do not assume every day, month, or year has a fixed number of seconds.

See /src/scheduling for the adjacent decision or procedure that completes this constraint.

---

### [RULE] Serialize temporal values without ambiguity  (path: /src/domain)
<!-- scope: folder | priority: high | strict -->

Human-readable date strings are locale-dependent and runtime parsers accept different subsets. A payload that relies on an implicit local zone or ambiguous day and month order can map to different values on different machines.

- Serialize instants in a standard timestamp format with an explicit offset, and normalize storage according to the domain contract rather than the current machine timezone.
- Serialize date-only values as date-only text and never append a midnight offset merely to reuse an instant column or parser.
- Carry the named zone separately for future wall-clock schedules; an offset alone cannot describe later daylight-saving rules.
- Parse through an explicit library or schema and reject ambiguous, out-of-range, nonexistent, or unsupported values with a field-specific error.

See /tests/time for the adjacent decision or procedure that completes this constraint.

---

### [MEMORY] Recurring schedules are generated in their named zone  (path: /src/scheduling)

Adding a fixed duration to the previous occurrence changes local clock time across daylight-saving transitions. The recurrence rule must live in local calendar space, with the zone applied to each generated occurrence.

- Store the recurrence definition, local time, named zone, start boundary, and any product-specific end or exception rules.
- Generate the next local calendar occurrence before converting it to an instant for delivery, storage, or comparison.
- Define what happens when a local time does not exist or occurs twice: skip, shift, choose earlier, choose later, or require user confirmation.
- Keep generated occurrence identity stable so a scheduler can retry without creating two jobs for the same logical recurrence.

See /tests/time for the rule or workflow that puts this decision into practice.

---

### [MEMORY] Display timezone belongs to the user or record context  (path: /src/domain)

Converting every timestamp to the server zone or browser default creates inconsistent reports and notifications. The correct display zone is a product decision, not a runtime convenience.

- Resolve timezone from an explicit user or organization preference when presenting viewer-relative activity.
- Use the event or location zone when the local wall time is part of the record, such as a flight, appointment, or store opening.
- Include zone or offset in displays where two viewers may compare times or where daylight-saving ambiguity matters.
- Keep formatting at the presentation boundary and preserve the underlying instant or calendar value for sorting, filtering, and API transport.

See /src/scheduling for the rule or workflow that puts this decision into practice.

---

### [MEMORY] Calendar arithmetic follows product rules  (path: /src/domain)

Adding one month to a date near the end of a month has several defensible outcomes, and billing or compliance logic often needs one specific answer. The same ambiguity appears in leap years and inclusive date ranges.

- Document whether month addition clamps to the last valid day, skips an invalid occurrence, or preserves an end-of-month convention.
- Define leap-day anniversaries and yearly renewals explicitly for non-leap years rather than accepting silent rollover.
- Represent date ranges with clear inclusive or exclusive boundaries and use the same convention in database queries and user-facing copy.
- Keep business calendars, holidays, and working-hour rules as versioned domain data when they affect money or obligations.

See /tests/time for the rule or workflow that puts this decision into practice.

---

### [SKILL] test-temporal-edge-cases  (path: /)

---
name: test-temporal-edge-cases
description: Test date, timezone, recurrence, or calendar behavior before changing a schedule or serialized contract.
---

# Test Temporal Edge Cases

Run this procedure when the affected surface changes, before the result is promoted to production. Record evidence for every step instead of accepting a plausible-looking result.

1. Freeze the clock and run the same case with process and browser defaults set to several distant timezones, including a zone without daylight-saving changes.
2. Test the transition into and out of daylight-saving time, including nonexistent and repeated local wall-clock values under the declared policy.
3. Exercise month end, year end, leap day, minimum and maximum supported dates, and inclusive range boundaries.
4. Round-trip API and database serialization for instants, date-only values, local date-times, named zones, and offsets without relying on host parsing.
5. Render representative locales and zones, then verify sorting and comparisons use the underlying value rather than formatted text.

## Exit criteria

The change is complete only when the expected behavior, failure behavior, and rollback path have all been exercised with representative data. Preserve the evidence with the change so the next operator can repeat the same checks.
