Chronos Plugins
-
Chronos
supports a powerful plugin system that allows developers to inject additional methods or utilities into theChronos
class 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()
method or its wrapper function:
Chronos.use(pluginName);
// or
chronos.use(pluginName)
- Each plugin is only applied once, even if
use()
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()
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)
// 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 | getRelativeYear, getRelativeMonth, getRelativeWeek, getRelativeDay, getRelativeHour, getRelativeMinute, getRelativeSecond, getRelativeMilliSecond, compare, isToday, isTomorrow, isYesterday | |
timeZonePlugin | timeZone, getTimeZoneNameShort | |
fromNowPlugin | fromNow | |
businessPlugin | isWeekend, isWorkday, isBusinessHour, toAcademicYear, toFiscalQuarter | |
seasonPlugin | season | |
dayPartPlugin | getPartOfDay | |
zodiacPlugin | getZodiacSign | |
palindromePlugin | isPalindromeDate | |
greetingPlugin | getGreeting | |
(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);
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 instance - Chronos instance to operate on
* @param method - Name of the method creating this instance
* @param label - Optional UTC offset label
*/
withOrigin(
instance: Chronos,
method: ChronosMethods,
label?: 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 from the package itself: plugin that adds a
timeZone
method toChronos
instances, 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 => {
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 internals = ChronosClass[INTERNALS];
const adjustedTime = new Date(
internals.internalDate(this).getTime() + relativeOffset * 60 * 1000
);
const instance = new ChronosClass(adjustedTime);
return internals.withOrigin(instance, 'timeZone', stringOffset);
};
};
π₯ Important Notesβ
- Always augment
Chronos
via module augmentation to ensure TypeScript recognizes your new methods using this subpath:'nhb-toolbox/chronos'
- Import
Chronos
andINTERNALS
from'nhb-toolbox'
in your plugin file - Always use the static
[INTERNALS]
interface rather than trying to access private fields directly - The
withOrigin
method should be used when creating newChronos
instances to maintain proper origin tracking - For native js
Date
manipulation in your plugin, prefer usingtoNewDate
fromChronosInternals
interface rather than creatingDate
objects directly to maintain consistency with internal handling ofChronos