date-time-format-icu
Version:
This package provides a simple and flexible way to format JavaScript dates
303 lines (269 loc) • 12.7 kB
Markdown
# date-time-format-icu-package
A lightweight and flexible JavaScript utility to format dates using **ICU date-time format tokens** and standard **preset styles**. Ideal for any JavaScript/TypeScript project that requires locale-aware and timezone-aware date formatting.
---
## ✨ Features
- ✅ Supports all ICU date-time format tokens
- ✅ Includes common preset styles (`short`, `medium`, `long`, `full`)
- ✅ Locale-aware formatting
- ✅ Timezone support
- ✅ Handles `null`/`undefined` inputs gracefully
- ✅ Fully typed with TypeScript
---
## 📦 Installation
```bash
npm install date-time-format-icu
```
or with yarn:
```bash
yarn add date-time-format-icu
```
## Built-in Presets (DateFormat Enum)
You can use the DateFormat enum for common date and time format presets:
<table style="border-collapse: collapse; width: 100%; font-family: Arial, sans-serif;">
<thead>
<tr>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Key</th>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Pattern</th>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Example Output</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">short</td>
<td style="border: 1px solid #ccc; padding: 8px;">'M/d/yy, h:mm a'</td>
<td style="border: 1px solid #ccc; padding: 8px;">5/29/25, 2:15 PM</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">medium</td>
<td style="border: 1px solid #ccc; padding: 8px;">'MMM d, y, h:mm:ss a'</td>
<td style="border: 1px solid #ccc; padding: 8px;">May 29, 2025, 2:15:30 PM</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">long</td>
<td style="border: 1px solid #ccc; padding: 8px;">'MMMM d, y, h:mm:ss a z'</td>
<td style="border: 1px solid #ccc; padding: 8px;">May 29, 2025, 2:15:30 PM GMT+5</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">full</td>
<td style="border: 1px solid #ccc; padding: 8px;">'EEEE, MMMM d, y, h:mm:ss a zzzz'</td>
<td style="border: 1px solid #ccc; padding: 8px;">Thursday, May 29, 2025, 2:15:30 PM Pakistan Standard Time</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">shortDate</td>
<td style="border: 1px solid #ccc; padding: 8px;">'M/d/yy'</td>
<td style="border: 1px solid #ccc; padding: 8px;">5/29/25</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">mediumDate</td>
<td style="border: 1px solid #ccc; padding: 8px;">'MMM d, y'</td>
<td style="border: 1px solid #ccc; padding: 8px;">May 29, 2025</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">longDate</td>
<td style="border: 1px solid #ccc; padding: 8px;">'MMMM d, y'</td>
<td style="border: 1px solid #ccc; padding: 8px;">May 29, 2025</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">fullDate</td>
<td style="border: 1px solid #ccc; padding: 8px;">'EEEE, MMMM d, y'</td>
<td style="border: 1px solid #ccc; padding: 8px;">Thursday, May 29, 2025</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">shortTime</td>
<td style="border: 1px solid #ccc; padding: 8px;">'h:mm a'</td>
<td style="border: 1px solid #ccc; padding: 8px;">2:15 PM</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">mediumTime</td>
<td style="border: 1px solid #ccc; padding: 8px;">'h:mm:ss a'</td>
<td style="border: 1px solid #ccc; padding: 8px;">2:15:30 PM</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">longTime</td>
<td style="border: 1px solid #ccc; padding: 8px;">'h:mm:ss a z'</td>
<td style="border: 1px solid #ccc; padding: 8px;">2:15:30 PM GMT+5</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">fullTime</td>
<td style="border: 1px solid #ccc; padding: 8px;">'h:mm:ss a zzzz'</td>
<td style="border: 1px solid #ccc; padding: 8px;">2:15:30 PM Pakistan Standard Time</td>
</tr>
</tbody>
</table>
## Custom Formats
The formatter supports a subset of ICU/Angular-style date tokens:
<table style="border-collapse: collapse; width: 100%; font-family: Arial, sans-serif;">
<thead>
<tr>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Token</th>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Meaning</th>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Example</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">y</td>
<td style="border: 1px solid #ccc; padding: 8px;">Year (numeric)</td>
<td style="border: 1px solid #ccc; padding: 8px;">2025</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">yy</td>
<td style="border: 1px solid #ccc; padding: 8px;">Year (2-digit)</td>
<td style="border: 1px solid #ccc; padding: 8px;">25</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">M</td>
<td style="border: 1px solid #ccc; padding: 8px;">Month (numeric)</td>
<td style="border: 1px solid #ccc; padding: 8px;">5</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">MM</td>
<td style="border: 1px solid #ccc; padding: 8px;">Month (2-digit)</td>
<td style="border: 1px solid #ccc; padding: 8px;">05</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">MMM</td>
<td style="border: 1px solid #ccc; padding: 8px;">Month (short text)</td>
<td style="border: 1px solid #ccc; padding: 8px;">May</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">MMMM</td>
<td style="border: 1px solid #ccc; padding: 8px;">Month (full text)</td>
<td style="border: 1px solid #ccc; padding: 8px;">May</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">d</td>
<td style="border: 1px solid #ccc; padding: 8px;">Day (numeric)</td>
<td style="border: 1px solid #ccc; padding: 8px;">9</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">dd</td>
<td style="border: 1px solid #ccc; padding: 8px;">Day (2-digit)</td>
<td style="border: 1px solid #ccc; padding: 8px;">09</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">EEE</td>
<td style="border: 1px solid #ccc; padding: 8px;">Weekday (short)</td>
<td style="border: 1px solid #ccc; padding: 8px;">Thu</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">EEEE</td>
<td style="border: 1px solid #ccc; padding: 8px;">Weekday (long)</td>
<td style="border: 1px solid #ccc; padding: 8px;">Thursday</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">h/hh</td>
<td style="border: 1px solid #ccc; padding: 8px;">Hour (12-hour)</td>
<td style="border: 1px solid #ccc; padding: 8px;">2 / 02</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">H/HH</td>
<td style="border: 1px solid #ccc; padding: 8px;">Hour (24-hour)</td>
<td style="border: 1px solid #ccc; padding: 8px;">14 / 14</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">m/mm</td>
<td style="border: 1px solid #ccc; padding: 8px;">Minute</td>
<td style="border: 1px solid #ccc; padding: 8px;">5 / 05</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">s/ss</td>
<td style="border: 1px solid #ccc; padding: 8px;">Second</td>
<td style="border: 1px solid #ccc; padding: 8px;">9 / 09</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">a</td>
<td style="border: 1px solid #ccc; padding: 8px;">AM/PM</td>
<td style="border: 1px solid #ccc; padding: 8px;">PM</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">z</td>
<td style="border: 1px solid #ccc; padding: 8px;">Time zone (short)</td>
<td style="border: 1px solid #ccc; padding: 8px;">GMT+5</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">zzzz</td>
<td style="border: 1px solid #ccc; padding: 8px;">Time zone (long)</td>
<td style="border: 1px solid #ccc; padding: 8px;">Pakistan Standard Time</td>
</tr>
</tbody>
</table>
## Function: `dateFormatter`
The core utility function of this package is:
```ts
dateFormatter(
input: Date | string | number,
format?: keyof typeof DateFormat | string,
locale?: string
): string
```
### Parameters
<table style="border-collapse: collapse; width: 100%; font-family: Arial, sans-serif;">
<thead>
<tr>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Parameter</th>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Type</th>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Default</th>
<th style="border: 1px solid #ccc; padding: 8px; background-color: #f2f2f2;">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">input</td>
<td style="border: 1px solid #ccc; padding: 8px;">Date | string | number</td>
<td style="border: 1px solid #ccc; padding: 8px;">Required</td>
<td style="border: 1px solid #ccc; padding: 8px;">
The input date to format. Can be a <code style="background-color: #f4f4f4; padding: 2px 4px; border-radius: 4px;">Date</code> object, ISO string (<code>'2025-12-25T10:00:00'</code>), or a timestamp (<code>1735123200000</code>).
</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">format</td>
<td style="border: 1px solid #ccc; padding: 8px;">keyof DateFormat | string</td>
<td style="border: 1px solid #ccc; padding: 8px;">'medium'</td>
<td style="border: 1px solid #ccc; padding: 8px;">
A custom ICU/Angular-style format string (e.g. <code>'dd/MM/yy'</code>) or a key from the built-in <code>DateFormat</code> enum (<code>'short'</code>, <code>'fullTime'</code>, etc.).
</td>
</tr>
<tr>
<td style="border: 1px solid #ccc; padding: 8px;">locale</td>
<td style="border: 1px solid #ccc; padding: 8px;">string</td>
<td style="border: 1px solid #ccc; padding: 8px;">'en-US'</td>
<td style="border: 1px solid #ccc; padding: 8px;">
Locale code to control localization of month names, day names, AM/PM, etc. Examples: <code>'en-US'</code>, <code>'fr-FR'</code>, <code>'ur-PK'</code>.
</td>
</tr>
</tbody>
</table>
## Usage & Examples
```bash
// Import
import { dateFormatter } from 'date-time-format-icu';
// Basic Example
const formatted = dateFormatter(new Date(), 'medium');
console.log(formatted); // e.g., "May 29, 2025, 2:15:30 PM"
// With Custom Format
const custom = dateFormatter(new Date(), 'dd/MM/yy');
console.log(custom); // e.g., "29/05/25"
// With Custom Locale
const french = dateFormatter(new Date(), 'fullDate', 'fr-FR');
console.log(french); // e.g., "jeudi 29 mai 2025"
// Example Scenarios
dateFormatter('2025-12-25T10:00:00', 'fullDate');
// Output: "Thursday, December 25, 2025";
dateFormatter(1735123200000, 'MMM d, y');
// Output: "Dec 25, 2025"
dateFormatter('invalid-date', 'medium');
// Output: "Invalid Date"
```
## Notes
<ul style="font-family: Arial, sans-serif; padding-left: 20px; line-height: 1.6;">
<li style="margin-bottom: 8px;">
Falls back to <code style="background-color: #f4f4f4; padding: 2px 4px; border-radius: 4px;">date.toISOString()</code> if format parsing fails.
</li>
<li style="margin-bottom: 8px;">
Supports only tokens explicitly mapped to <code style="background-color: #f4f4f4; padding: 2px 4px; border-radius: 4px;">Intl.DateTimeFormatOptions</code>.
</li>
<li style="margin-bottom: 8px;">
Ideal for lightweight date formatting without pulling in larger libraries like <code style="background-color: #f4f4f4; padding: 2px 4px; border-radius: 4px;">date-fns</code> or <code style="background-color: #f4f4f4; padding: 2px 4px; border-radius: 4px;">moment</code>.
</li>
</ul>