import zeroFill from ‘../utils/zero-fill’; import { createDuration } from ‘../duration/create’; import { addSubtract } from ‘../moment/add-subtract’; import { isMoment } from ‘../moment/constructor’; import { addFormatToken } from ‘../format/format’; import { addRegexToken, matchOffset } from ‘../parse/regex’; import { addParseToken } from ‘../parse/token’; import { createLocal } from ‘../create/local’; import { createUTC } from ‘../create/utc’; import isDate from ‘../utils/is-date’; import toInt from ‘../utils/to-int’; import compareArrays from ‘../utils/compare-arrays’; import { hooks } from ‘../utils/hooks’;

// FORMATTING

function offset (token, separator) {

addFormatToken(token, 0, 0, function () {
    var offset = this.utcOffset();
    var sign = '+';
    if (offset < 0) {
        offset = -offset;
        sign = '-';
    }
    return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
});

}

offset(‘Z’, ‘:’); offset(‘ZZ’, ”);

// PARSING

addRegexToken(‘Z’, matchOffset); addRegexToken(‘ZZ’, matchOffset); addParseToken([‘Z’, ‘ZZ’], function (input, array, config) {

config._useUTC = true;
config._tzm = offsetFromString(input);

});

// HELPERS

// timezone chunker // ‘+10:00’ > [‘10’, ‘00’] // ‘-1530’ > [‘-15’, ‘30’] var chunkOffset = /([+-]|dd)/gi;

function offsetFromString(string) {

var matches = ((string || '').match(matchOffset) || []);
var chunk   = matches[matches.length - 1] || [];
var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
var minutes = +(parts[1] * 60) + toInt(parts[2]);

return parts[0] === '+' ? minutes : -minutes;

}

// Return a moment from input, that is local/utc/zone equivalent to model. export function cloneWithOffset(input, model) {

var res, diff;
if (model._isUTC) {
    res = model.clone();
    diff = (isMoment(input) || isDate(input) ? +input : +createLocal(input)) - (+res);
    // Use low-level api, because this fn is low-level api.
    res._d.setTime(+res._d + diff);
    hooks.updateOffset(res, false);
    return res;
} else {
    return createLocal(input).local();
}
return model._isUTC ? createLocal(input).zone(model._offset || 0) : createLocal(input).local();

}

function getDateOffset (m) {

// On Firefox.24 Date#getTimezoneOffset returns a floating point.
// https://github.com/moment/moment/pull/1871
return -Math.round(m._d.getTimezoneOffset() / 15) * 15;

}

// HOOKS

// This function will be called whenever a moment is mutated. // It is intended to keep the offset in sync with the timezone. hooks.updateOffset = function () {};

// MOMENTS

// keepLocalTime = true means only change the timezone, without // affecting the local hour. So 5:31:26 +0300 –[utcOffset(2, true)]–> // 5:31:26 +0200 It is possible that 5:31:26 doesn’t exist with offset // +0200, so we adjust the time as needed, to be valid. // // Keeping the time actually adds/subtracts (one hour) // from the actual represented time. That is why we call updateOffset // a second time. In case it wants us to change the offset again // _changeInProgress == true case, then we have to adjust, because // there is no such time in the given timezone. export function getSetOffset (input, keepLocalTime) {

var offset = this._offset || 0,
    localAdjust;
if (input != null) {
    if (typeof input === 'string') {
        input = offsetFromString(input);
    }
    if (Math.abs(input) < 16) {
        input = input * 60;
    }
    if (!this._isUTC && keepLocalTime) {
        localAdjust = getDateOffset(this);
    }
    this._offset = input;
    this._isUTC = true;
    if (localAdjust != null) {
        this.add(localAdjust, 'm');
    }
    if (offset !== input) {
        if (!keepLocalTime || this._changeInProgress) {
            addSubtract(this, createDuration(input - offset, 'm'), 1, false);
        } else if (!this._changeInProgress) {
            this._changeInProgress = true;
            hooks.updateOffset(this, true);
            this._changeInProgress = null;
        }
    }
    return this;
} else {
    return this._isUTC ? offset : getDateOffset(this);
}

}

export function getSetZone (input, keepLocalTime) {

if (input != null) {
    if (typeof input !== 'string') {
        input = -input;
    }

    this.utcOffset(input, keepLocalTime);

    return this;
} else {
    return -this.utcOffset();
}

}

export function setOffsetToUTC (keepLocalTime) {

return this.utcOffset(0, keepLocalTime);

}

export function setOffsetToLocal (keepLocalTime) {

if (this._isUTC) {
    this.utcOffset(0, keepLocalTime);
    this._isUTC = false;

    if (keepLocalTime) {
        this.subtract(getDateOffset(this), 'm');
    }
}
return this;

}

export function setOffsetToParsedOffset () {

if (this._tzm) {
    this.utcOffset(this._tzm);
} else if (typeof this._i === 'string') {
    this.utcOffset(offsetFromString(this._i));
}
return this;

}

export function hasAlignedHourOffset (input) {

if (!input) {
    input = 0;
}
else {
    input = createLocal(input).utcOffset();
}

return (this.utcOffset() - input) % 60 === 0;

}

export function isDaylightSavingTime () {

return (
    this.utcOffset() > this.clone().month(0).utcOffset() ||
    this.utcOffset() > this.clone().month(5).utcOffset()
);

}

export function isDaylightSavingTimeShifted () {

if (this._a) {
    var other = this._isUTC ? createUTC(this._a) : createLocal(this._a);
    return this.isValid() && compareArrays(this._a, other.toArray()) > 0;
}

return false;

}

export function isLocal () {

return !this._isUTC;

}

export function isUtcOffset () {

return this._isUTC;

}

export function isUtc () {

return this._isUTC && this._offset === 0;

}