8f5c2f727542d044ad25cbe8e4f9a972ca5c4751712d524649c1ab32b8a3f3906065a7b3f345ff1af2128278c4d892b966fce5639728d85ffb8c6f872d0de2 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { Duration, isDuration } from './constructor';
  2. import toInt from '../utils/to-int';
  3. import absRound from '../utils/abs-round';
  4. import hasOwnProp from '../utils/has-own-prop';
  5. import { DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants';
  6. import { cloneWithOffset } from '../units/offset';
  7. import { createLocal } from '../create/local';
  8. // ASP.NET json date format regex
  9. var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
  10. // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
  11. // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
  12. // and further modified to allow for strings containing both week and day
  13. var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;
  14. export function createDuration (input, key) {
  15. var duration = input,
  16. // matching against regexp is expensive, do it on demand
  17. match = null,
  18. sign,
  19. ret,
  20. diffRes;
  21. if (isDuration(input)) {
  22. duration = {
  23. ms : input._milliseconds,
  24. d : input._days,
  25. M : input._months
  26. };
  27. } else if (typeof input === 'number') {
  28. duration = {};
  29. if (key) {
  30. duration[key] = input;
  31. } else {
  32. duration.milliseconds = input;
  33. }
  34. } else if (!!(match = aspNetRegex.exec(input))) {
  35. sign = (match[1] === '-') ? -1 : 1;
  36. duration = {
  37. y : 0,
  38. d : toInt(match[DATE]) * sign,
  39. h : toInt(match[HOUR]) * sign,
  40. m : toInt(match[MINUTE]) * sign,
  41. s : toInt(match[SECOND]) * sign,
  42. ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
  43. };
  44. } else if (!!(match = isoRegex.exec(input))) {
  45. sign = (match[1] === '-') ? -1 : 1;
  46. duration = {
  47. y : parseIso(match[2], sign),
  48. M : parseIso(match[3], sign),
  49. w : parseIso(match[4], sign),
  50. d : parseIso(match[5], sign),
  51. h : parseIso(match[6], sign),
  52. m : parseIso(match[7], sign),
  53. s : parseIso(match[8], sign)
  54. };
  55. } else if (duration == null) {// checks for null or undefined
  56. duration = {};
  57. } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
  58. diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
  59. duration = {};
  60. duration.ms = diffRes.milliseconds;
  61. duration.M = diffRes.months;
  62. }
  63. ret = new Duration(duration);
  64. if (isDuration(input) && hasOwnProp(input, '_locale')) {
  65. ret._locale = input._locale;
  66. }
  67. return ret;
  68. }
  69. createDuration.fn = Duration.prototype;
  70. function parseIso (inp, sign) {
  71. // We'd normally use ~~inp for this, but unfortunately it also
  72. // converts floats to ints.
  73. // inp may be undefined, so careful calling replace on it.
  74. var res = inp && parseFloat(inp.replace(',', '.'));
  75. // apply sign while we're at it
  76. return (isNaN(res) ? 0 : res) * sign;
  77. }
  78. function positiveMomentsDifference(base, other) {
  79. var res = {milliseconds: 0, months: 0};
  80. res.months = other.month() - base.month() +
  81. (other.year() - base.year()) * 12;
  82. if (base.clone().add(res.months, 'M').isAfter(other)) {
  83. --res.months;
  84. }
  85. res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
  86. return res;
  87. }
  88. function momentsDifference(base, other) {
  89. var res;
  90. if (!(base.isValid() && other.isValid())) {
  91. return {milliseconds: 0, months: 0};
  92. }
  93. other = cloneWithOffset(other, base);
  94. if (base.isBefore(other)) {
  95. res = positiveMomentsDifference(base, other);
  96. } else {
  97. res = positiveMomentsDifference(other, base);
  98. res.milliseconds = -res.milliseconds;
  99. res.months = -res.months;
  100. }
  101. return res;
  102. }