tui-code-snippet
Version:
TOAST UI Utility: CodeSnippet
238 lines (213 loc) • 6 kB
JavaScript
/**
* @fileoverview This module has a function for date format.
* @author NHN FE Development Lab <dl_javascript@nhn.com>
*/
;
var pick = require('../object/pick');
var isDate = require('../type/isDate');
var tokens = /[\\]*YYYY|[\\]*YY|[\\]*MMMM|[\\]*MMM|[\\]*MM|[\\]*M|[\\]*DD|[\\]*D|[\\]*HH|[\\]*H|[\\]*A/gi;
var MONTH_STR = [
'Invalid month', 'January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September', 'October', 'November', 'December'
];
var MONTH_DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var replaceMap = {
M: function(date) {
return Number(date.month);
},
MM: function(date) {
var month = date.month;
return (Number(month) < 10) ? '0' + month : month;
},
MMM: function(date) {
return MONTH_STR[Number(date.month)].substr(0, 3);
},
MMMM: function(date) {
return MONTH_STR[Number(date.month)];
},
D: function(date) {
return Number(date.date);
},
d: function(date) {
return replaceMap.D(date); // eslint-disable-line new-cap
},
DD: function(date) {
var dayInMonth = date.date;
return (Number(dayInMonth) < 10) ? '0' + dayInMonth : dayInMonth;
},
dd: function(date) {
return replaceMap.DD(date); // eslint-disable-line new-cap
},
YY: function(date) {
return Number(date.year) % 100;
},
yy: function(date) {
return replaceMap.YY(date); // eslint-disable-line new-cap
},
YYYY: function(date) {
var prefix = '20',
year = date.year;
if (year > 69 && year < 100) {
prefix = '19';
}
return (Number(year) < 100) ? prefix + String(year) : year;
},
yyyy: function(date) {
return replaceMap.YYYY(date); // eslint-disable-line new-cap
},
A: function(date) {
return date.meridiem;
},
a: function(date) {
return date.meridiem;
},
hh: function(date) {
var hour = date.hour;
return (Number(hour) < 10) ? '0' + hour : hour;
},
HH: function(date) {
return replaceMap.hh(date);
},
h: function(date) {
return String(Number(date.hour));
},
H: function(date) {
return replaceMap.h(date);
},
m: function(date) {
return String(Number(date.minute));
},
mm: function(date) {
var minute = date.minute;
return (Number(minute) < 10) ? '0' + minute : minute;
}
};
/**
* Check whether the given variables are valid date or not.
* @param {number} year - Year
* @param {number} month - Month
* @param {number} date - Day in month.
* @returns {boolean} Is valid?
* @private
*/
function isValidDate(year, month, date) { // eslint-disable-line complexity
var isValidYear, isValidMonth, isValid, lastDayInMonth;
year = Number(year);
month = Number(month);
date = Number(date);
isValidYear = (year > -1 && year < 100) || ((year > 1969) && (year < 2070));
isValidMonth = (month > 0) && (month < 13);
if (!isValidYear || !isValidMonth) {
return false;
}
lastDayInMonth = MONTH_DAYS[month];
if (month === 2 && year % 4 === 0) {
if (year % 100 !== 0 || year % 400 === 0) {
lastDayInMonth = 29;
}
}
isValid = (date > 0) && (date <= lastDayInMonth);
return isValid;
}
/**
* @module formatDate
*/
/**
* Return a string that transformed from the given form and date.
* @param {string} form - Date form
* @param {Date|Object} date - Date object
* @param {{meridiemSet: {AM: string, PM: string}}} option - Option
* @returns {boolean|string} A transformed string or false.
* @memberof module:formatDate
* @example
* // key | Shorthand
* // --------------- |-----------------------
* // years | YY / YYYY / yy / yyyy
* // months(n) | M / MM
* // months(str) | MMM / MMMM
* // days | D / DD / d / dd
* // hours | H / HH / h / hh
* // minutes | m / mm
* // meridiem(AM,PM) | A / a
*
* // ES6
* import formatDate from 'tui-code-snippet/formatDate/formatDate';
*
* // CommonJS
* const formatDate = require('tui-code-snippet/formatDate/formatDate');
*
* const dateStr1 = formatDate('yyyy-MM-dd', {
* year: 2014,
* month: 12,
* date: 12
* });
* alert(dateStr1); // '2014-12-12'
*
* const dateStr2 = formatDate('MMM DD YYYY HH:mm', {
* year: 1999,
* month: 9,
* date: 9,
* hour: 0,
* minute: 2
* });
* alert(dateStr2); // 'Sep 09 1999 00:02'
*
* const dt = new Date(2010, 2, 13),
* dateStr3 = formatDate('yyyy년 M월 dd일', dt);
* alert(dateStr3); // '2010년 3월 13일'
*
* const option4 = {
* meridiemSet: {
* AM: '오전',
* PM: '오후'
* }
* };
*
* const date4 = {year: 1999, month: 9, date: 9, hour: 13, minute: 2};
* const dateStr4 = formatDate('yyyy-MM-dd A hh:mm', date4, option4);
* alert(dateStr4); // '1999-09-09 오후 01:02'
*/
function formatDate(form, date, option) { // eslint-disable-line complexity
var am = pick(option, 'meridiemSet', 'AM') || 'AM';
var pm = pick(option, 'meridiemSet', 'PM') || 'PM';
var meridiem, nDate, resultStr;
if (isDate(date)) {
nDate = {
year: date.getFullYear(),
month: date.getMonth() + 1,
date: date.getDate(),
hour: date.getHours(),
minute: date.getMinutes()
};
} else {
nDate = {
year: date.year,
month: date.month,
date: date.date,
hour: date.hour,
minute: date.minute
};
}
if (!isValidDate(nDate.year, nDate.month, nDate.date)) {
return false;
}
nDate.meridiem = '';
if (/([^\\]|^)[aA]\b/.test(form)) {
meridiem = (nDate.hour > 11) ? pm : am;
if (nDate.hour > 12) { // See the clock system: https://en.wikipedia.org/wiki/12-hour_clock
nDate.hour %= 12;
}
if (nDate.hour === 0) {
nDate.hour = 12;
}
nDate.meridiem = meridiem;
}
resultStr = form.replace(tokens, function(key) {
if (key.indexOf('\\') > -1) { // escape character
return key.replace(/\\/, '');
}
return replaceMap[key](nDate) || '';
});
return resultStr;
}
module.exports = formatDate;