Blame view

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