dateformat.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Date Format 1.2.3
  3. * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
  4. * MIT license
  5. *
  6. * Includes enhancements by Scott Trenda <scott.trenda.net>
  7. * and Kris Kowal <cixar.com/~kris.kowal/>
  8. *
  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.
  13. */
  14. (function(global) {
  15. 'use strict';
  16. var dateFormat = (function() {
  17. var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZWN]|"[^"]*"|'[^']*'/g;
  18. var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g;
  19. var timezoneClip = /[^-+\dA-Z]/g;
  20. // Regexes and supporting functions are cached through closure
  21. return function (date, mask, utc, gmt) {
  22. // You can't provide utc if you skip other args (use the 'UTC:' mask prefix)
  23. if (arguments.length === 1 && kindOf(date) === 'string' && !/\d/.test(date)) {
  24. mask = date;
  25. date = undefined;
  26. }
  27. date = date || new Date;
  28. if(!(date instanceof Date)) {
  29. date = new Date(date);
  30. }
  31. if (isNaN(date)) {
  32. throw TypeError('Invalid date');
  33. }
  34. mask = String(dateFormat.masks[mask] || mask || dateFormat.masks['default']);
  35. // Allow setting the utc/gmt argument via the mask
  36. var maskSlice = mask.slice(0, 4);
  37. if (maskSlice === 'UTC:' || maskSlice === 'GMT:') {
  38. mask = mask.slice(4);
  39. utc = true;
  40. if (maskSlice === 'GMT:') {
  41. gmt = true;
  42. }
  43. }
  44. var _ = utc ? 'getUTC' : 'get';
  45. var d = date[_ + 'Date']();
  46. var D = date[_ + 'Day']();
  47. var m = date[_ + 'Month']();
  48. var y = date[_ + 'FullYear']();
  49. var H = date[_ + 'Hours']();
  50. var M = date[_ + 'Minutes']();
  51. var s = date[_ + 'Seconds']();
  52. var L = date[_ + 'Milliseconds']();
  53. var o = utc ? 0 : date.getTimezoneOffset();
  54. var W = getWeek(date);
  55. var N = getDayOfWeek(date);
  56. var flags = {
  57. d: d,
  58. dd: pad(d),
  59. ddd: dateFormat.i18n.dayNames[D],
  60. dddd: dateFormat.i18n.dayNames[D + 7],
  61. m: m + 1,
  62. mm: pad(m + 1),
  63. mmm: dateFormat.i18n.monthNames[m],
  64. mmmm: dateFormat.i18n.monthNames[m + 12],
  65. yy: String(y).slice(2),
  66. yyyy: y,
  67. h: H % 12 || 12,
  68. hh: pad(H % 12 || 12),
  69. H: H,
  70. HH: pad(H),
  71. M: M,
  72. MM: pad(M),
  73. s: s,
  74. ss: pad(s),
  75. l: pad(L, 3),
  76. L: pad(Math.round(L / 10)),
  77. t: H < 12 ? dateFormat.i18n.timeNames[0] : dateFormat.i18n.timeNames[1],
  78. tt: H < 12 ? dateFormat.i18n.timeNames[2] : dateFormat.i18n.timeNames[3],
  79. T: H < 12 ? dateFormat.i18n.timeNames[4] : dateFormat.i18n.timeNames[5],
  80. TT: H < 12 ? dateFormat.i18n.timeNames[6] : dateFormat.i18n.timeNames[7],
  81. Z: gmt ? 'GMT' : utc ? 'UTC' : (String(date).match(timezone) || ['']).pop().replace(timezoneClip, ''),
  82. o: (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
  83. S: ['th', 'st', 'nd', 'rd'][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10],
  84. W: W,
  85. N: N
  86. };
  87. return mask.replace(token, function (match) {
  88. if (match in flags) {
  89. return flags[match];
  90. }
  91. return match.slice(1, match.length - 1);
  92. });
  93. };
  94. })();
  95. dateFormat.masks = {
  96. 'default': 'ddd mmm dd yyyy HH:MM:ss',
  97. 'shortDate': 'm/d/yy',
  98. 'mediumDate': 'mmm d, yyyy',
  99. 'longDate': 'mmmm d, yyyy',
  100. 'fullDate': 'dddd, mmmm d, yyyy',
  101. 'shortTime': 'h:MM TT',
  102. 'mediumTime': 'h:MM:ss TT',
  103. 'longTime': 'h:MM:ss TT Z',
  104. 'isoDate': 'yyyy-mm-dd',
  105. 'isoTime': 'HH:MM:ss',
  106. 'isoDateTime': 'yyyy-mm-dd\'T\'HH:MM:sso',
  107. 'isoUtcDateTime': 'UTC:yyyy-mm-dd\'T\'HH:MM:ss\'Z\'',
  108. 'expiresHeaderFormat': 'ddd, dd mmm yyyy HH:MM:ss Z'
  109. };
  110. // Internationalization strings
  111. dateFormat.i18n = {
  112. dayNames: [
  113. 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat',
  114. 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
  115. ],
  116. monthNames: [
  117. 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
  118. 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'
  119. ],
  120. timeNames: [
  121. 'a', 'p', 'am', 'pm', 'A', 'P', 'AM', 'PM'
  122. ]
  123. };
  124. function pad(val, len) {
  125. val = String(val);
  126. len = len || 2;
  127. while (val.length < len) {
  128. val = '0' + val;
  129. }
  130. return val;
  131. }
  132. /**
  133. * Get the ISO 8601 week number
  134. * Based on comments from
  135. * http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html
  136. *
  137. * @param {Object} `date`
  138. * @return {Number}
  139. */
  140. function getWeek(date) {
  141. // Remove time components of date
  142. var targetThursday = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  143. // Change date to Thursday same week
  144. targetThursday.setDate(targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3);
  145. // Take January 4th as it is always in week 1 (see ISO 8601)
  146. var firstThursday = new Date(targetThursday.getFullYear(), 0, 4);
  147. // Change date to Thursday same week
  148. firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3);
  149. // Check if daylight-saving-time-switch occurred and correct for it
  150. var ds = targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset();
  151. targetThursday.setHours(targetThursday.getHours() - ds);
  152. // Number of weeks between target Thursday and first Thursday
  153. var weekDiff = (targetThursday - firstThursday) / (86400000*7);
  154. return 1 + Math.floor(weekDiff);
  155. }
  156. /**
  157. * Get ISO-8601 numeric representation of the day of the week
  158. * 1 (for Monday) through 7 (for Sunday)
  159. *
  160. * @param {Object} `date`
  161. * @return {Number}
  162. */
  163. function getDayOfWeek(date) {
  164. var dow = date.getDay();
  165. if(dow === 0) {
  166. dow = 7;
  167. }
  168. return dow;
  169. }
  170. /**
  171. * kind-of shortcut
  172. * @param {*} val
  173. * @return {String}
  174. */
  175. function kindOf(val) {
  176. if (val === null) {
  177. return 'null';
  178. }
  179. if (val === undefined) {
  180. return 'undefined';
  181. }
  182. if (typeof val !== 'object') {
  183. return typeof val;
  184. }
  185. if (Array.isArray(val)) {
  186. return 'array';
  187. }
  188. return {}.toString.call(val)
  189. .slice(8, -1).toLowerCase();
  190. };
  191. if (typeof define === 'function' && define.amd) {
  192. define(function () {
  193. return dateFormat;
  194. });
  195. } else if (typeof exports === 'object') {
  196. module.exports = dateFormat;
  197. } else {
  198. global.dateFormat = dateFormat;
  199. }
  200. })(this);