Introducing a handy JavaScript date formatting function.
Tags: javascript, dateformat
Published: 2020-02-18 03:21:49

---
title:Introducing a handy JavaScript date formatting function.
published: true
description: Introducing a handy JavaScript date formatting function.
tags: JavaScript,Date format
cover_image: https://riversun.github.io/simple-date-format/formatedate_coverimage.png
---

I created A function to format the date (Date object) with a pattern like `yyyy-MM-dd'T'HH:mm:ssXXX` in JavaScript.
With this function alone, ISO8601 format, RFC1123 format, time zone RFC822, etc. can be expressed.
Pattern specification is like Java's [SimpleDateFormat](https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html).

# Date formatting function

```javascript
function formatDate(formatStr, date, opts) {

    if (!date) {
        date = new Date();
    }

    opts = opts || {};

    let _days = opts.days;

    if (!_days) {
        _days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    }

    let _months = opts.months;

    if (!_months) {
        _months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    }

    const pad = (number, strDigits, isUnpad) => {
        const strNum = Math.abs(number).toString();
        if (!isUnpad && strNum.length > strDigits.length) {
            return strNum;
        } else {
            return ('0000' + strNum).slice(-strDigits.length);
        }
    };

    const timezone = (date, letter) => {
        const chunk = [];
        const offset = -date.getTimezoneOffset();
        chunk.push(offset === 0 ? 'Z' : offset > 0 ? '+' : '-');//add Z or +,-
        if (offset === 0) return chunk;
        chunk.push(pad(Math.floor(offset / 60), '00'));//hour
        if (letter === 'X') return chunk.join('');
        if (letter === 'XXX') chunk.push(':');
        chunk.push(pad((offset % 60), '00'));//min
        return chunk.join('');
    };

    const DELIM = '\0\0';
    const escapeStack = [];

    const escapedFmtStr = formatStr.replace(/'.*?'/g, m => {
        escapeStack.push(m.replace(/'/g, ''));
        return `${DELIM}${escapeStack.length - 1}${DELIM}`;
    });

    const formattedStr = escapedFmtStr
        .replace(/y{4}|y{2}/g, m => pad(date.getFullYear(), m, true))
        .replace(/M{3}/g, m => _months[date.getMonth()])
        .replace(/M{1,2}/g, m => pad(date.getMonth() + 1, m))
        .replace(/M{1,2}/g, m => pad(date.getMonth() + 1, m))
        .replace(/d{1,2}/g, m => pad(date.getDate(), m))
        .replace(/H{1,2}/g, m => pad(date.getHours(), m))
        .replace(/h{1,2}/g, m => {
            const hours = date.getHours();
            return pad(hours === 0 ? 12 : hours > 12 ? hours - 12 : hours, m);
        })
        .replace(/a{1,2}/g, m => date.getHours() >= 12 ? 'PM' : 'AM')
        .replace(/m{1,2}/g, m => pad(date.getMinutes(), m))
        .replace(/s{1,2}/g, m => pad(date.getSeconds(), m))
        .replace(/S{3}/g, m => pad(date.getMilliseconds(), m))
        .replace(/[E]+/g, m => _days[date.getDay()])
        .replace(/[Z]+/g, m => timezone(date, m))
        .replace(/X{1,3}/g, m => timezone(date, m));

    const unescapedStr = formattedStr.replace(new RegExp(`${DELIM}\\d+${DELIM}`, 'g'),
        m => {
            const unescaped = escapeStack.shift();
            return unescaped.length > 0 ? unescaped : '\'';
        });

    return unescapedStr;
}
```

## Call function like as follows

```javascript
const date = new Date();

//Format with patterns
console.log(formatDate("MMM dd, yyyy",date));
//->Feb 17, 2020

console.log(formatDate("MM/dd/yyyy",date));
//->02/17/2020

console.log(formatDate("EEE, MMM d, ''yy",date));
//->Mon, Feb 17, '20

console.log(formatDate("h:mm a",date));
//->8:46 PM

console.log(formatDate("hh 'o''''clock' a, Z",date));
//->08 o'clock PM, -0600

//ISO8601 format
console.log(formatDate("yyyyMMdd'T'HHmmssXX",date));
//->20200217T204746-0600

//ISO8601 format alt
console.log(formatDate("yyyy-MM-dd'T'HH:mm:ssXXX",date));
//->2020-02-17T20:47:46-06:00

//RFC1123(RFC822) format
console.log(formatDate("E, dd MMM yyyy HH:mm:ss Z",date));
//->Mon, 17 Feb 2020 20:47:46 -0600


```

The result is as follows:

