index.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. var getDayOfYear = require('../get_day_of_year/index.js')
  2. var getISOWeek = require('../get_iso_week/index.js')
  3. var getISOYear = require('../get_iso_year/index.js')
  4. var parse = require('../parse/index.js')
  5. var isValid = require('../is_valid/index.js')
  6. var enLocale = require('../locale/en/index.js')
  7. /**
  8. * @category Common Helpers
  9. * @summary Format the date.
  10. *
  11. * @description
  12. * Return the formatted date string in the given format.
  13. *
  14. * Accepted tokens:
  15. * | Unit | Token | Result examples |
  16. * |-------------------------|-------|----------------------------------|
  17. * | Month | M | 1, 2, ..., 12 |
  18. * | | Mo | 1st, 2nd, ..., 12th |
  19. * | | MM | 01, 02, ..., 12 |
  20. * | | MMM | Jan, Feb, ..., Dec |
  21. * | | MMMM | January, February, ..., December |
  22. * | Quarter | Q | 1, 2, 3, 4 |
  23. * | | Qo | 1st, 2nd, 3rd, 4th |
  24. * | Day of month | D | 1, 2, ..., 31 |
  25. * | | Do | 1st, 2nd, ..., 31st |
  26. * | | DD | 01, 02, ..., 31 |
  27. * | Day of year | DDD | 1, 2, ..., 366 |
  28. * | | DDDo | 1st, 2nd, ..., 366th |
  29. * | | DDDD | 001, 002, ..., 366 |
  30. * | Day of week | d | 0, 1, ..., 6 |
  31. * | | do | 0th, 1st, ..., 6th |
  32. * | | dd | Su, Mo, ..., Sa |
  33. * | | ddd | Sun, Mon, ..., Sat |
  34. * | | dddd | Sunday, Monday, ..., Saturday |
  35. * | Day of ISO week | E | 1, 2, ..., 7 |
  36. * | ISO week | W | 1, 2, ..., 53 |
  37. * | | Wo | 1st, 2nd, ..., 53rd |
  38. * | | WW | 01, 02, ..., 53 |
  39. * | Year | YY | 00, 01, ..., 99 |
  40. * | | YYYY | 1900, 1901, ..., 2099 |
  41. * | ISO week-numbering year | GG | 00, 01, ..., 99 |
  42. * | | GGGG | 1900, 1901, ..., 2099 |
  43. * | AM/PM | A | AM, PM |
  44. * | | a | am, pm |
  45. * | | aa | a.m., p.m. |
  46. * | Hour | H | 0, 1, ... 23 |
  47. * | | HH | 00, 01, ... 23 |
  48. * | | h | 1, 2, ..., 12 |
  49. * | | hh | 01, 02, ..., 12 |
  50. * | Minute | m | 0, 1, ..., 59 |
  51. * | | mm | 00, 01, ..., 59 |
  52. * | Second | s | 0, 1, ..., 59 |
  53. * | | ss | 00, 01, ..., 59 |
  54. * | 1/10 of second | S | 0, 1, ..., 9 |
  55. * | 1/100 of second | SS | 00, 01, ..., 99 |
  56. * | Millisecond | SSS | 000, 001, ..., 999 |
  57. * | Timezone | Z | -01:00, +00:00, ... +12:00 |
  58. * | | ZZ | -0100, +0000, ..., +1200 |
  59. * | Seconds timestamp | X | 512969520 |
  60. * | Milliseconds timestamp | x | 512969520900 |
  61. *
  62. * The characters wrapped in square brackets are escaped.
  63. *
  64. * The result may vary by locale.
  65. *
  66. * @param {Date|String|Number} date - the original date
  67. * @param {String} [format='YYYY-MM-DDTHH:mm:ss.SSSZ'] - the string of tokens
  68. * @param {Object} [options] - the object with options
  69. * @param {Object} [options.locale=enLocale] - the locale object
  70. * @returns {String} the formatted date string
  71. *
  72. * @example
  73. * // Represent 11 February 2014 in middle-endian format:
  74. * var result = format(
  75. * new Date(2014, 1, 11),
  76. * 'MM/DD/YYYY'
  77. * )
  78. * //=> '02/11/2014'
  79. *
  80. * @example
  81. * // Represent 2 July 2014 in Esperanto:
  82. * var eoLocale = require('date-fns/locale/eo')
  83. * var result = format(
  84. * new Date(2014, 6, 2),
  85. * 'Do [de] MMMM YYYY',
  86. * {locale: eoLocale}
  87. * )
  88. * //=> '2-a de julio 2014'
  89. */
  90. function format (dirtyDate, dirtyFormatStr, dirtyOptions) {
  91. var formatStr = dirtyFormatStr ? String(dirtyFormatStr) : 'YYYY-MM-DDTHH:mm:ss.SSSZ'
  92. var options = dirtyOptions || {}
  93. var locale = options.locale
  94. var localeFormatters = enLocale.format.formatters
  95. var formattingTokensRegExp = enLocale.format.formattingTokensRegExp
  96. if (locale && locale.format && locale.format.formatters) {
  97. localeFormatters = locale.format.formatters
  98. if (locale.format.formattingTokensRegExp) {
  99. formattingTokensRegExp = locale.format.formattingTokensRegExp
  100. }
  101. }
  102. var date = parse(dirtyDate)
  103. if (!isValid(date)) {
  104. return 'Invalid Date'
  105. }
  106. var formatFn = buildFormatFn(formatStr, localeFormatters, formattingTokensRegExp)
  107. return formatFn(date)
  108. }
  109. var formatters = {
  110. // Month: 1, 2, ..., 12
  111. 'M': function (date) {
  112. return date.getMonth() + 1
  113. },
  114. // Month: 01, 02, ..., 12
  115. 'MM': function (date) {
  116. return addLeadingZeros(date.getMonth() + 1, 2)
  117. },
  118. // Quarter: 1, 2, 3, 4
  119. 'Q': function (date) {
  120. return Math.ceil((date.getMonth() + 1) / 3)
  121. },
  122. // Day of month: 1, 2, ..., 31
  123. 'D': function (date) {
  124. return date.getDate()
  125. },
  126. // Day of month: 01, 02, ..., 31
  127. 'DD': function (date) {
  128. return addLeadingZeros(date.getDate(), 2)
  129. },
  130. // Day of year: 1, 2, ..., 366
  131. 'DDD': function (date) {
  132. return getDayOfYear(date)
  133. },
  134. // Day of year: 001, 002, ..., 366
  135. 'DDDD': function (date) {
  136. return addLeadingZeros(getDayOfYear(date), 3)
  137. },
  138. // Day of week: 0, 1, ..., 6
  139. 'd': function (date) {
  140. return date.getDay()
  141. },
  142. // Day of ISO week: 1, 2, ..., 7
  143. 'E': function (date) {
  144. return date.getDay() || 7
  145. },
  146. // ISO week: 1, 2, ..., 53
  147. 'W': function (date) {
  148. return getISOWeek(date)
  149. },
  150. // ISO week: 01, 02, ..., 53
  151. 'WW': function (date) {
  152. return addLeadingZeros(getISOWeek(date), 2)
  153. },
  154. // Year: 00, 01, ..., 99
  155. 'YY': function (date) {
  156. return addLeadingZeros(date.getFullYear(), 4).substr(2)
  157. },
  158. // Year: 1900, 1901, ..., 2099
  159. 'YYYY': function (date) {
  160. return addLeadingZeros(date.getFullYear(), 4)
  161. },
  162. // ISO week-numbering year: 00, 01, ..., 99
  163. 'GG': function (date) {
  164. return String(getISOYear(date)).substr(2)
  165. },
  166. // ISO week-numbering year: 1900, 1901, ..., 2099
  167. 'GGGG': function (date) {
  168. return getISOYear(date)
  169. },
  170. // Hour: 0, 1, ... 23
  171. 'H': function (date) {
  172. return date.getHours()
  173. },
  174. // Hour: 00, 01, ..., 23
  175. 'HH': function (date) {
  176. return addLeadingZeros(date.getHours(), 2)
  177. },
  178. // Hour: 1, 2, ..., 12
  179. 'h': function (date) {
  180. var hours = date.getHours()
  181. if (hours === 0) {
  182. return 12
  183. } else if (hours > 12) {
  184. return hours % 12
  185. } else {
  186. return hours
  187. }
  188. },
  189. // Hour: 01, 02, ..., 12
  190. 'hh': function (date) {
  191. return addLeadingZeros(formatters['h'](date), 2)
  192. },
  193. // Minute: 0, 1, ..., 59
  194. 'm': function (date) {
  195. return date.getMinutes()
  196. },
  197. // Minute: 00, 01, ..., 59
  198. 'mm': function (date) {
  199. return addLeadingZeros(date.getMinutes(), 2)
  200. },
  201. // Second: 0, 1, ..., 59
  202. 's': function (date) {
  203. return date.getSeconds()
  204. },
  205. // Second: 00, 01, ..., 59
  206. 'ss': function (date) {
  207. return addLeadingZeros(date.getSeconds(), 2)
  208. },
  209. // 1/10 of second: 0, 1, ..., 9
  210. 'S': function (date) {
  211. return Math.floor(date.getMilliseconds() / 100)
  212. },
  213. // 1/100 of second: 00, 01, ..., 99
  214. 'SS': function (date) {
  215. return addLeadingZeros(Math.floor(date.getMilliseconds() / 10), 2)
  216. },
  217. // Millisecond: 000, 001, ..., 999
  218. 'SSS': function (date) {
  219. return addLeadingZeros(date.getMilliseconds(), 3)
  220. },
  221. // Timezone: -01:00, +00:00, ... +12:00
  222. 'Z': function (date) {
  223. return formatTimezone(date.getTimezoneOffset(), ':')
  224. },
  225. // Timezone: -0100, +0000, ... +1200
  226. 'ZZ': function (date) {
  227. return formatTimezone(date.getTimezoneOffset())
  228. },
  229. // Seconds timestamp: 512969520
  230. 'X': function (date) {
  231. return Math.floor(date.getTime() / 1000)
  232. },
  233. // Milliseconds timestamp: 512969520900
  234. 'x': function (date) {
  235. return date.getTime()
  236. }
  237. }
  238. function buildFormatFn (formatStr, localeFormatters, formattingTokensRegExp) {
  239. var array = formatStr.match(formattingTokensRegExp)
  240. var length = array.length
  241. var i
  242. var formatter
  243. for (i = 0; i < length; i++) {
  244. formatter = localeFormatters[array[i]] || formatters[array[i]]
  245. if (formatter) {
  246. array[i] = formatter
  247. } else {
  248. array[i] = removeFormattingTokens(array[i])
  249. }
  250. }
  251. return function (date) {
  252. var output = ''
  253. for (var i = 0; i < length; i++) {
  254. if (array[i] instanceof Function) {
  255. output += array[i](date, formatters)
  256. } else {
  257. output += array[i]
  258. }
  259. }
  260. return output
  261. }
  262. }
  263. function removeFormattingTokens (input) {
  264. if (input.match(/\[[\s\S]/)) {
  265. return input.replace(/^\[|]$/g, '')
  266. }
  267. return input.replace(/\\/g, '')
  268. }
  269. function formatTimezone (offset, delimeter) {
  270. delimeter = delimeter || ''
  271. var sign = offset > 0 ? '-' : '+'
  272. var absOffset = Math.abs(offset)
  273. var hours = Math.floor(absOffset / 60)
  274. var minutes = absOffset % 60
  275. return sign + addLeadingZeros(hours, 2) + delimeter + addLeadingZeros(minutes, 2)
  276. }
  277. function addLeadingZeros (number, targetLength) {
  278. var output = Math.abs(number).toString()
  279. while (output.length < targetLength) {
  280. output = '0' + output
  281. }
  282. return output
  283. }
  284. module.exports = format