Chronos Plugins
-
Chronossupports a powerful plugin system that allows developers to inject additional methods or utilities into theChronosclass without modifying its core. This enables clean separation of concerns, tree-shaking, modular feature design, and maintainability. -
Plugins can be official (maintained by the core team) or custom (developed by users). See the list of official plugins below or learn how to write your own plugin.
π§© What Is a Plugin?β
A plugin is a function that takes the Chronos class constructor and augments itβusually by adding prototype methods.
type ChronosPlugin = (ChronosClass: typeof Chronos) => void;
You can inject plugins via the static Chronos.use() or Chronos.register() method or its wrapper function:
Chronos.use(pluginName);
// or
chronos.use(pluginName);
// or
Chronos.register(pluginName);
// or
chronos.register(pluginName);
- Each plugin is only applied once, even if
use()orregister()is called multiple times with the same plugin. - If a plugin enables multiple methods, injecting once will enable all the methods by that particular plugin. See the list below
β Using a Pluginβ
To enable a plugin, use the static Chronos.use() or Chronos.register() method before creating instances:
import { Chronos, chronos } from 'nhb-toolbox';
// For importing a plugin from the package, plugin name and import path are same
import { pluginName } from 'nhb-toolbox/plugins/pluginName';
// Using the plugin
Chronos.use(pluginName);
// or
chronos.use(pluginName);
// or
Chronos.register(pluginName);
// or
chronos.register(pluginName);
// Using the method enabled by that plugin
const c = new Chronos();
c.enabledMethod();
// or
chronos().enabledMethod()
π¦ Official Pluginsβ
| Plugin Names | Imports Statements | Methods Registered |
|---|---|---|
relativeTimePlugin | compare, getRelativeYear, getRelativeMonth, getRelativeWeek, getRelativeDay, getRelativeHour, getRelativeMinute, getRelativeSecond, getRelativeMilliSecond, isToday, isTomorrow, isYesterday | |
timeZonePlugin | timeZone, getTimeZoneName, getTimeZoneNameShort | |
durationPlugin | duration, durationString | |
fromNowPlugin | fromNow | |
businessPlugin | isWeekend, isWorkday, isBusinessHour, toAcademicYear, toFiscalQuarter | |
seasonPlugin | season | |
dayPartPlugin | getPartOfDay | |
zodiacPlugin | getZodiacSign | |
palindromePlugin | isPalindromeDate | |
greetingPlugin | getGreeting | |
roundPlugin | round |
More coming soon...
π οΈ Writing Your Own Custom Pluginβ
Here's the basic structure of a Chronos plugin with access to protected and/or private internals:
import { Chronos, INTERNALS } from 'nhb-toolbox';
// Create a module augmentation to add your custom method to the `Chronos` interface
// This allows TypeScript to recognize the new method on `Chronos` instances
// This should be inside a `d.ts` file or at the top of your plugin file (must be a `.ts` file)
declare module 'nhb-toolbox/chronos' {
interface Chronos {
/**
* @instance Custom `Chronos` method to greet a user with the current date.
* @param user The name of the user to greet.
* @returns A greeting message including the user's name and the current ISO dates.
*/
customMethod(user: string): string;
}
}
// The plugin function must be in a `.ts` or `.js` file
/** * Plugin to inject `customMethod` into Chronos instances. */
export const customPlugin = (ChronosClass: typeof Chronos): void => {
ChronosClass.prototype.customMethod = function (this: Chronos, user: string): string {
// Example of accessing internals through protected static interface
const internalDate = ChronosClass[INTERNALS].internalDate(this);
return `Hello ${user}, Welcome to custom plugin! Current date: { local: ${this} } { utc: ${internalDate.toISOString()} }`;
};
};
Now consume the plugin in the same file or another file where you want to use your custom method
import { Chronos } from 'nhb-toolbox';
// or import { Chronos } from 'nhb-toolbox/chronos';
import { customPlugin } from './path-to-your-plugin-file';
// Use the plugin in your application's root/entry file or where you initialize `Chronos`
Chronos.use(customPlugin);
// or
Chronos.register(customPlugin);
new Chronos().customMethod('NHB');
// => "Hello NHB, Welcome to custom plugin! Current date: { local: 2025-09-22T14:47:44.132+06:00 } { utc: 2025-09-22T08:47:44.132Z }"
π Accessing Internalsβ
Plugins can safely access protected and/or private internal properties or methods through the static [INTERNALS] interface:
π Available Internal Propertiesβ
interface ChronosInternals {
/**
* Creates a new Chronos instance with origin tracking
* @param origin Origin of the instance, the method name from where it was created.
* @param offset Optional UTC offset in `UTCΒ±HH:mm` format.
* @param tzName Optional time zone name to set.
* @param tzId Optional time zone identifier(s) to set.
* @param tzTracker Optional tracker to identify the instance created by {@link timeZone} method.
* @returns The `Chronos` instance with the specified origin and other properties.
*/
withOrigin(
instance: Chronos,
method: PluginMethods,
offset?: UTCOffset,
tzName?: LooseLiteral<TimeZoneName>,
tzId?: TimeZoneId,
tzTracker?: $TimeZoneIdentifier | TimeZone | UTCOffset
): Chronos;
/**
* Creates a new Date object from Chronos input
* @param instance - Chronos instance to operate on
* @param value - Input value to convert (optional, uses current date if omitted)
*/
toNewDate(instance: Chronos, value?: ChronosInput): Date;
/**
* Gets the internal Date object
* @param instance - Chronos instance to access
*/
internalDate(instance: Chronos): Date;
/**
* Gets the current UTC offset
* @param instance - Chronos instance to access
*/
offset(instance: Chronos): UTCOffset;
}
π Usage Exampleβ
Here's a real example (simpler version) from the package itself: plugin that adds a
timeZonemethod toChronosinstances, allowing users to convert the instance to a specified time zone using some internal methods and properties:
import { Chronos, INTERNALS } from 'nhb-toolbox';
// Other imports
declare module 'nhb-toolbox/chronos' {
interface Chronos {
timeZone(): string;
}
}
export const timeZonePlugin = (ChronosClass: typeof Chronos): void => {
const { internalDate, withOrigin } = ChronosClass[INTERNALS];
ChronosClass.prototype.timeZone = function (
this: Chronos,
zone: TimeZone | UTCOffset
): Chronos {
let targetOffset: number;
let stringOffset: UTCOffset;
if (isValidUTCOffSet(zone)) {
targetOffset = extractMinutesFromUTC(zone);
stringOffset = zone;
} else {
targetOffset = TIME_ZONES?.[zone] ?? TIME_ZONES['UTC'];
stringOffset = formatUTCOffset(targetOffset);
}
const previousOffset = this.getTimeZoneOffsetMinutes();
const relativeOffset = targetOffset - previousOffset;
const adjustedTime = new Date(internalDate(this).getTime() + relativeOffset * 60 * 1000);
const instance = new ChronosClass(adjustedTime);
return withOrigin(instance, 'timeZone', stringOffset);
};
};
π₯ Important Notesβ
- Always augment
Chronosvia module augmentation to ensure TypeScript recognizes your new methods using this subpath:'nhb-toolbox/chronos' - Import
ChronosandINTERNALSfrom'nhb-toolbox'in your plugin file - Always use the static
[INTERNALS]interface rather than trying to access private fields directly - The
withOriginmethod should be used when creating newChronosinstances to maintain proper origin tracking - For native js
Datemanipulation in your plugin, prefer usingtoNewDatefromChronosInternalsinterface rather than creatingDateobjects directly to maintain consistency with internal handling ofChronos