```
Feb 17, 2020
02/17/2020
Mon, Feb 17, '20
8:47 PM
08 o'clock PM, -0600
20200217T204746-0600
2020-02-17T20:47:46-06:00
Mon, 17 Feb 2020 20:47:46 -0600
Mon, Feb 17, '20
Hello! It's 20:47:46.
```

{% codepen https://codepen.io/riversun/pen/YzXWwwO %}

## Pattern of the date
The following examples show how date and time patterns are interpreted.
The given date and time are 2018-07-17 12:08:56 local time in Tokyo/Japan time zone.

<table>
 <tr>
  <td>Letter(s)</td>
  <td>Date or Time Component</td>
  <td>Examples</td>
 </tr>
 <tr>
  <td>yyyy</td>
  <td>Year</td>
  <td>2018</td>
 </tr>
 <tr>
  <td>yy</td>
  <td></td>
  <td>18</td>
 </tr>
 <tr>
  <td>M</td>
  <td>Month in year</td>
  <td>7</td>
 </tr>
 <tr>
  <td>MM</td>
  <td></td>
  <td>07</td>
 </tr>
 <tr>
  <td>MMM</td>
  <td>Month name</td>
  <td>Jul</td>
 </tr>
 <tr>
  <td>d</td>
  <td>Day in month</td>
  <td>17</td>
 </tr>
 <tr>
  <td>dd</td>
  <td></td>
  <td>17</td>
 </tr>
 <tr>
  <td>a</td>
  <td>Am/pm marker</td>
  <td>PM</td>
 </tr>
 <tr>
  <td>H</td>
  <td>Hour in day (0-23)</td>
  <td>12</td>
 </tr>
 <tr>
  <td>HH</td>
  <td></td>
  <td>12</td>
 </tr>
 <tr>
  <td>E</td>
  <td>day of week</td>
  <td>Tue</td>
 </tr>
 <tr>
  <td>h</td>
  <td>Hour in am/pm (1-12)</td>
  <td>12</td>
 </tr>
 <tr>
  <td>hh</td>
  <td></td>
  <td>12</td>
 </tr>
 <tr>
  <td>m</td>
  <td>Minute in hour</td>
  <td>8</td>
 </tr>
 <tr>
  <td>mm</td>
  <td></td>
  <td>08</td>
 </tr>
 <tr>
  <td>s</td>
  <td>Second in minute</td>
  <td>56</td>
 </tr>
 <tr>
  <td>ss</td>
  <td></td>
  <td>56</td>
 </tr>
 <tr>
  <td>S</td>
  <td>Millisecond</td>
  <td>789</td>
 </tr>
 <tr>
  <td>Z</td>
  <td>Timezone(RFC822)</td>
  <td>+0900</td>
 </tr>
 <tr>
  <td>X</td>
  <td>Timezone(ISO8601)</td>
  <td>+09</td>
 </tr>
 <tr>
  <td>XX</td>
  <td></td>
  <td>+0900</td>
 </tr>
 <tr>
  <td>XXX</td>
  <td></td>
  <td>+09:00</td>
 </tr>
 <tr>
  <td>' '</td>
  <td>Strings(Escaped)</td>
  <td></td>
 </tr>
 <tr>
  <td>''</td>
  <td>Single Quote</td>
  <td></td>
 </tr>
</table>

# Pattern examples

<table>
 <tr>
  <td>Format String</td>
  <td>Example</td>
 </tr>
 <tr>
  <td>yyyyMMdd'T'HHmmssXX<br>(ISO 8601)</td>
  <td>20180717T120856+0900</td>
 </tr>
 <tr>
  <td>yyyy-MM-dd'T'HH:mm:ssXXX<br>(ISO 8601)</td>
  <td>2018-07-17T12:08:56+09:00</td>
 </tr>
 <tr>
  <td>E, dd MMM yyyy HH:mm:ss Z</td>
  <td>Tue, 17 Jul 2018 12:08:56 +0900</td>
 </tr>
 <tr>
  <td>yyyy.MM.dd 'at' hh:mm:ss Z</td>
  <td>2018.07.17 at 12:08:56 +0900</td>
 </tr>
 <tr>
  <td>EEE, MMM d, ''yy</td>
  <td>Tue, Jul 17, '18</td>
 </tr>
 <tr>
  <td>h:mm a</td>
  <td>12:08 PM</td>
 </tr>
 <tr>
  <td>hh 'o''''clock' a, X</td>
  <td>12 o'clock PM, +09</td>
 </tr>
 <tr>
  <td>yyyyMMddHHmmssSSS</td>
  <td>20180717120856789</td>
 </tr>
</table>


# Live demo

{% codepen https://codepen.io/riversun/pen/ZEGWdKE %}

# Repository

The library version is in the following repository for ease of use.

https://github.com/riversun/simple-date-format