---
title: System Functions - Done
slug: system-functions-done
createdAt: 2025-01-06T23:23:03.957Z
---

# Format Date

## Function

formatDate(date, pattern, isInputUTC, outputTZ)

## Description

The `formatDate` function is designed for developers integrating it into various applications to handle date and time formatting across different timezones seamlessly.

- **Automatic Timezone Detection:**
  - By default, the function detects the user's (client's) timezone using `dayjs.tz.guess()`. This makes it ideal for client-side applications where the user's timezone can be accurately determined.
- **Client-Side Optimization:**
  - Since the function automatically detects the local timezone, it is primarily intended to be run client-side. This ensures that the formatted dates align with the user's local settings.
- **Server-Side Usage:**
  - When running the function server-side, `dayjs.tz.guess()` may detect the server's timezone instead of the client's. To maintain consistency and avoid discrepancies, it is recommended to always set `isInputUTC` to `true` when using the function in a server-side environment. This treats the input date as UTC, ensuring that the output remains consistent regardless of the server's timezone.
- **Timezone Handling:**
  - **Input Timezone:** Developers can specify if the input date is in UTC by setting the `isInputUTC` parameter to `true`. If not specified, the function uses the detected local timezone.
  - **Output Timezones:** Developers can specify one or more additional output timezones. Regardless of the specified timezones, UTC is always included in the output.
