3 * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
6 * Includes enhancements by Scott Trenda <scott.trenda.net>
7 * and Kris Kowal <cixar.com/~kris.kowal/>
9 * Accepts a date, a mask, or a date and a mask.
10 * Returns a formatted version of the given date.
11 * The date defaults to the current date/time.
12 * The mask defaults to dateFormat.masks.default.
18 var dateFormat = (function() {
19 var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZWN]|'[^']*'|'[^']*'/g;
20 var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g;
21 var timezoneClip = /[^-+\dA-Z]/g;
23 // Regexes and supporting functions are cached through closure
24 return function (date, mask, utc, gmt) {
26 // You can't provide utc if you skip other args (use the 'UTC:' mask prefix)
27 if (arguments.length === 1 && kindOf(date) === 'string' && !/\d/.test(date)) {
32 date = date || new Date;
34 if(!(date instanceof Date)) {
35 date = new Date(date);
39 throw TypeError('Invalid date');
42 mask = String(dateFormat.masks[mask] || mask || dateFormat.masks['default']);
44 // Allow setting the utc/gmt argument via the mask
45 var maskSlice = mask.slice(0, 4);
46 if (maskSlice === 'UTC:' || maskSlice === 'GMT:') {
49 if (maskSlice === 'GMT:') {
54 var _ = utc ? 'getUTC' : 'get';
55 var d = date[_ + 'Date']();
56 var D = date[_ + 'Day']();
57 var m = date[_ + 'Month']();
58 var y = date[_ + 'FullYear']();
59 var H = date[_ + 'Hours']();
60 var M = date[_ + 'Minutes']();
61 var s = date[_ + 'Seconds']();
62 var L = date[_ + 'Milliseconds']();
63 var o = utc ? 0 : date.getTimezoneOffset();
64 var W = getWeek(date);
65 var N = getDayOfWeek(date);
69 ddd: dateFormat.i18n.dayNames[D],
70 dddd: dateFormat.i18n.dayNames[D + 7],
73 mmm: dateFormat.i18n.monthNames[m],
74 mmmm: dateFormat.i18n.monthNames[m + 12],
75 yy: String(y).slice(2),
78 hh: pad(H % 12 || 12),
86 L: pad(Math.round(L / 10)),
87 t: H < 12 ? 'a' : 'p',
88 tt: H < 12 ? 'am' : 'pm',
89 T: H < 12 ? 'A' : 'P',
90 TT: H < 12 ? 'AM' : 'PM',
91 Z: gmt ? 'GMT' : utc ? 'UTC' : (String(date).match(timezone) || ['']).pop().replace(timezoneClip, ''),
92 o: (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
93 S: ['th', 'st', 'nd', 'rd'][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10],
98 return mask.replace(token, function (match) {
102 return match.slice(1, match.length - 1);
108 'default': 'ddd mmm dd yyyy HH:MM:ss',
109 'shortDate': 'm/d/yy',
110 'mediumDate': 'mmm d, yyyy',
111 'longDate': 'mmmm d, yyyy',
112 'fullDate': 'dddd, mmmm d, yyyy',
113 'shortTime': 'h:MM TT',
114 'mediumTime': 'h:MM:ss TT',
115 'longTime': 'h:MM:ss TT Z',
116 'isoDate': 'yyyy-mm-dd',
117 'isoTime': 'HH:MM:ss',
118 'isoDateTime': 'yyyy-mm-dd\'T\'HH:MM:sso',
119 'isoUtcDateTime': 'UTC:yyyy-mm-dd\'T\'HH:MM:ss\'Z\'',
120 'expiresHeaderFormat': 'ddd, dd mmm yyyy HH:MM:ss Z'
123 // Internationalization strings
126 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat',
127 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
130 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
131 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'
135 function pad(val, len) {
138 while (val.length < len) {
145 * Get the ISO 8601 week number
146 * Based on comments from
147 * http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html
149 * @param {Object} `date`
152 function getWeek(date) {
153 // Remove time components of date
154 var targetThursday = new Date(date.getFullYear(), date.getMonth(), date.getDate());
156 // Change date to Thursday same week
157 targetThursday.setDate(targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3);
159 // Take January 4th as it is always in week 1 (see ISO 8601)
160 var firstThursday = new Date(targetThursday.getFullYear(), 0, 4);
162 // Change date to Thursday same week
163 firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3);
165 // Check if daylight-saving-time-switch occured and correct for it
166 var ds = targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset();
167 targetThursday.setHours(targetThursday.getHours() - ds);
169 // Number of weeks between target Thursday and first Thursday
170 var weekDiff = (targetThursday - firstThursday) / (86400000*7);
171 return 1 + Math.floor(weekDiff);
175 * Get ISO-8601 numeric representation of the day of the week
176 * 1 (for Monday) through 7 (for Sunday)
178 * @param {Object} `date`
181 function getDayOfWeek(date) {
182 var dow = date.getDay();
194 function kindOf(val) {
199 if (val === undefined) {
203 if (typeof val !== 'object') {
207 if (Array.isArray(val)) {
211 return {}.toString.call(val)
212 .slice(8, -1).toLowerCase();
217 if (typeof define === 'function' && define.amd) {
221 } else if (typeof exports === 'object') {
222 module.exports = dateFormat;
224 global.dateFormat = dateFormat;