<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>@riversun/formatDate</title>
</head>
<body>
<h3>@riversun/formatDate demo</h3>
<div id="preview"></div>
</body>
</html>
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;
}
const patterns = [
"yyyyMMdd'T'HHmmssXX",//ISO8601
"yyyy-MM-dd'T'HH:mm:ssXXX",//ISO8601EX
"E, dd MMM yyyy HH:mm:ss Z",//RFC1123(RFC822) like email
"yyyy.MM.dd 'at' hh:mm:ss Z",//hh shows 1-12
"EEE, MMM d, ''yy",
"h:mm a",
"hh 'o''''clock' a, X",
"yyyy年M月d日 H時m分s秒",
"yyyy年MM月dd日 HH時mm分ss秒",
"yyyyMMddHHmmssSSS"
];
const preview = document.querySelector('#preview');
const updateDate = () => {
const now = new Date();
preview.innerHTML = `Now : ${now}<br><br>`;
for (const pattern of patterns) {
preview.innerHTML += `${pattern} → ${formatDate(pattern, now)}<br>`;
}
setTimeout(updateDate, 500);
}
updateDate();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.