| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import { Duration, isDuration } from './constructor';
- 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';
- // 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 (typeof input === 'number') {
- 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 : 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;
- 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;
- }
|