- **Flexible Formatting:**
  - Utilizes [dayjs formatting tokens](https://day.js.org/docs/en/display/format) to allow customizable date and time representations.
- **Validation:**
  - Validates the input `Date` object and the format pattern to ensure accurate formatting.
  - Handles invalid timezone inputs gracefully by skipping them and logging warnings, while still including UTC in the output.
- **Consistent Output Structure:**
  - Returns an object containing:
    - `isValid`: A boolean indicating the validity of the input date.
    - `formattedDates`: An object mapping each specified timezone (including UTC) to its corresponding formatted date string.

## Notes

- **Assumed Local Timezone:**
  - For the examples provided, it's assumed that the user's local timezone is **America/New\_York (UTC-5)**. If your local timezone differs, adjust the expected outputs accordingly.
- **Handling Invalid Timezones:**
  - If an invalid timezone is provided in `outputTZ`, the function will skip it and log a warning to the console. UTC will still be included in the output.
- **Default Behavior:**
  - If `outputTZ` is not specified, the function defaults to including both `'Local'` and `'UTC'` formatted dates.
- **Including UTC Always:**
  - The `formatDate` function is designed to **always** include UTC in the output, ensuring a consistent reference point regardless of other specified timezones.
- **Pattern Flexibility:**
  - Ensure that the `pattern` provided is compatible with `dayjs` formatting tokens to achieve the desired date and time representations.

## Usage Scenarios:

- **Default Formatting:** Format a date using the local timezone and UTC.
- **Specify Input as UTC:** Indicate that the input date is in UTC and format accordingly, especially useful in server-side applications.
- **Multiple Output Timezones:** Obtain formatted dates in multiple timezones alongside UTC.
- **Handle Invalid Inputs:** Safely handle invalid dates or timezones without disrupting the output structure.

## Prerequisites

Install the dayjs library using npm:

```bash
npm install dayjs
npm install dayjs-plugin-utc
npm install dayjs-plugin-timezone
```

## Parameters

| Parameter    | Type                   | Description                                                                                               |
| ------------ | ---------------------- | --------------------------------------------------------------------------------------------------------- |
| `date`       | `Date`                 | The Date object to format.                                                                                |
| `pattern`    | `string`               | The format pattern following [dayjs formatting tokens](https://day.js.org/docs/en/display/format).        |
| `isInputUTC` | `boolean`              | (Optional) If set to `true`, the input date is treated as UTC. Defaults to `false` (uses local timezone). |
| `outputTZ`   | `string` or `string[]` | (Optional) Specifies additional output timezones. UTC is always included in the output.                   |

### Date Pattern Tokens

The `pattern` string in the `formatDate` function uses `dayjs` formatting tokens to define the output format. Below is a table of common tokens you can use:

| Token  | Description                               | Example Output |
| ------ | ----------------------------------------- | -------------- |
| `YYYY` | 4-digit year                              | `2025`         |
| `YY`   | 2-digit year                              | `25`           |
| `MMMM` | Full name of the month                    | `January`      |
| `MMM`  | Abbreviated name of the month             | `Jan`          |
| `MM`   | 2-digit month                             | `01`           |
| `M`    | Month without leading zero                | `1`            |
| `DD`   | 2-digit day of the month                  | `07`           |
| `D`    | Day of the month without leading zero     | `7`            |
| `dddd` | Full name of the day of the week          | `Tuesday`      |
| `ddd`  | Abbreviated name of the day of the week   | `Tue`          |
| `HH`   | 2-digit hour (24-hour clock)              | `14`           |
| `H`    | Hour without leading zero (24-hour clock) | `14`           |
| `hh`   | 2-digit hour (12-hour clock)              | `02`           |
| `h`    | Hour without leading zero (12-hour clock) | `2`            |
| `mm`   | 2-digit minutes                           | `35`           |
| `m`    | Minutes without leading zero              | `5`            |
| `ss`   | 2-digit seconds                           | `09`           |
| `s`    | Seconds without leading zero              | `9`            |
| `A`    | AM/PM marker (uppercase)                  | `PM`           |
| `a`    | am/pm marker (lowercase)                  | `pm`           |
| `Z`    | UTC offset (e.g., `+05:00`)               | `+05:00`       |
| `ZZ`   | UTC offset without colon (e.g., `+0500`)  | `+0500`        |

For a complete list of tokens, refer to the [dayjs documentation](https://day.js.org/docs/en/display/format).

### Timezone Patterns

The `inputTZ` and `outputTZ` parameters accept [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) identifiers. Below is a table of common timezone options you can use. For a complete list, refer to the [IANA Time Zone Database](https://www.iana.org/time-zones).

| Timezone Identifier              | Location                    | Description                                                                                   |
| -------------------------------- | --------------------------- | --------------------------------------------------------------------------------------------- |
| `UTC`                            | Coordinated Universal Time  | The primary time standard by which the world regulates clocks and time.                       |
| `America/New_York`               | Eastern Time (US & Canada)  | Observes Eastern Standard Time (EST) and Eastern Daylight Time (EDT).                         |
| `America/Chicago`                | Central Time (US & Canada)  | Observes Central Standard Time (CST) and Central Daylight Time (CDT).                         |
| `America/Denver`                 | Mountain Time (US & Canada) | Observes Mountain Standard Time (MST) and Mountain Daylight Time (MDT).                       |
| `America/Los_Angeles`            | Pacific Time (US & Canada)  | Observes Pacific Standard Time (PST) and Pacific Daylight Time (PDT).                         |
| `Europe/London`                  | London, United Kingdom      | Observes Greenwich Mean Time (GMT) and British Summer Time (BST).                             |
| `Europe/Berlin`                  | Berlin, Germany             | Observes Central European Time (CET) and Central European Summer Time (CEST).                 |
| `Europe/Moscow`                  | Moscow, Russia              | Observes Moscow Standard Time (MSK).                                                          |
| `Asia/Tokyo`                     | Tokyo, Japan                | Observes Japan Standard Time (JST).                                                           |
| `Asia/Shanghai`                  | Shanghai, China             | Observes China Standard Time (CST).                                                           |
| `Asia/Kolkata`                   | Kolkata, India              | Observes India Standard Time (IST).                                                           |
| `Australia/Sydney`               | Sydney, Australia           | Observes Australian Eastern Standard Time (AEST) and Australian Eastern Daylight Time (AEDT). |
| `Pacific/Auckland`               | Auckland, New Zealand       | Observes New Zealand Standard Time (NZST) and New Zealand Daylight Time (NZDT).               |
| `America/Sao_Paulo`              | São Paulo, Brazil           | Observes Brasília Time (BRT) and Brasília Summer Time (BRST).                                 |
| `America/Argentina/Buenos_Aires` | Buenos Aires, Argentina     | Observes Argentina Time (ART).                                                                |
| `Africa/Johannesburg`            | Johannesburg, South Africa  | Observes South Africa Standard Time (SAST).                                                   |
| `Asia/Dubai`                     | Dubai, United Arab Emirates | Observes Gulf Standard Time (GST).                                                            |
| `Asia/Singapore`                 | Singapore                   | Observes Singapore Standard Time (SGT).                                                       |
| `Asia/Bangkok`                   | Bangkok, Thailand           | Observes Indochina Time (ICT).                                                                |
| `Asia/Hong_Kong`                 | Hong Kong                   | Observes Hong Kong Time (HKT).                                                                |
| `America/Denver`                 | Denver, USA                 | Observes Mountain Time (MT).                                                                  |
| `America/Vancouver`              | Vancouver, Canada           | Observes Pacific Time (PT).                                                                   |

### Timezone Notes

- **Case Sensitivity**: Timezone identifiers are case-sensitive. Ensure that you use the correct casing (e.g., America/New\_York not america/new\_york).
- **Daylight Saving Time (DST)**: Many timezones observe DST. The dayjs library automatically adjusts for DST based on the provided timezone.
- **Invalid Timezones**: If an invalid timezone identifier is provided, the function will return that the date is invalid. Ensure that the timezone strings used are valid IANA identifiers.

## Return Value

The function returns an object containing the validity of the date and the formatted date string.

| Property      | Type    | Description                                                                                                 |
| ------------- | ------- | ----------------------------------------------------------------------------------------------------------- |
| isValid       | boolean | true if the date is valid and formatted successfully, false otherwise.                                      |
| formattedDate | string  | The formatted date string based on the provided pattern. If isValid is false, this will be an empty string. |

## Notes

- Assumed Local Timezone:
  - For these examples, it's assumed that the user's local timezone is America/New\_York (UTC-5). If your local timezone differs, adjust the expected outputs accordingly.
- Function Parameters Explained:
  - `date` (`Date`): The date to be formatted.
  - `pattern` (`string`): The format pattern following [dayjs formatting tokens](https://day.js.org/docs/en/display/format).
  - `isInputUTC` (`boolean`, optional): If set to `true`, the input date is treated as UTC. Defaults to `false` (uses the user's local timezone).
  - `outputTZ` (`string` or `string[]`, optional): Specifies additional output timezones. UTC is always included in the output.
- Handling Invalid Timezones:
  - If an invalid timezone is provided in `outputTZ`, the function will skip it and log a warning to the console. UTC will still be included in the output.
- Default Behavior:
  - If `outputTZ` is not specified, the function defaults to including both 'Local' and 'UTC' formatted dates.
- Including UTC Always:
  - The `formatDate` function is designed to **always** include UTC in the output, ensuring a consistent reference point regardless of other specified timezones.
- Pattern Flexibility:
  - Ensure that the `pattern` provided is compatible with `dayjs` formatting tokens to achieve the desired date and time representations.

## Example Usage

| Description                                 | Input                                                                                                        | Output                                                                                                                                                                                    |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Valid Date in `YYYY-MM-DD` Format           | `formatDate(new Date('2025-01-07T14:35:12Z'), 'YYYY-MM-DD')`                                                 | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"Local": "2025-01-07",<br />"UTC": "2025-01-07"<br />}<br />}                                                                |
| Full Day and Month Names with Time          | `formatDate(new Date('2025-01-07T14:35:12Z'), 'dddd, MMMM D, YYYY hh:mm A')`                                 | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"Local": "Tuesday, January 7, 2025 09:35 AM",<br />"UTC": "Tuesday, January 7, 2025 02:35 PM"<br />}<br />}                  |
| Date in Abbreviated Day and Month Format    | `formatDate(new Date('2025-01-07T14:35:12Z'), 'ddd, MMM D, YY')`                                             | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"Local": "Tue, Jan 7, 25",<br />"UTC": "Tue, Jan 7, 25"<br />}<br />}                                                        |
| Time in 12-Hour Clock with Minutes          | `formatDate(new Date('2025-01-07T14:35:12Z'), 'hh:mm A')`                                                    | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"Local": "09:35 AM",<br />"UTC": "02:35 PM"<br />}<br />}                                                                    |
| Invalid Date Object                         | `formatDate(new Date('invalid-date'), 'YYYY-MM-DD')`                                                         | \{<br />"isValid": false,<br />"formattedDates": \{}<br />}                                                                                                                               |
| Specifying a Single Output Timezone         | `formatDate(new Date('2025-01-07T14:35:12Z'), 'YYYY-MM-DD hh A', true, 'America/New_York')`                  | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"UTC": "2025-01-07 02 PM",<br />"America/New\_York": "2025-01-07 09 AM"<br />}<br />}                                        |
| Specifying Multiple Output Timezones        | `formatDate(new Date('2025-01-07T14:35:12Z'), 'YYYY-MM-DD hh A', true, ['America/New_York', 'Asia/Tokyo'])`  | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"UTC": "2025-01-07 02 PM",<br />"America/New\_York": "2025-01-07 09 AM",<br />"Asia/Tokyo": "2025-01-07 11 PM"<br />}<br />} |
| Combining Default and Specified Timezones   | `formatDate(new Date('2025-01-07T14:35:12Z'), 'YYYY-MM-DD hh A', true, ['Local', 'Asia/Tokyo'])`             | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"UTC": "2025-01-07 02 PM",<br />"Local": "2025-01-07 09 AM",<br />"Asia/Tokyo": "2025-01-07 11 PM"<br />}<br />}             |
| Handling Invalid Output Timezones           | `formatDate(new Date('2025-01-07T14:35:12Z'), 'YYYY-MM-DD hh A', true, ['Invalid/Timezone', 'Asia/Tokyo'])`  | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"UTC": "2025-01-07 02 PM",<br />"Asia/Tokyo": "2025-01-07 11 PM"<br />}<br />}                                               |
| Non-String Pattern                          | `formatDate(new Date(), 12345)`                                                                              | \{<br />"isValid": false,<br />"formattedDates": \{}<br />}                                                                                                                               |
| Default Behavior (Local and UTC)            | `formatDate(new Date('2025-01-07T14:35:12Z'), 'YYYY-MM-DD HH:mm A')`                                         | \{<br />"isValid": true,<br />"formattedDates":<br />\{<br />"Local": "2025-01-07 09:35 AM",<br />"UTC": "2025-01-07 02:35 PM"<br />}<br />}                                              |
| Specifying Output Timezone Only             | `formatDate(new Date('2025-01-07T14:35:12Z'), 'dddd, MMMM D, YYYY h:mm A', false, 'Europe/London')`          | \{<br />"isValid": true,<br />"formattedDates":<br />\{ "UTC": "Tuesday, January 7, 2025 02:35 PM",<br />"Europe/London": "Tuesday, January 7, 2025 02:35 PM"<br />}<br />}               |
| Multiple Output Timezones Including Default | `formatDate(new Date('2025-01-07T14:35:12Z'), 'YYYY-MM-DD HH:mm A', true, ['Local', 'UTC', 'Asia/Kolkata'])` | \{<br />"isValid": true,<br />"formattedDates":<br />\{ "UTC": "2025-01-07 02:35 PM",<br />"Local": "2025-01-07 09:35 AM",<br />"Asia/Kolkata": "2025-01-07 08:05 PM"<br />}<br />}       |

