UNPKG

faerun-date

Version:

Canonical Harptos calendar utilities for JavaScript

197 lines (116 loc) 5.72 kB
# faerun-date [![Release](https://github.com/Cantilux/faerun-date/actions/workflows/release.yml/badge.svg)](https://github.com/Cantilux/faerun-date/actions/workflows/release.yml) [![npm version](https://img.shields.io/npm/v/faerun-date.svg)](https://www.npmjs.com/package/faerun-date) [![GitHub Package](https://img.shields.io/badge/GitHub%20Packages-@cantilux%2Ffaerun--date-24292e)](https://github.com/Cantilux/faerun-date/pkgs/npm/faerun-date) Canonical JavaScript utilities for the **Calendar of Harptos**, the calendar used across most of Faerun in the Forgotten Realms. This package models Harptos as: - 12 months of 30 days - 5 intercalary festivals: `Midwinter`, `Greengrass`, `Midsummer`, `Highharvestide`, `Feast of the Moon` - `Shieldmeet` after `Midsummer` every four years - 3 tendays per month Unlike the previous implementation, festivals are treated as standalone days between months, not as regular month dates. The core calendar metadata now lives in a dedicated module, and the public API exposes more Date-like helpers for moving around the Harptos calendar. ## Installation ```bash npm install faerun-date ``` This refactor makes the package ESM-only. CommonJS `require()` is no longer supported on this branch and should be treated as a breaking change for the next release. ## Usage ```js import { HarptosDate, fromGregorian, fromHarptos } from "faerun-date"; const gregorian = fromGregorian(new Date(2025, 1, 1), { drYear: 1497 }); console.log(gregorian.toString()); // "1 Alturiak 1497 DR" const festival = fromGregorian(new Date(2025, 0, 31), { drYear: 1497 }); console.log(festival.toString()); // "Midwinter 1497 DR" const harptos = fromHarptos({ year: 1496, festival: "Shieldmeet" }); console.log(harptos.toLocaleString()); // "Shieldmeet 1496 DR - Summer festival" const direct = new HarptosDate({ year: 1492, month: "Mirtul", day: 5 }); console.log(direct.toLocaleString()); // "5 Mirtul 1492 DR - Spring - Tenday 13, Day 5" const ordinal = new HarptosDate("2026-04-24", { drYear: 1498 }); console.log(ordinal.toString()); // "23 Tarsakh 1498 DR" ``` ## API ### `new HarptosDate(input, options?)` Accepts either: - a Gregorian `Date` - a Gregorian date string such as `2026-04-24` - a Harptos object such as `{ year, month, day }` - a Harptos festival object such as `{ year, festival: "Greengrass" }` - a Harptos ordinal object such as `{ year, dayOfYear: 122 }` `options`: - `drYear`: explicit Harptos year to use when converting from Gregorian - `faerunYear`: legacy alias for `drYear` - `yearOffset`: offset added to the Gregorian year when `drYear` is omitted ### `HarptosDate.fromGregorian(input, options?)` Converts a Gregorian date to the equivalent ordinal day in Harptos for that year length. Harptos month boundaries are always calculated from 30-day months plus intercalary festivals, so Gregorian months with 28, 29, or 31 days do not change the length of Hammer, Alturiak, Ches, or any other Harptos month. ### `HarptosDate.fromHarptos(input, options?)` Creates a canonical Harptos date from month/day, festival, or `dayOfYear`. ### `isFestival()` Returns `true` when the date is one of the intercalary festivals. ### `getFestival()` Returns the festival name or `null`. ### `getMonth()` Returns the Harptos month name or `null` for festivals. ### `getDay()` Returns the day of the month or `null` for festivals. ### `getDate()` Date-style alias of `getDay()`. ### `getMonthIndex()` Returns the zero-based month index or `null` for festivals. ### `getDayOfYear()` Returns the ordinal day in the Harptos year, including festivals. ### `getTenday()` Returns the tenday number for month dates. Festivals return `null` because they are outside the tenday structure. ### `getDayOfTenday()` Returns the day number within the current tenday for month dates. Festivals return `null`. ### `getWeekOfYear()` Legacy alias of `getTenday()`. ### `getWeekday()` Legacy helper that returns a descriptive label such as `5th day of the tenday`. Harptos does not assign formal weekday names to individual days. ### `getSeason()` Returns `Winter`, `Spring`, `Summer`, or `Autumn`. ### `addDays(amount)` Returns a new `HarptosDate` shifted by the given number of days. This operation requires a Harptos year. ### `addTendays(amount)` Returns a new `HarptosDate` shifted by `amount * 10` days. ### `addMonths(amount)` Returns a new `HarptosDate` shifted by calendar months while preserving the day-of-month. This is only supported for month dates, not festivals. ### `addYears(amount)` Returns a new `HarptosDate` shifted by Harptos years. `Shieldmeet` throws when the target year is not leap. ### `toFaerunParts()` Returns normalized calendar parts, including `year`, `monthIndex`, `dayOfYear`, `tenday`, and festival metadata. ### `HarptosDate.fromFaerunParts(input, options?)` Alias of `fromHarptos`, useful when working with normalized parts objects. ### `HarptosDate.compare(a, b)` Compares two Harptos dates by year and ordinal day. ### `toString()` Canonical string form: - month date: `5 Mirtul 1492 DR` - festival: `Shieldmeet 1496 DR` ### `toLocaleString()` Extended display form: - month date: `5 Mirtul 1492 DR - Spring - Tenday 13, Day 5` - festival: `Shieldmeet 1496 DR - Summer festival` ### `toObject()` Returns a plain object with the canonical normalized fields. ## CLI The package ships with a small CLI: ```bash npx faerun-compare-weeks --year 2025 --weeks 12 --dr-year 1497 ``` Options: - `--year <YYYY>`: Gregorian year to inspect - `--weeks <N>`: number of Gregorian weeks to print - `--dr-year <YYYY>`: Harptos year label to print ## Development ```bash npm test ``` ## License [MIT](./LICENSE)