]> git.ipfire.org Git - thirdparty/moment.git/commitdiff
WIP new zone API, zone constructors, no-touch after construction
authorIskren Chernev <iskren.chernev@gmail.com>
Sat, 17 Jun 2017 01:18:50 +0000 (04:18 +0300)
committerIskren Chernev <iskren.chernev@gmail.com>
Sat, 17 Jun 2017 01:18:50 +0000 (04:18 +0300)
25 files changed:
TODO [new file with mode: 0644]
src/lib/create/constructors.js [new file with mode: 0644]
src/lib/create/from-anything.js
src/lib/create/from-array.js
src/lib/create/from-string-and-array.js
src/lib/create/from-string.js
src/lib/create/local.js [deleted file]
src/lib/create/utc.js [deleted file]
src/lib/duration/create.js
src/lib/moment/add-subtract.js
src/lib/moment/calendar.js
src/lib/moment/constructor.js
src/lib/moment/get-set.js
src/lib/moment/locale.js
src/lib/units/day-of-month.js
src/lib/units/hour.js
src/lib/units/millisecond.js
src/lib/units/minute.js
src/lib/units/month.js
src/lib/units/offset.js
src/lib/units/second.js
src/lib/units/week-calendar-utils.js
src/lib/units/week-year.js
src/lib/units/week.js
src/lib/units/year.js

diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..10295dd
--- /dev/null
+++ b/TODO
@@ -0,0 +1,36 @@
+# creation
+
+createMoment({
+    input,
+    locale,
+    format,
+    strict, # dfl - yes?
+    timeZone, # dfl - local
+    # localHandling, [OVERLAP_FIRST|OVERLAP_SECOND|OVERLAP_THROW] + [HOLE_FWD|HOLE_BWD|HOLE_THROW]
+})
+
+quickCreate({
+    date,
+    locale,
+    timeZone
+})
+
+
+
+
+* createLocal (local)
+* createLocalOrUTC (from-anything) -> just puts inp data in config object
+* createFromConfig (from-anything)
+* prepareConfig (from-anything)
+ --> from moment
+ --> from date
+ --> from str+array configFromStringAndArray
+ --> from str+fmt configFromStringAndFormat
+ --> from input (str only)  configFromInput
+
+# am/pm bug 297 -- should be able to skip am/pm ?
+# array of formats --> there won't be any leftovers, so rethink strict with arrays
+ ---> define strictness with flags and make it configurable?
+# X (unix) parses also parts, we need to make X.S, X.SS and X.SSS separate tokens
+# 'str Z' is not valid ISO, 'strZ' is
+# what about all the locale issues related to strict parsing
diff --git a/src/lib/create/constructors.js b/src/lib/create/constructors.js
new file mode 100644 (file)
index 0000000..1e5de54
--- /dev/null
@@ -0,0 +1,26 @@
+import { createCollect } from './from-anything';
+import { localTimeZone } from '../timezone/local';
+import { fixedTimeZoneForOffset } from '../timezone/fixed-offset';
+
+export function createUTC (input, format, locale, strict) {
+    return createCollect(input, format, locale, strict, fixedTimeZoneForOffset(0));
+}
+
+export function createFixedOffset (offset) {
+    // maybe parse offset
+    return function (input, format, locale, strict) {
+        return createCollect(input, format, locale, strict, fixedTimeZoneForOffset(offset));
+    }
+}
+
+// TODO(Iskren): Recheck all internal uses and take into account that it
+// WON'T copy the zone any more
+export function createLocal (input, format, locale, strict) {
+    return createCollect(input, format, locale, strict, localTimeZone);
+}
+
+export function createZoned (tz) {
+    return function (input, format, locale, strict) {
+        return createCollect(input, format, locale, strict, tz);
+    }
+}
index c94394539061ce9b363d4ed4975b32d3cb1d75f2..3af46e1aff86aaa61c262239a551e063d640e25d 100644 (file)
@@ -24,11 +24,11 @@ function createFromConfig (config) {
     var res = new Moment(checkOverflow(prepareConfig(config)));
 
     // Prevent infinite loop in case updateOffset creates new moment objects.
-    if (updateInProgress === false) {
-        updateInProgress = true;
-        res = hooks.updateOffset(res);
-        updateInProgress = false;
-    }
+    // if (updateInProgress === false) {
+    //     updateInProgress = true;
+    //     res = hooks.updateOffset(res);
+    //     updateInProgress = false;
+    // }
 
     if (res._nextDay) {
         // Adding is smart enough around DST
@@ -53,7 +53,16 @@ export function prepareConfig (config) {
         config._i = input = config._locale.preparse(input);
     }
 
-    if (isMoment(input)) {
+    if (input._d != null || input._l != null && input._isAMomentObject !== true) {
+        // If it looks like a moment, but isn't
+        throw new Error("No uninitialized config should ever reach this place");
+    } else if (isMoment(input)) {
+        // TODO(iskren): This is wrong, we create moment twice, this is
+        // supposed to return ready config
+        //
+        // TODOv3(iskren): config._i could be just config in-progress? I don't
+        // think this should be allowed -- find all places by removing
+        // isAMomentObject from config and setting it in the constructor.
         return new Moment(checkOverflow(input));
     } else if (isDate(input)) {
         config._d = input;
@@ -95,7 +104,59 @@ function configFromInput(config) {
     }
 }
 
-export function createLocalOrUTC (input, format, locale, strict, isUTC) {
+// TODO: Check what existing moments have in them
+// ts, off, locale, tz + parsing flags (only for new)
+export function quickCreateLocal(lts, locale, timeZone, flags) {
+    var local_ts_offset = computeOffset(lts, timeZone, flags);
+    return new Moment({local_ts[0], local_ts[1], locale, timeZone});
+}
+
+export function quickCreateUTC(uts, locale, timeZone) {
+    var offset = timeZone.offsetFromTimestamp(uts);
+    return new Moment({uts + offset, offset, locale, timeZone});
+}
+
+function computeOffset(lts, timeZone, flags) {
+    // TODO: Flags are being ignored. Take them into account some day
+
+    var of1 = timezone.offsetFromTimestamp(lts) // we treat local timestamp as unix to get
+                                                // a ballbpark estimate
+    var of2 = timezone.offsetFromTimestamp(lts - of1) // adjust local by probable offset
+    if (of1 == of2) {
+        // (lts, of1) is valid, but could be ambigous (second)
+        of3 = timezone.offsetFromTimestamp(lts - of1 - 6 * 60 * 60 * 1000); // subtract 6h to see if
+                                                                            // we're near DST
+        if (of1 === of3) {
+            return [lts, of1];
+        } else if (timezone.offsetFromTimestamp(lts - of3) === of3) {
+            // ambiguous, variants are [lts, of3], [lts, of1], of3 being
+            // the previous
+            return [lts, of3];
+        } else {
+            // there was DST shortly before [lts, of1], but it fully passed
+            return [lts, of1];
+        }
+    } else {
+        // we try a second time, this could happen around invalid time
+        var of3 = timezone.offsetFromTimestamp(lts - of2);
+        if (of3 === of2) {
+            return [lts, of2]
+        } else {
+            // invalid time!
+            if (of2 > of3) {
+                var tmp = of2; of2 = of3; of3 = tmp;
+            }
+            var dstGap = of3 - of2;
+            if (timezone.offsetFromTimestamp(lts + dstGap - of3) == of3) {
+                return [lts + dstGap, of3];
+            } else {
+                throw new Error("should never happen (test)");
+            }
+        }
+    }
+}
+
+export function createCollect (input, format, locale, strict, tz) {
     var c = {};
 
     if (locale === true || locale === false) {
@@ -109,8 +170,8 @@ export function createLocalOrUTC (input, format, locale, strict, isUTC) {
     }
     // object construction must be done this way.
     // https://github.com/moment/moment/issues/1423
-    c._isAMomentObject = true;
-    c._useUTC = c._isUTC = isUTC;
+    // c._isAMomentObject = true;
+    c._tz = tz;
     c._l = locale;
     c._i = input;
     c._f = format;
index 0cdf474cf3ae5359cb79877e8fca1239c37e6ace..af07fe8a1124129c8b3e91998b520766667d9d0a 100644 (file)
@@ -7,12 +7,19 @@ import { createLocal } from './local';
 import defaults from '../utils/defaults';
 import getParsingFlags from './parsing-flags';
 
+// TODO(Iskren): The proper impl of this function, should:
+// - check if there is config._tzm, if there is, get the local time in that
+//   fixed offset timezone
+// - otherwise, return the local date for the config._tz (quickCreateUTC(now(),
+//   _l, _tz).year()/.month()/.date()
+// But then every moment object creation creates another object ... at least
+// not recursive, but much slower.
 function currentDateArray(config) {
     // hooks is actually the exported moment object
     var nowValue = new Date(hooks.now());
-    if (config._useUTC) {
-        return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
-    }
+    // if (config._useUTC) {
+    //     return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
+    // }
     return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
 }
 
@@ -70,7 +77,7 @@ export function configFromArray (config) {
         config._a[HOUR] = 0;
     }
 
-    config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
+    config._d = createUTCDate.apply(null, input);
     // Apply timezone offset from input. The actual utcOffset can be changed
     // with parseZone.
     if (config._tzm != null) {
@@ -83,13 +90,15 @@ export function configFromArray (config) {
 }
 
 function dayOfYearFromWeekInfo(config) {
-    var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
+    var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, now;
 
     w = config._w;
     if (w.GG != null || w.W != null || w.E != null) {
         dow = 1;
         doy = 4;
 
+        // TODO: NOW we can do this, revisit after making sure config._tz is an
+        // object at this point.
         // TODO: We need to take the current isoWeekYear, but that depends on
         // how we interpret now (local, utc, fixed offset). So create
         // a now version of current config (take local/utc/offset flags, and
index 1d8a7a806cda2fee37170e4b5615b7acabb555e2..07d119536b8171bff976e90b16c1211c67681b4d 100644 (file)
@@ -22,9 +22,6 @@ export function configFromStringAndArray(config) {
     for (i = 0; i < config._f.length; i++) {
         currentScore = 0;
         tempConfig = copyConfig({}, config);
-        if (config._useUTC != null) {
-            tempConfig._useUTC = config._useUTC;
-        }
         tempConfig._f = config._f[i];
         configFromStringAndFormat(tempConfig);
 
index 7cae76d70ef57c64b683ac9a97876ab5b684b922..ac278fe1907ed5c87ccfd650a674e344b22649f4 100644 (file)
@@ -197,6 +197,6 @@ hooks.createFromInputFallback = deprecate(
     'discouraged and will be removed in an upcoming major release. Please refer to ' +
     'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
     function (config) {
-        config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+        config._d = new Date(config._i + (config._tz.type != 'local' ? ' UTC' : ''));
     }
 );
diff --git a/src/lib/create/local.js b/src/lib/create/local.js
deleted file mode 100644 (file)
index 88c1e26..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createLocalOrUTC } from './from-anything';
-
-export function createLocal (input, format, locale, strict) {
-    return createLocalOrUTC(input, format, locale, strict, false);
-}
diff --git a/src/lib/create/utc.js b/src/lib/create/utc.js
deleted file mode 100644 (file)
index 9613953..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createLocalOrUTC } from './from-anything';
-
-export function createUTC (input, format, locale, strict) {
-    return createLocalOrUTC(input, format, locale, strict, true).utc();
-}
index ef9707221ecf04233f02feb83d0abc30a9d2726f..bbc041232d140db05b6a320b8d4376fda0ac29ea 100644 (file)
@@ -57,6 +57,8 @@ export function createDuration (input, key) {
     } else if (duration == null) {// checks for null or undefined
         duration = {};
     } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
+        // TODO: Do not createLocal, instead, use the zone of one of them, and
+        // align the other.
         diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
 
         duration = {};
index 7b682d53a45c914ab1a2acb89321d0c1288fc74b..e469c261165f9f0b017c52c25a9301ca87e1a734 100644 (file)
@@ -1,6 +1,6 @@
 import { Moment } from './constructor';
 import { get, set } from './get-set';
-import { setMonth } from '../units/month';
+import { smartSetUTCMonth } from '../units/month';
 import { createDuration } from '../duration/create';
 import { deprecateSimple } from '../utils/deprecate';
 import { hooks } from '../utils/hooks';
@@ -24,32 +24,51 @@ function createAdder(direction, name) {
     };
 }
 
-export function addSubtract (mom, duration, isAdding, updateOffset) {
+export function addSubtract (mom, duration, isAdding) {
+    // TODO: Check for last argument usage, make sure its ok
     var milliseconds = duration._milliseconds,
         days = absRound(duration._days),
-        months = absRound(duration._months);
+        months = absRound(duration._months),
+        d;
 
     if (!mom.isValid()) {
         // No op
         return mom;
     }
 
-    updateOffset = updateOffset == null ? true : updateOffset;
-
-    if (milliseconds) {
-        mom = new Moment(mom);
-        mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
-    }
-    if (days) {
-        mom = set(mom, 'Date', get(mom, 'Date') + days * isAdding);
-    }
-    if (months) {
-        mom = setMonth(mom, get(mom, 'Month') + months * isAdding);
-    }
-    if (updateOffset) {
-        mom = hooks.updateOffset(mom, days || months);
+    if (months || days) {
+        d = new Date(mom._d);
+        if (months) {
+            // takes care of 31st Jan + 1m -> 28th Feb
+            smartSetUTCMonth(d, d.getUTCMonth() + months);
+        }
+        if (days) {
+            d.setUTCDate(d.getUTCDate() + days);
+        }
+        return quickCreateLocal(d.valueOf() + milliseconds, mom._l, mom._tz);
+    } else {
+        return quickCreateUTC(mom.unix() + milliseconds, mom._l, mom._tz);
     }
-    return mom;
+
+//     if (milliseconds) {
+//         // TODOv3 -- work on the config if necessary
+//         // TODOv3 -- 1) order MS, D, M or M, D, MS
+//         // TODOv3 -- 2) work on date object directly (all operations)
+//         // TODOv3 -- 3) figure out updateOffset so it only happens once in
+//         // constructor
+//         mom = new Moment(mom);
+//         mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
+//     }
+//     if (days) {
+//         mom = set(mom, 'Date', get(mom, 'Date') + days * isAdding);
+//     }
+//     if (months) {
+//         mom = setMonth(mom, get(mom, 'Month') + months * isAdding);
+//     }
+//     if (updateOffset) {
+//         mom = hooks.updateOffset(mom, days || months);
+//     }
+//     return mom;
 }
 
 export var add      = createAdder(1, 'add');
index 4b5725c58b0c17010d99f893995b4f067e80e467..fec062dc94e6699a7a261b2e5cf83e6124a80677 100644 (file)
@@ -16,11 +16,11 @@ export function getCalendarFormat(myMoment, now) {
 export function calendar (time, formats) {
     // We want to compare the start of today, vs this.
     // Getting start-of-today depends on whether we're local/utc/offset or not.
-    var now = time || createLocal(),
+    var now = time != null ? createLocal(time) : createLocal(),
         sod = cloneWithOffset(now, this).startOf('day'),
         format = hooks.calendarFormat(this, sod) || 'sameElse';
 
     var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
 
-    return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
+    return this.format(output || this.localeData().calendar(format, this, now));
 }
index c28cb3c7ac8f29a29c00d93bdb861efa1226f59d..86bd3b11806b98c45198cbd9b88c7fc9f20fc40d 100644 (file)
@@ -66,6 +66,7 @@ export function Moment(config) {
     if (!this.isValid()) {
         this._d = new Date(NaN);
     }
+    this._isAMomentObject = true;
 }
 
 export function isMoment (obj) {
index 54f3f49320ee55f5ddec93ed097950fe5d5b0da3..3e07aff8a447e43644dac2976215d29b592b903a 100644 (file)
@@ -5,30 +5,41 @@ import { hooks } from '../utils/hooks';
 import isFunction from '../utils/is-function';
 
 
-export function makeGetSet (unit, keepTime) {
+export function makeGetSet (unit, msCoef) {
     return function (value) {
         if (value != null) {
-            var mom = set(this, unit, value);
-            return hooks.updateOffset(mom, keepTime);
+            return set(this, unit, value, msCoef);
         } else {
             return get(this, unit);
         }
     };
 }
 
-export function get (mom, unit) {
+function get (mom, unit) {
     return mom.isValid() ?
         mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
 }
 
-export function set (mom, unit, value) {
-    if (mom.isValid()) {
-        mom = new Moment(mom);
-        mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+function set (mom, unit, value, msCoef) {
+    if (!mom.isValid()) {
+        return mom;
+        // TODOv3 -- clone & modify config directly
+    }
+    var d, uts;
+    if (msCoef != null) {
+        // this is one of ms, second, minute, hour
+        uts = mom.unix();
+        uts += (unit - get(mom, unit)) * msCoef;
+        return quickCreateUTC(uts, mom._l, mom._tz);
+    } else {
+        // this is one of day, year. NOT month
+        d = new Date(mom._d);
+        d['setUTC' + unit](value);
+        return quickCreateLocal(d.valueOf(), mom._l, mom._tz);
     }
-    return mom;
 }
 
+
 // MOMENTS
 
 export function stringGet (units) {
index cb8f466796ccc23fbe5901583b205fca2baac5de..5ea89d512dfc5430460301778b1d3f957dea1f9d 100644 (file)
@@ -10,12 +10,11 @@ export function locale (key) {
     if (key === undefined) {
         return this._locale._abbr;
     } else {
-        clone = new Moment(this);
         newLocaleData = getLocale(key);
         if (newLocaleData != null) {
-            clone._locale = newLocaleData;
+            return quickCreateUTC(this.unix(), newLocaleData, this._tz);
         }
-        return clone;
+        return this;
     }
 }
 
index 4626977de0bf2f90584ae783d3d3340456ef83dd..fa51767e47d8bfc81a5635ad2be6730b799c5ca3 100644 (file)
@@ -33,7 +33,7 @@ addParseToken('Do', function (input, array) {
 
 // MOMENTS
 
-export var getSetDayOfMonth = makeGetSet('Date', true);
+export var getSetDayOfMonth = makeGetSet('Date');
 
 // PRIORITY
 
index d4aed9c223e3dec392ecbb83431a37ee29b23868..eeca0dc625d0e9231062cfe37caee7bf26490125 100644 (file)
@@ -138,7 +138,7 @@ export function localeMeridiem (hours, minutes, isLower) {
 // specified which hour he wants. So trying to maintain the same hour (in
 // a new timezone) makes sense. Adding/subtracting hours does not follow
 // this rule.
-export var getSetHour = makeGetSet('Hours', true);
+export var getSetHour = makeGetSet('Hours', 60 * 60 * 1000);
 
 // PRIORITY
 
index d37e1ca142fafb61e92eed7f4298fd32be964c35..309ce3ce3f126150e48311b7a08dfd78b74d6f45 100644 (file)
@@ -61,7 +61,7 @@ for (token = 'S'; token.length <= 9; token += 'S') {
 }
 // MOMENTS
 
-export var getSetMillisecond = makeGetSet('Milliseconds', false);
+export var getSetMillisecond = makeGetSet('Milliseconds', 1);
 
 // PRIORITY
 
index 08b0b6bc4fd48b214cdb8f781f5ea910d0b7fdfb..fabe466ed18539a2eea19a4f57f1b1bfb2d47e03 100644 (file)
@@ -22,7 +22,7 @@ addParseToken(['m', 'mm'], MINUTE);
 
 // MOMENTS
 
-export var getSetMinute = makeGetSet('Minutes', false);
+export var getSetMinute = makeGetSet('Minutes', 60 * 1000);
 
 // PRIORITY
 
index a08ee1961929d06388b4f148daacaa7938cdcb9d..f89d2de61d7233d075ae4d68408cf289dc3ef417 100644 (file)
@@ -167,7 +167,7 @@ export function localeMonthsParse (monthName, format, strict) {
 // MOMENTS
 
 export function setMonth (mom, value) {
-    var dayOfMonth;
+    var d;
 
     if (!mom.isValid()) {
         // No op
@@ -186,16 +186,21 @@ export function setMonth (mom, value) {
         }
     }
 
-    dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
-    mom = new Moment(mom);
-    mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
-    return mom;
+    // TODOv3 -- there is a low-level set method, this should be one of its
+    // cases.
+    d = new Date(mom._d);
+    smartSetUTCMonth(d, value);
+    return quickCreateLocal(d.valueOf(), mom._l, mom._tz);
+}
+
+export function smartSetUTCMonth(d, month) {
+    var dayOfMonth = Math.min(d.getUTCDate(), daysInMonth(d.getUTCFullYear(), value));
+    d.setUTCMonth(value, dayOfMonth);
 }
 
 export function getSetMonth (value) {
     if (value != null) {
-        var mom = setMonth(this, value);
-        return hooks.updateOffset(mom, true);
+        return setMonth(this, value);
     } else {
         return get(this, 'Month');
     }
index 03d3bd8e7ecb53f98cb7c7bdc17da9f4119a3d2b..5adbbfb819c0bcb69674a445d2337769e1c8c9ae 100644 (file)
@@ -6,7 +6,7 @@ import { addFormatToken } from '../format/format';
 import { addRegexToken, matchOffset, matchShortOffset } from '../parse/regex';
 import { addParseToken } from '../parse/token';
 import { createLocal } from '../create/local';
-import { prepareConfig } from '../create/from-anything';
+import { quickCreateLocal, quickCreateUTC } from '../create/from-anything';
 import { createUTC } from '../create/utc';
 import isDate from '../utils/is-date';
 import toInt from '../utils/to-int';
@@ -36,7 +36,6 @@ offset('ZZ', '');
 addRegexToken('Z',  matchShortOffset);
 addRegexToken('ZZ', matchShortOffset);
 addParseToken(['Z', 'ZZ'], function (input, array, config) {
-    config._useUTC = true;
     config._tzm = offsetFromString(matchShortOffset, input);
 });
 
@@ -65,16 +64,9 @@ function offsetFromString(matcher, string) {
 
 // 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 = new Moment(model);
-        diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
-        // Use low-level api, because this fn is low-level api.
-        res._d.setTime(res._d.valueOf() + diff);
-        return hooks.updateOffset(res, false);
-    } else {
-        return createLocal(input).local();
-    }
+    // TODO: input could be a non-moment object, in certain cases
+    // createLocal("....z") --> is this UTC?
+    return changeTimezone(input, model._tz);
 }
 
 function getDateOffset (m) {
@@ -91,9 +83,10 @@ function getDateOffset (m) {
 // Because Moment's external API is immutable and this hook will be defined
 // externally (e.g. by Moment Timezone), this hook must return a (possibly new)
 // Moment instance that reflects the correctly-updated offset.
-hooks.updateOffset = function (m) {
-    return m;
-};
+// hooks.updateOffset = function (m) {
+//     return m;
+// };
+// TODO: Fix usages, if any
 
 // MOMENTS
 
@@ -107,13 +100,18 @@ hooks.updateOffset = function (m) {
 // 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, keepMinutes) {
-    var mom = this,
-        offset = mom._offset || 0,
-        localAdjust;
-    if (!mom.isValid()) {
-        return input != null ? mom : NaN;
+
+function changeTimezone(mom, newTz, keepLocalTime) {
+    // TODO: Check if newTz is same as current (by comparing zone._key or sth)
+    // -- it is used a lot with possibly same tz (from cloneWithOffset)
+    if (keepLocalTime) {
+        return quickCreateLocal(mom._d.valueOf(), mom._l, newTz);
+    } else {
+        return quickCreateUTC(mom.unix(), mom._l, newTz);
     }
+}
+
+export function getSetOffset (input, keepLocalTime, keepMinutes) {
     if (input != null) {
         if (typeof input === 'string') {
             input = offsetFromString(matchShortOffset, input);
@@ -123,30 +121,62 @@ export function getSetOffset (input, keepLocalTime, keepMinutes) {
         } else if (Math.abs(input) < 16 && !keepMinutes) {
             input = input * 60;
         }
-        if (!mom._isUTC && keepLocalTime) {
-            localAdjust = getDateOffset(mom);
-        }
-        mom = new Moment(mom);
-        mom._offset = input;
-        mom._isUTC = true;
-        if (localAdjust != null) {
-            mom = mom.add(localAdjust, 'm');
-        }
-        if (offset !== input) {
-            if (!keepLocalTime || mom._changeInProgress) {
-                mom = addSubtract(mom, createDuration(input - offset, 'm'), 1, false);
-            } else if (!mom._changeInProgress) {
-                mom._changeInProgress = true;
-                mom = hooks.updateOffset(mom, true);
-                mom._changeInProgress = null;
-            }
-        }
-        return mom;
+        // not sure we need this no-op case, for speed I guess
+        // if (this._tz.type === 'fixed-offset' && this._tz.offset === input) {
+        //     return mom;
+        // }
+        var newTz = FixedOffsetTimeZone.fromOffset(input);
+        return changeTimezone(this, newTz, keepLocalTime);
     } else {
-        return mom._isUTC ? offset : getDateOffset(mom);
+        return this._offset / 60000;
     }
 }
 
+
+
+// export function getSetOffset (input, keepLocalTime, keepMinutes) {
+//     var mom = this,
+//         offset = mom._offset || 0,
+//         localAdjust;
+//     if (!mom.isValid()) {
+//         return input != null ? mom : NaN;
+//     }
+//     if (input != null) {
+//         if (typeof input === 'string') {
+//             input = offsetFromString(matchShortOffset, input);
+//             if (input === null) {
+//                 return mom;
+//             }
+//         } else if (Math.abs(input) < 16 && !keepMinutes) {
+//             input = input * 60;
+//         }
+//         if (!mom._isUTC && keepLocalTime) {
+//             localAdjust = getDateOffset(mom);
+//         }
+//         // TODOv3 -- the new zone api should support 'is valid' that checks for
+//         // a 'hole', and maybe ambiguity (overlap). This logic could be reorganized
+//         // afterwards.
+//         mom = new Moment(mom);
+//         mom._offset = input;
+//         mom._isUTC = true;
+//         if (localAdjust != null) {
+//             mom = mom.add(localAdjust, 'm');
+//         }
+//         if (offset !== input) {
+//             if (!keepLocalTime || mom._changeInProgress) {
+//                 mom = addSubtract(mom, createDuration(input - offset, 'm'), 1, false);
+//             } else if (!mom._changeInProgress) {
+//                 mom._changeInProgress = true;
+//                 mom = hooks.updateOffset(mom, true);
+//                 mom._changeInProgress = null;
+//             }
+//         }
+//         return mom;
+//     } else {
+//         return mom._isUTC ? offset : getDateOffset(mom);
+//     }
+// }
+
 export function getSetZone (input, keepLocalTime) {
     if (input != null) {
         if (typeof input !== 'string') {
@@ -160,20 +190,11 @@ export function getSetZone (input, keepLocalTime) {
 }
 
 export function setOffsetToUTC (keepLocalTime) {
-    return this.utcOffset(0, keepLocalTime);
+    return changeTimezone(this, FixedOffsetTimeZone.fromOffset(0), keepLocalTime);
 }
 
 export function setOffsetToLocal (keepLocalTime) {
-    var ret = this;
-    if (ret._isUTC) {
-        ret = ret.utcOffset(0, keepLocalTime);
-        ret._isUTC = false;
-
-        if (keepLocalTime) {
-            ret = ret.subtract(getDateOffset(ret), 'm');
-        }
-    }
-    return ret;
+    return changeTimezone(this, LocalTimeZone.instance(), keepLocalTime);
 }
 
 export function setOffsetToParsedOffset () {
@@ -208,35 +229,38 @@ export function isDaylightSavingTime () {
     );
 }
 
-export function isDaylightSavingTimeShifted () {
-    if (!isUndefined(this._isDSTShifted)) {
-        return this._isDSTShifted;
-    }
+// TODO: We could do this properly, but I don't think we should.
+// Maybe expose the local -> [local, offset] function and let people shoot
+// themselves in the foot
+// export function isDaylightSavingTimeShifted () {
+//     if (!isUndefined(this._isDSTShifted)) {
+//         return this._isDSTShifted;
+//     }
 
-    var c = {};
+//     var c = {};
 
-    copyConfig(c, this);
-    c = prepareConfig(c);
+//     copyConfig(c, this);
+//     c = prepareConfig(c);
 
-    if (c._a) {
-        var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
-        this._isDSTShifted = this.isValid() &&
-            compareArrays(c._a, other.toArray()) > 0;
-    } else {
-        this._isDSTShifted = false;
-    }
+//     if (c._a) {
+//         var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
+//         this._isDSTShifted = this.isValid() &&
+//             compareArrays(c._a, other.toArray()) > 0;
+//     } else {
+//         this._isDSTShifted = false;
+//     }
 
-    return this._isDSTShifted;
-}
+//     return this._isDSTShifted;
+// }
 
 export function isLocal () {
-    return this.isValid() ? !this._isUTC : false;
+    return this._tz.type == 'local';
 }
 
 export function isUtcOffset () {
-    return this.isValid() ? this._isUTC : false;
+    return this._tz.type == 'fixed-offset';
 }
 
 export function isUtc () {
-    return this.isValid() ? this._isUTC && this._offset === 0 : false;
+    return this._tz.type == 'fixed-offset' && this._tz.offset === 0;
 }
index 8f6952f1e9035e69d1ccf1e0ee57a7aa05e57c28..9fdf6342637c1150cf02ad63168da260951299a2 100644 (file)
@@ -22,7 +22,7 @@ addParseToken(['s', 'ss'], SECOND);
 
 // MOMENTS
 
-export var getSetSecond = makeGetSet('Seconds', false);
+export var getSetSecond = makeGetSet('Seconds', 1000);
 
 // PRIORITY
 
index 5be8a5fa6eca9959513f45fbbbd3f2d991df7b0a..b9aaab6d39e627183d76293314403d0d0c494593 100644 (file)
@@ -1,5 +1,4 @@
 import { daysInYear } from './year';
-import { createLocal } from '../create/local';
 import { createUTCDate } from '../create/date-from-array';
 
 // start-of-first-week - start-of-year
index 42fad5f9858bff52e666f673c7b39c89deee85eb..39e367ab79822c10d5c55b0bd1338bd36e3992d1 100644 (file)
@@ -1,4 +1,3 @@
-import { Moment } from '../moment/constructor';
 import { addFormatToken } from '../format/format';
 import { addUnitAlias } from './aliases';
 import { addUnitPriority } from './priorities';
@@ -7,7 +6,7 @@ import { addWeekParseToken } from '../parse/token';
 import { weekOfYear, weeksInYear, dayOfYearFromWeeks } from './week-calendar-utils';
 import toInt from '../utils/to-int';
 import { hooks } from '../utils/hooks';
-import { createLocal } from '../create/local';
+import { quickCreateLocal } from '../create/from-anything';
 import { createUTCDate } from '../create/date-from-array';
 import { getSetDayOfMonth } from './day-of-month';
 import { getSetMonth } from './month';
@@ -97,12 +96,13 @@ function getSetWeekYearHelper(mom, input, week, weekday, dow, doy) {
 
 function setWeekAll(mom, weekYear, week, weekday, dow, doy) {
     var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
-        date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
+        date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear),
+        d = new Date(mom._d);
 
-    mom = new Moment(mom);
-    mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'FullYear'](
-        date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
-    return mom;
+    // TODOv3 -- I guess the generic set method should accept all args that the Date
+    // object accepts.
+    d.setUTCFullYear(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
+    return quickCreateLocal(d.valueOf(), mom._l, mom._tz);
 }
 
 // PRIORITY
index e63b3e109dd786e2d3f7a61ee7f2b29e204a1ce5..f03a3d6ea44660472f4dd8db2f8f5c9252e34e62 100644 (file)
@@ -4,7 +4,6 @@ import { addUnitPriority } from './priorities';
 import { addRegexToken, match1to2, match2 } from '../parse/regex';
 import { addWeekParseToken } from '../parse/token';
 import toInt from '../utils/to-int';
-import { createLocal } from '../create/local';
 import { weekOfYear } from './week-calendar-utils';
 
 // FORMATTING
index 47353a0442df8601efad13f182bde96b9d15a4c9..72a08ce610cc6cdb745bbe7da181c85d7ddcbc28 100644 (file)
@@ -64,7 +64,7 @@ hooks.parseTwoDigitYear = function (input) {
 
 // MOMENTS
 
-export var getSetYear = makeGetSet('FullYear', true);
+export var getSetYear = makeGetSet('FullYear');
 
 export function getIsLeapYear () {
     return isLeapYear(this.year());