## Script

```javascript
const dayjs = require('dayjs');
const utc = require('dayjs/plugin/utc');
const timezone = require('dayjs/plugin/timezone');

// Extend dayjs with necessary plugins
dayjs.extend(utc);
dayjs.extend(timezone);

/**
 * Formats a given Date object into specified patterns using dayjs.
 *
 * @param {Date} date - The Date object to format.
 * @param {string} pattern - The pattern defining the output format.
 * @param {boolean} [isInputUTC=false] - (Optional) If true, treats the input date as UTC. Otherwise, uses the user's local timezone.
 * @param {string|string[]} [outputTZ] - (Optional) The timezone(s) for the output formatted date(s). Can be a single timezone string or an array of timezone strings.
 * @returns {{
 *   isValid: boolean,
 *   formattedDates: { [timezone: string]: string }
 * }} - An object containing the validity of the date and an object of formatted date strings keyed by timezone.
 *
 * @example
 * formatDate(new Date(), 'YYYY-MM-DD HH:mm'); 
 * // {
 * //   isValid: true,
 * //   formattedDates: {
 * //     'Local': "2025-01-07 09:35 AM",
 * //     'UTC': "2025-01-07 14:35 PM"
 * //   }
 * // }
 */
function formatDate(date, pattern, isInputUTC = false, outputTZ) {
  // Initialize return object
  const result = {
    isValid: false,
    formattedDates: {}
  };

  // Validate the date object
  if (!(date instanceof Date) || isNaN(date)) {
    return result; // isValid remains false, formattedDates is empty
  }

  // Validate the pattern
  if (typeof pattern !== 'string') {
    return result; // isValid remains false, formattedDates is empty
  }

  // Determine the input timezone
  const inputTZ = isInputUTC ? 'UTC' : dayjs.tz.guess();

  // Create a dayjs instance with input timezone
  let m;
  if (inputTZ === 'UTC') {
    m = dayjs.utc(date);
  } else {
    m = dayjs.tz(date, inputTZ);
  }

  // Check if the date is valid
  if (m.isValid()) {
    result.isValid = true;

    // Always include UTC
    result.formattedDates['UTC'] = m.clone().utc().format(pattern);

    // Prepare the list of additional output timezones
    let additionalTimezones = [];

    if (outputTZ) {
      if (Array.isArray(outputTZ)) {
        additionalTimezones = outputTZ;
      } else if (typeof outputTZ === 'string') {
        additionalTimezones = [outputTZ];
      } else {
        console.warn('outputTZ should be a string or an array of strings representing valid IANA timezones.');
      }
    } else {
      // Default to 'Local' if no outputTZ is specified
      additionalTimezones = ['Local'];
    }

    // Iterate over each specified output timezone and format the date
    additionalTimezones.forEach(tz => {
      let formattedDate = '';
      if (tz === 'Local') {
        const localTZ = dayjs.tz.guess();
        formattedDate = m.clone().tz(localTZ).format(pattern);
        result.formattedDates['Local'] = formattedDate;
      } else {
        // Validate the timezone
        if (dayjs.tz.zone(tz)) { // Checks if tz is a valid timezone
          formattedDate = m.clone().tz(tz).format(pattern);
          result.formattedDates[tz] = formattedDate;
        } else {
          console.warn(`Invalid timezone provided: "${tz}". Skipping this timezone.`);
        }
      }
    });
  }

  return result;
}
```

