vanilla_date_format_date_index.js
const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
const suffs = ['th', 'st', 'nd', 'rd']
const pad = s => (s < 10 ? `0${s}` : `${s}`)
const ordinal = n => n + (suffs[((n % 100) - 20) % 10] || suffs[n % 100] || suffs[0])
const formatCache = new Map()
const formats = {
/* eslint-disable id-match */
YY: d => String(d.getFullYear()).slice(-2),
YYYY: d => d.getFullYear(),
M: d => d.getMonth() + 1,
MM: d => pad(d.getMonth() + 1),
MMM: d => months[d.getMonth()].slice(0, 3),
MMMM: d => months[d.getMonth()],
D: d => d.getDate(),
DD: d => pad(d.getDate()),
d: d => d.getDay(),
dd: d => days[d.getDay()].slice(0, 1),
ddd: d => days[d.getDay()].slice(0, 3),
dddd: d => days[d.getDay()],
Do: d => ordinal(d.getDate()),
H: d => d.getHours(),
HH: d => pad(d.getHours()),
h: d => d.getHours() % 12 || 12,
hh: d => pad(d.getHours() % 12 || 12),
m: d => d.getMinutes(),
mm: d => pad(d.getMinutes()),
s: d => d.getSeconds(),
ss: d => pad(d.getSeconds()),
SSS: d => d.getMilliseconds(),
A: d => (d.getHours() >= 12 ? 'PM' : 'AM'),
a: d => (d.getHours() >= 12 ? 'pm' : 'am')
/* eslint-enable id-match */
}
const formatRegex = /{([^{}]+)}/g
/**
* @module formatDate
* @description Creates a nice formatted date from a unix timestamp
* @memberof Vanilla
* @version 3.0.0
* @param {string} str - string containing formats ie. {YYYY}
* @param {Date|number|string} [date] - Date object, timestamp, or date string
* @returns {string} Formatted date string
*/
export function formatDate(str, date = new Date()) {
const d = date instanceof Date ? date : new Date(date)
let formatFunc = formatCache.get(str)
if (!formatFunc) {
const parts = []
let lastIndex = 0
str.replace(formatRegex, (match, f, index) => {
if (index > lastIndex) {
parts.push(str.slice(lastIndex, index))
}
if (!formats[f]) {
throw new Error(`{${f}} is an invalid format. Valid formats are: ${Object.keys(formats).join(', ')}`)
}
parts.push(formats[f])
lastIndex = index + match.length
})
if (lastIndex < str.length) {
parts.push(str.slice(lastIndex))
}
formatFunc = date => parts.map(part => (typeof part === 'function' ? part(date) : part)).join('')
formatCache.set(str, formatFunc)
}
return formatFunc(d)
}