vue-moment.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. module.exports = {
  2. install(Vue, options) {
  3. const moment = options && options.moment ? options.moment : require('moment');
  4. Object.defineProperties(Vue.prototype, {
  5. $moment: {
  6. get() {
  7. return moment;
  8. },
  9. },
  10. });
  11. Vue.moment = moment;
  12. Vue.filter('moment', (...args) => {
  13. args = Array.prototype.slice.call(args);
  14. const input = args.shift();
  15. let date;
  16. if (Array.isArray(input) && typeof input[0] === 'string') {
  17. // If input is array, assume we're being passed a format pattern to parse against.
  18. // Format pattern will accept an array of potential formats to parse against.
  19. // Date string should be at [0], format pattern(s) should be at [1]
  20. date = moment(input[0], input[1], true);
  21. } else if (typeof input === 'number') {
  22. if (input.toString().length < 12) {
  23. // If input is an integer with fewer than 12 digits, assume Unix seconds...
  24. date = moment.unix(input);
  25. } else {
  26. // ..otherwise, assume milliseconds.
  27. date = moment(input);
  28. }
  29. } else {
  30. // Otherwise, throw the input at moment and see what happens...
  31. date = moment(input);
  32. }
  33. if (!input || !date.isValid()) {
  34. // Log a warning if moment couldn't reconcile the input. Better than throwing an error?
  35. console.warn('Could not build a valid `moment` object from input.');
  36. return input;
  37. }
  38. function parse(...args) {
  39. args = Array.prototype.slice.call(args);
  40. const method = args.shift();
  41. switch (method) {
  42. case 'add': {
  43. /*
  44. * Mutates the original moment by adding time.
  45. * http://momentjs.com/docs/#/manipulating/add/
  46. */
  47. const addends = args.shift()
  48. .split(',')
  49. .map(Function.prototype.call, String.prototype.trim);
  50. const obj = {};
  51. for (let n = 0; n < addends.length; n++) {
  52. const addend = addends[n].split(' ');
  53. obj[addend[1]] = addend[0];
  54. }
  55. date.add(obj);
  56. break;
  57. }
  58. case 'subtract': {
  59. /*
  60. * Mutates the original moment by subtracting time.
  61. * http://momentjs.com/docs/#/manipulating/subtract/
  62. */
  63. const subtrahends = args.shift()
  64. .split(',')
  65. .map(Function.prototype.call, String.prototype.trim);
  66. const obj = {};
  67. for (let n = 0; n < subtrahends.length; n++) {
  68. const subtrahend = subtrahends[n].split(' ');
  69. obj[subtrahend[1]] = subtrahend[0];
  70. }
  71. date.subtract(obj);
  72. break;
  73. }
  74. case 'from': {
  75. /*
  76. * Display a moment in relative time, either from now or from a specified date.
  77. * http://momentjs.com/docs/#/displaying/fromnow/
  78. */
  79. let from = 'now';
  80. let removeSuffix = false;
  81. if (args[0] === 'now') args.shift();
  82. // If valid, assume it is a date we want the output computed against.
  83. if (moment(args[0]).isValid()) from = moment(args.shift());
  84. if (args[0] === true) {
  85. args.shift();
  86. removeSuffix = true;
  87. }
  88. if (from !== 'now') {
  89. date = date.from(from, removeSuffix);
  90. } else {
  91. date = date.fromNow(removeSuffix);
  92. }
  93. break;
  94. }
  95. case 'diff': {
  96. /*
  97. * Mutates the original moment by doing a difference with another date.
  98. * http://momentjs.com/docs/#/displaying/difference/
  99. */
  100. let referenceTime = moment();
  101. let units = '';
  102. let float = false;
  103. if (moment(args[0]).isValid()) {
  104. // If valid, assume it is a date we want the output computed against.
  105. referenceTime = moment(args.shift());
  106. } else if (args[0] === null || args[0] === 'now') {
  107. // If null or 'now', remove argument and proceed with default referenceTime.
  108. args.shift();
  109. }
  110. if (args[0]) units = args.shift();
  111. if (args[0] === true) float = args.shift();
  112. date = date.diff(referenceTime, units, float);
  113. break;
  114. }
  115. case 'calendar': {
  116. /*
  117. * Formats a date with different strings depending on how close
  118. * to a certain date (today by default) the date is.
  119. * http://momentjs.com/docs/#/displaying/calendar-time/
  120. */
  121. let referenceTime = moment();
  122. let formats = {};
  123. if (moment(args[0]).isValid()) {
  124. // If valid, assume it is a date we want the output computed against.
  125. referenceTime = moment(args.shift());
  126. } else if (args[0] === null || args[0] === 'now') {
  127. // If null or 'now', remove argument and proceed with default referenceTime.
  128. args.shift();
  129. }
  130. if (typeof args[0] === 'object') formats = args.shift();
  131. date = date.calendar(referenceTime, formats);
  132. break;
  133. }
  134. case 'utc': {
  135. /*
  136. * Mutates the original moment by converting to UTC
  137. * https://momentjs.com/docs/#/manipulating/utc/
  138. */
  139. date.utc();
  140. break;
  141. }
  142. case 'timezone': {
  143. /*
  144. * Mutates the original moment by converting to a new timezone.
  145. * https://momentjs.com/timezone/docs/#/using-timezones/converting-to-zone/
  146. */
  147. date.tz(args.shift());
  148. break;
  149. }
  150. default: {
  151. /*
  152. * Formats a date by taking a string of tokens and replacing
  153. * them with their corresponding values.
  154. * http://momentjs.com/docs/#/displaying/format/
  155. */
  156. const format = method;
  157. date = date.format(format);
  158. }
  159. }
  160. if (args.length) parse.apply(parse, args);
  161. }
  162. parse.apply(parse, args);
  163. return date;
  164. });
  165. Vue.filter('duration', (...args) => {
  166. /*
  167. * Basic pass-through filter for leveraging moment.js's ability
  168. * to manipulate and display durations.
  169. * https://momentjs.com/docs/#/durations/
  170. */
  171. args = Array.prototype.slice.call(args);
  172. const input = args.shift();
  173. const method = args.shift();
  174. function createDuration(time) {
  175. if (!Array.isArray(time)) time = [time];
  176. const result = moment.duration(...time);
  177. if (!result.isValid()) console.warn('Could not build a valid `duration` object from input.');
  178. return result;
  179. }
  180. let duration = createDuration(input);
  181. if (method === 'add' || method === 'subtract') {
  182. // Generates a duration object and either adds or subtracts it
  183. // from our original duration.
  184. const durationChange = createDuration(args);
  185. duration[method](durationChange);
  186. } else if (duration && duration[method]) {
  187. // This gives a full proxy to moment.duration functions.
  188. duration = duration[method](...args);
  189. }
  190. return duration;
  191. });
  192. },
  193. };