get-date-formatter.js 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import { getDateFormatOptions } from './options.js';
  2. import { parseDateTokens } from './tokens.js';
  3. /**
  4. * Returns a date formatter function for the given locales and date skeleton
  5. *
  6. * @remarks
  7. * Uses `Intl.DateTimeFormat` internally.
  8. *
  9. * @public
  10. * @param locales - One or more valid BCP 47 language tags, e.g. `fr` or `en-CA`
  11. * @param tokens - An ICU DateFormat skeleton string, or an array or parsed
  12. * `DateToken` tokens
  13. * @param onError - If defined, will be called separately for each encountered
  14. * parsing error and unsupported feature.
  15. * @example
  16. * ```js
  17. * import { getDateFormatter } from '@messageformat/date-skeleton'
  18. *
  19. * // 2006 Jan 2, 15:04:05.789 in local time
  20. * const date = new Date(2006, 0, 2, 15, 4, 5, 789)
  21. *
  22. * let fmt = getDateFormatter('en-CA', 'GrMMMdd', console.error)
  23. * fmt(date) // 'Jan. 02, 2006 AD'
  24. *
  25. * fmt = getDateFormatter('en-CA', 'hamszzzz', console.error)
  26. * fmt(date) // '3:04:05 p.m. Newfoundland Daylight Time'
  27. * ```
  28. */
  29. export function getDateFormatter(locales, tokens, onError) {
  30. if (typeof tokens === 'string')
  31. tokens = parseDateTokens(tokens);
  32. const opt = getDateFormatOptions(tokens, onError);
  33. const dtf = new Intl.DateTimeFormat(locales, opt);
  34. return (date) => dtf.format(date);
  35. }
  36. /**
  37. * Returns a string of JavaScript source that evaluates to a date formatter
  38. * function with the same `(date: Date | number) => string` signature as the
  39. * function returned by {@link getDateFormatter}.
  40. *
  41. * @remarks
  42. * The returned function will memoize an `Intl.DateTimeFormat` instance.
  43. *
  44. * @public
  45. * @param locales - One or more valid BCP 47 language tags, e.g. `fr` or `en-CA`
  46. * @param tokens - An ICU DateFormat skeleton string, or an array or parsed
  47. * `DateToken` tokens
  48. * @param onError - If defined, will be called separately for each encountered
  49. * parsing error and unsupported feature.
  50. * @example
  51. * ```js
  52. * import { getDateFormatterSource } from '@messageformat/date-skeleton'
  53. *
  54. * getDateFormatterSource('en-CA', 'GrMMMdd', console.error)
  55. * // '(function() {\n' +
  56. * // ' var opt = {"era":"short","calendar":"gregory","year":"numeric",' +
  57. * // '"month":"short","day":"2-digit"};\n' +
  58. * // ' var dtf = new Intl.DateTimeFormat("en-CA", opt);\n' +
  59. * // ' return function(value) { return dtf.format(value); }\n' +
  60. * // '})()'
  61. *
  62. * const src = getDateFormatterSource('en-CA', 'hamszzzz', console.error)
  63. * // '(function() {\n' +
  64. * // ' var opt = {"hour":"numeric","hourCycle":"h12","minute":"numeric",' +
  65. * // '"second":"numeric","timeZoneName":"long"};\n' +
  66. * // ' var dtf = new Intl.DateTimeFormat("en-CA", opt);\n' +
  67. * // ' return function(value) { return dtf.format(value); }\n' +
  68. * // '})()'
  69. *
  70. * const fmt = new Function(`return ${src}`)()
  71. * const date = new Date(2006, 0, 2, 15, 4, 5, 789)
  72. * fmt(date) // '3:04:05 p.m. Newfoundland Daylight Time'
  73. * ```
  74. */
  75. export function getDateFormatterSource(locales, tokens, onError) {
  76. if (typeof tokens === 'string')
  77. tokens = parseDateTokens(tokens);
  78. const opt = getDateFormatOptions(tokens, onError);
  79. const lines = [
  80. `(function() {`,
  81. `var opt = ${JSON.stringify(opt)};`,
  82. `var dtf = new Intl.DateTimeFormat(${JSON.stringify(locales)}, opt);`,
  83. `return function(value) { return dtf.format(value); }`
  84. ];
  85. return lines.join('\n ') + '\n})()';
  86. }