text: /** 
   * vis-data - data
   * http://visjs.org/
   * 
   * Manage unstructured data using DataSet. Add, update, and remove data, and listen for changes in the data.
   * 
   * @version 6.2.1
   * @date    2019-09-13T21:24:53Z
   * 
   * @copyright (c) 2011-2017 Almende B.V, http://almende.com
   * @copyright (c) 2018-2019 visjs contributors, https://github.com/visjs
   * 
   * @license 
   * vis.js is dual licensed under both
   * 
   *   1. The Apache 2.0 License
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   *   and
   * 
   *   2. The MIT License
   *      http://opensource.org/licenses/MIT
   * 
   * vis.js may be distributed under either license.
   */
  function createCommonjsModule(fn, module) {
  	return module = { exports: {} }, fn(module, module.exports), module.exports;
  }
  
  var runtime_1 = createCommonjsModule(function (module) {
    /**
     * Copyright (c) 2014-present, Facebook, Inc.
     *
     * This source code is licensed under the MIT license found in the
     * LICENSE file in the root directory of this source tree.
     */
    var runtime = function (exports) {
  
      var Op = Object.prototype;
      var hasOwn = Op.hasOwnProperty;
      var undefined$1; // More compressible than void 0.
  
      var $Symbol = typeof Symbol === "function" ? Symbol : {};
      var iteratorSymbol = $Symbol.iterator || "@@iterator";
      var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
      var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
  
      function wrap(innerFn, outerFn, self, tryLocsList) {
        // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
        var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
        var generator = Object.create(protoGenerator.prototype);
        var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next,
        // .throw, and .return methods.
  
        generator._invoke = makeInvokeMethod(innerFn, self, context);
        return generator;
      }
  
      exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion
      // record like context.tryEntries[i].completion. This interface could
      // have been (and was previously) designed to take a closure to be
      // invoked without arguments, but in all the cases we care about we
      // already have an existing method we want to call, so there's no need
      // to create a new function object. We can even get away with assuming
      // the method takes exactly one argument, since that happens to be true
      // in every case, so we don't have to touch the arguments object. The
      // only additional allocation required is the completion record, which
      // has a stable shape and so hopefully should be cheap to allocate.
  
      function tryCatch(fn, obj, arg) {
        try {
          return {
            type: "normal",
            arg: fn.call(obj, arg)
          };
        } catch (err) {
          return {
            type: "throw",
            arg: err
          };
        }
      }
  
      var GenStateSuspendedStart = "suspendedStart";
      var GenStateSuspendedYield = "suspendedYield";
      var GenStateExecuting = "executing";
      var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as
      // breaking out of the dispatch switch statement.
  
      var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and
      // .constructor.prototype properties for functions that return Generator
      // objects. For full spec compliance, you may wish to configure your
      // minifier not to mangle the names of these two functions.
  
      function Generator() {}
  
      function GeneratorFunction() {}
  
      function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that
      // don't natively support it.
  
  
      var IteratorPrototype = {};
  
      IteratorPrototype[iteratorSymbol] = function () {
        return this;
      };
  
      var getProto = Object.getPrototypeOf;
      var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
  
      if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
        // This environment has a native %IteratorPrototype%; use it instead
        // of the polyfill.
        IteratorPrototype = NativeIteratorPrototype;
      }
  
      var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
      GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
      GeneratorFunctionPrototype.constructor = GeneratorFunction;
      GeneratorFunctionPrototype[toStringTagSymbol] = GeneratorFunction.displayName = "GeneratorFunction"; // Helper for defining the .next, .throw, and .return methods of the
      // Iterator interface in terms of a single ._invoke method.
  
      function defineIteratorMethods(prototype) {
        ["next", "throw", "return"].forEach(function (method) {
          prototype[method] = function (arg) {
            return this._invoke(method, arg);
          };
        });
      }
  
      exports.isGeneratorFunction = function (genFun) {
        var ctor = typeof genFun === "function" && genFun.constructor;
        return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can
        // do is to check its .name property.
        (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
      };
  
      exports.mark = function (genFun) {
        if (Object.setPrototypeOf) {
          Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
        } else {
          genFun.__proto__ = GeneratorFunctionPrototype;
  
          if (!(toStringTagSymbol in genFun)) {
            genFun[toStringTagSymbol] = "GeneratorFunction";
          }
        }
  
        genFun.prototype = Object.create(Gp);
        return genFun;
      }; // Within the body of any async function, `await x` is transformed to
      // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
      // `hasOwn.call(value, "__await")` to determine if the yielded value is
      // meant to be awaited.
  
  
      exports.awrap = function (arg) {
        return {
          __await: arg
        };
      };
  
      function AsyncIterator(generator) {
        function invoke(method, arg, resolve, reject) {
          var record = tryCatch(generator[method], generator, arg);
  
          if (record.type === "throw") {
            reject(record.arg);
          } else {
            var result = record.arg;
            var value = result.value;
  
            if (value && typeof value === "object" && hasOwn.call(value, "__await")) {
              return Promise.resolve(value.__await).then(function (value) {
                invoke("next", value, resolve, reject);
              }, function (err) {
                invoke("throw", err, resolve, reject);
              });
            }
  
            return Promise.resolve(value).then(function (unwrapped) {
              // When a yielded Promise is resolved, its final value becomes
              // the .value of the Promise<{value,done}> result for the
              // current iteration.
              result.value = unwrapped;
              resolve(result);
            }, function (error) {
              // If a rejected Promise was yielded, throw the rejection back
              // into the async generator function so it can be handled there.
              return invoke("throw", error, resolve, reject);
            });
          }
        }
  
        var previousPromise;
  
        function enqueue(method, arg) {
          function callInvokeWithMethodAndArg() {
            return new Promise(function (resolve, reject) {
              invoke(method, arg, resolve, reject);
            });
          }
  
          return previousPromise = // If enqueue has been called before, then we want to wait until
          // all previous Promises have been resolved before calling invoke,
          // so that results are always delivered in the correct order. If
          // enqueue has not been called before, then it is important to
          // call invoke immediately, without waiting on a callback to fire,
          // so that the async generator function has the opportunity to do
          // any necessary setup in a predictable way. This predictability
          // is why the Promise constructor synchronously invokes its
          // executor callback, and why async functions synchronously
          // execute code before the first await. Since we implement simple
          // async functions in terms of async generators, it is especially
          // important to get this right, even though it requires care.
          previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later
          // invocations of the iterator.
          callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
        } // Define the unified helper method that is used to implement .next,
        // .throw, and .return (see defineIteratorMethods).
  
  
        this._invoke = enqueue;
      }
  
      defineIteratorMethods(AsyncIterator.prototype);
  
      AsyncIterator.prototype[asyncIteratorSymbol] = function () {
        return this;
      };
  
      exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of
      // AsyncIterator objects; they just return a Promise for the value of
      // the final result produced by the iterator.
  
      exports.async = function (innerFn, outerFn, self, tryLocsList) {
        var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList));
        return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator.
        : iter.next().then(function (result) {
          return result.done ? result.value : iter.next();
        });
      };
  
      function makeInvokeMethod(innerFn, self, context) {
        var state = GenStateSuspendedStart;
        return function invoke(method, arg) {
          if (state === GenStateExecuting) {
            throw new Error("Generator is already running");
          }
  
          if (state === GenStateCompleted) {
            if (method === "throw") {
              throw arg;
            } // Be forgiving, per 25.3.3.3.3 of the spec:
            // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
  
  
            return doneResult();
          }
  
          context.method = method;
          context.arg = arg;
  
          while (true) {
            var delegate = context.delegate;
  
            if (delegate) {
              var delegateResult = maybeInvokeDelegate(delegate, context);
  
              if (delegateResult) {
                if (delegateResult === ContinueSentinel) continue;
                return delegateResult;
              }
            }
  
            if (context.method === "next") {
              // Setting context._sent for legacy support of Babel's
              // function.sent implementation.
              context.sent = context._sent = context.arg;
            } else if (context.method === "throw") {
              if (state === GenStateSuspendedStart) {
                state = GenStateCompleted;
                throw context.arg;
              }
  
              context.dispatchException(context.arg);
            } else if (context.method === "return") {
              context.abrupt("return", context.arg);
            }
  
            state = GenStateExecuting;
            var record = tryCatch(innerFn, self, context);
  
            if (record.type === "normal") {
              // If an exception is thrown from innerFn, we leave state ===
              // GenStateExecuting and loop back for another invocation.
              state = context.done ? GenStateCompleted : GenStateSuspendedYield;
  
              if (record.arg === ContinueSentinel) {
                continue;
              }
  
              return {
                value: record.arg,
                done: context.done
              };
            } else if (record.type === "throw") {
              state = GenStateCompleted; // Dispatch the exception by looping back around to the
              // context.dispatchException(context.arg) call above.
  
              context.method = "throw";
              context.arg = record.arg;
            }
          }
        };
      } // Call delegate.iterator[context.method](context.arg) and handle the
      // result, either by returning a { value, done } result from the
      // delegate iterator, or by modifying context.method and context.arg,
      // setting context.delegate to null, and returning the ContinueSentinel.
  
  
      function maybeInvokeDelegate(delegate, context) {
        var method = delegate.iterator[context.method];
  
        if (method === undefined$1) {
          // A .throw or .return when the delegate iterator has no .throw
          // method always terminates the yield* loop.
          context.delegate = null;
  
          if (context.method === "throw") {
            // Note: ["return"] must be used for ES3 parsing compatibility.
            if (delegate.iterator["return"]) {
              // If the delegate iterator has a return method, give it a
              // chance to clean up.
              context.method = "return";
              context.arg = undefined$1;
              maybeInvokeDelegate(delegate, context);
  
              if (context.method === "throw") {
                // If maybeInvokeDelegate(context) changed context.method from
                // "return" to "throw", let that override the TypeError below.
                return ContinueSentinel;
              }
            }
  
            context.method = "throw";
            context.arg = new TypeError("The iterator does not provide a 'throw' method");
          }
  
          return ContinueSentinel;
        }
  
        var record = tryCatch(method, delegate.iterator, context.arg);
  
        if (record.type === "throw") {
          context.method = "throw";
          context.arg = record.arg;
          context.delegate = null;
          return ContinueSentinel;
        }
  
        var info = record.arg;
  
        if (!info) {
          context.method = "throw";
          context.arg = new TypeError("iterator result is not an object");
          context.delegate = null;
          return ContinueSentinel;
        }
  
        if (info.done) {
          // Assign the result of the finished delegate to the temporary
          // variable specified by delegate.resultName (see delegateYield).
          context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield).
  
          context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the
          // exception, let the outer generator proceed normally. If
          // context.method was "next", forget context.arg since it has been
          // "consumed" by the delegate iterator. If context.method was
          // "return", allow the original .return call to continue in the
          // outer generator.
  
          if (context.method !== "return") {
            context.method = "next";
            context.arg = undefined$1;
          }
        } else {
          // Re-yield the result returned by the delegate method.
          return info;
        } // The delegate iterator is finished, so forget it and continue with
        // the outer generator.
  
  
        context.delegate = null;
        return ContinueSentinel;
      } // Define Generator.prototype.{next,throw,return} in terms of the
      // unified ._invoke helper method.
  
  
      defineIteratorMethods(Gp);
      Gp[toStringTagSymbol] = "Generator"; // A Generator should always return itself as the iterator object when the
      // @@iterator function is called on it. Some browsers' implementations of the
      // iterator prototype chain incorrectly implement this, causing the Generator
      // object to not be returned from this call. This ensures that doesn't happen.
      // See https://github.com/facebook/regenerator/issues/274 for more details.
  
      Gp[iteratorSymbol] = function () {
        return this;
      };
  
      Gp.toString = function () {
        return "[object Generator]";
      };
  
      function pushTryEntry(locs) {
        var entry = {
          tryLoc: locs[0]
        };
  
        if (1 in locs) {
          entry.catchLoc = locs[1];
        }
  
        if (2 in locs) {
          entry.finallyLoc = locs[2];
          entry.afterLoc = locs[3];
        }
  
        this.tryEntries.push(entry);
      }
  
      function resetTryEntry(entry) {
        var record = entry.completion || {};
        record.type = "normal";
        delete record.arg;
        entry.completion = record;
      }
  
      function Context(tryLocsList) {
        // The root entry object (effectively a try statement without a catch
        // or a finally block) gives us a place to store values thrown from
        // locations where there is no enclosing try statement.
        this.tryEntries = [{
          tryLoc: "root"
        }];
        tryLocsList.forEach(pushTryEntry, this);
        this.reset(true);
      }
  
      exports.keys = function (object) {
        var keys = [];
  
        for (var key in object) {
          keys.push(key);
        }
  
        keys.reverse(); // Rather than returning an object with a next method, we keep
        // things simple and return the next function itself.
  
        return function next() {
          while (keys.length) {
            var key = keys.pop();
  
            if (key in object) {
              next.value = key;
              next.done = false;
              return next;
            }
          } // To avoid creating an additional object, we just hang the .value
          // and .done properties off the next function object itself. This
          // also ensures that the minifier will not anonymize the function.
  
  
          next.done = true;
          return next;
        };
      };
  
      function values(iterable) {
        if (iterable) {
          var iteratorMethod = iterable[iteratorSymbol];
  
          if (iteratorMethod) {
            return iteratorMethod.call(iterable);
          }
  
          if (typeof iterable.next === "function") {
            return iterable;
          }
  
          if (!isNaN(iterable.length)) {
            var i = -1,
                next = function next() {
              while (++i < iterable.length) {
                if (hasOwn.call(iterable, i)) {
                  next.value = iterable[i];
                  next.done = false;
                  return next;
                }
              }
  
              next.value = undefined$1;
              next.done = true;
              return next;
            };
  
            return next.next = next;
          }
        } // Return an iterator with no values.
  
  
        return {
          next: doneResult
        };
      }
  
      exports.values = values;
  
      function doneResult() {
        return {
          value: undefined$1,
          done: true
        };
      }
  
      Context.prototype = {
        constructor: Context,
        reset: function (skipTempReset) {
          this.prev = 0;
          this.next = 0; // Resetting context._sent for legacy support of Babel's
          // function.sent implementation.
  
          this.sent = this._sent = undefined$1;
          this.done = false;
          this.delegate = null;
          this.method = "next";
          this.arg = undefined$1;
          this.tryEntries.forEach(resetTryEntry);
  
          if (!skipTempReset) {
            for (var name in this) {
              // Not sure about the optimal order of these conditions:
              if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
                this[name] = undefined$1;
              }
            }
          }
        },
        stop: function () {
          this.done = true;
          var rootEntry = this.tryEntries[0];
          var rootRecord = rootEntry.completion;
  
          if (rootRecord.type === "throw") {
            throw rootRecord.arg;
          }
  
          return this.rval;
        },
        dispatchException: function (exception) {
          if (this.done) {
            throw exception;
          }
  
          var context = this;
  
          function handle(loc, caught) {
            record.type = "throw";
            record.arg = exception;
            context.next = loc;
  
            if (caught) {
              // If the dispatched exception was caught by a catch block,
              // then let that catch block handle the exception normally.
              context.method = "next";
              context.arg = undefined$1;
            }
  
            return !!caught;
          }
  
          for (var i = this.tryEntries.length - 1; i >= 0; --i) {
            var entry = this.tryEntries[i];
            var record = entry.completion;
  
            if (entry.tryLoc === "root") {
              // Exception thrown outside of any try block that could handle
              // it, so set the completion value of the entire function to
              // throw the exception.
              return handle("end");
            }
  
            if (entry.tryLoc <= this.prev) {
              var hasCatch = hasOwn.call(entry, "catchLoc");
              var hasFinally = hasOwn.call(entry, "finallyLoc");
  
              if (hasCatch && hasFinally) {
                if (this.prev < entry.catchLoc) {
                  return handle(entry.catchLoc, true);
                } else if (this.prev < entry.finallyLoc) {
                  return handle(entry.finallyLoc);
                }
              } else if (hasCatch) {
                if (this.prev < entry.catchLoc) {
                  return handle(entry.catchLoc, true);
                }
              } else if (hasFinally) {
                if (this.prev < entry.finallyLoc) {
                  return handle(entry.finallyLoc);
                }
              } else {
                throw new Error("try statement without catch or finally");
              }
            }
          }
        },
        abrupt: function (type, arg) {
          for (var i = this.tryEntries.length - 1; i >= 0; --i) {
            var entry = this.tryEntries[i];
  
            if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
              var finallyEntry = entry;
              break;
            }
          }
  
          if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
            // Ignore the finally entry if control is not jumping to a
            // location outside the try/catch block.
            finallyEntry = null;
          }
  
          var record = finallyEntry ? finallyEntry.completion : {};
          record.type = type;
          record.arg = arg;
  
          if (finallyEntry) {
            this.method = "next";
            this.next = finallyEntry.finallyLoc;
            return ContinueSentinel;
          }
  
          return this.complete(record);
        },
        complete: function (record, afterLoc) {
          if (record.type === "throw") {
            throw record.arg;
          }
  
          if (record.type === "break" || record.type === "continue") {
            this.next = record.arg;
          } else if (record.type === "return") {
            this.rval = this.arg = record.arg;
            this.method = "return";
            this.next = "end";
          } else if (record.type === "normal" && afterLoc) {
            this.next = afterLoc;
          }
  
          return ContinueSentinel;
        },
        finish: function (finallyLoc) {
          for (var i = this.tryEntries.length - 1; i >= 0; --i) {
            var entry = this.tryEntries[i];
  
            if (entry.finallyLoc === finallyLoc) {
              this.complete(entry.completion, entry.afterLoc);
              resetTryEntry(entry);
              return ContinueSentinel;
            }
          }
        },
        "catch": function (tryLoc) {
          for (var i = this.tryEntries.length - 1; i >= 0; --i) {
            var entry = this.tryEntries[i];
  
            if (entry.tryLoc === tryLoc) {
              var record = entry.completion;
  
              if (record.type === "throw") {
                var thrown = record.arg;
                resetTryEntry(entry);
              }
  
              return thrown;
            }
          } // The context.catch method must only be called with a location
          // argument that corresponds to a known catch block.
  
  
          throw new Error("illegal catch attempt");
        },
        delegateYield: function (iterable, resultName, nextLoc) {
          this.delegate = {
            iterator: values(iterable),
            resultName: resultName,
            nextLoc: nextLoc
          };
  
          if (this.method === "next") {
            // Deliberately forget the last sent value so that we don't
            // accidentally pass it on to the delegate.
            this.arg = undefined$1;
          }
  
          return ContinueSentinel;
        }
      }; // Regardless of whether this script is executing as a CommonJS module
      // or not, return the runtime object so that we can declare the variable
      // regeneratorRuntime in the outer scope, which allows this module to be
      // injected easily by `bin/regenerator --include-runtime script.js`.
  
      return exports;
    }( // If this script is executing as a CommonJS module, use module.exports
    // as the regeneratorRuntime namespace. Otherwise create a new empty
    // object. Either way, the resulting object will be used to initialize
    // the regeneratorRuntime variable at the top of this file.
     module.exports );
  
    try {
      regeneratorRuntime = runtime;
    } catch (accidentalStrictMode) {
      // This module should not be running in strict mode, so the above
      // assignment should always work unless something is misconfigured. Just
      // in case runtime.js accidentally runs in strict mode, we can escape
      // strict mode using a global Function call. This could conceivably fail
      // if a Content Security Policy forbids using Function, but in that case
      // the proper solution is to fix the accidental strict mode problem. If
      // you've misconfigured your bundler to force strict mode and applied a
      // CSP to forbid Function, and you're not willing to fix either of those
      // problems, please detail your unique predicament in a GitHub issue.
      Function("r", "regeneratorRuntime = r")(runtime);
    }
  });
  
  var regenerator = runtime_1;
  
  function _defineProperty(obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }
  
    return obj;
  }
  
  var defineProperty = _defineProperty;
  
  function _arrayWithoutHoles(arr) {
    if (Array.isArray(arr)) {
      for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
        arr2[i] = arr[i];
      }
  
      return arr2;
    }
  }
  
  var arrayWithoutHoles = _arrayWithoutHoles;
  
  function _iterableToArray(iter) {
    if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
  }
  
  var iterableToArray = _iterableToArray;
  
  function _nonIterableSpread() {
    throw new TypeError("Invalid attempt to spread non-iterable instance");
  }
  
  var nonIterableSpread = _nonIterableSpread;
  
  function _toConsumableArray(arr) {
    return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread();
  }
  
  var toConsumableArray = _toConsumableArray;
  
  var _typeof_1 = createCommonjsModule(function (module) {
    function _typeof2(obj) {
      if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
        _typeof2 = function _typeof2(obj) {
          return typeof obj;
        };
      } else {
        _typeof2 = function _typeof2(obj) {
          return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
      }
  
      return _typeof2(obj);
    }
  
    function _typeof(obj) {
      if (typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol") {
        module.exports = _typeof = function _typeof(obj) {
          return _typeof2(obj);
        };
      } else {
        module.exports = _typeof = function _typeof(obj) {
          return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
        };
      }
  
      return _typeof(obj);
    }
  
    module.exports = _typeof;
  });
  
  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }
  
  var classCallCheck = _classCallCheck;
  
  function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }
  
  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
  }
  
  var createClass = _createClass;
  
  function _assertThisInitialized(self) {
    if (self === void 0) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
  
    return self;
  }
  
  var assertThisInitialized = _assertThisInitialized;
  
  function _possibleConstructorReturn(self, call) {
    if (call && (_typeof_1(call) === "object" || typeof call === "function")) {
      return call;
    }
  
    return assertThisInitialized(self);
  }
  
  var possibleConstructorReturn = _possibleConstructorReturn;
  
  var getPrototypeOf = createCommonjsModule(function (module) {
    function _getPrototypeOf(o) {
      module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
        return o.__proto__ || Object.getPrototypeOf(o);
      };
      return _getPrototypeOf(o);
    }
  
    module.exports = _getPrototypeOf;
  });
  
  var setPrototypeOf = createCommonjsModule(function (module) {
    function _setPrototypeOf(o, p) {
      module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
        o.__proto__ = p;
        return o;
      };
  
      return _setPrototypeOf(o, p);
    }
  
    module.exports = _setPrototypeOf;
  });
  
  function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function");
    }
  
    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        writable: true,
        configurable: true
      }
    });
    if (superClass) setPrototypeOf(subClass, superClass);
  }
  
  var inherits = _inherits;
  
  // Maps for number <-> hex string conversion
  var byteToHex = [];
  
  for (var i = 0; i < 256; i++) {
    byteToHex[i] = (i + 0x100).toString(16).substr(1);
  }
  /**
   * Represent binary UUID into it's string representation.
   *
   * @param buf - Buffer containing UUID bytes.
   * @param offset - Offset from the start of the buffer where the UUID is saved (not needed if the buffer starts with the UUID).
   *
   * @returns String representation of the UUID.
   */
  
  
  function stringifyUUID(buf, offset) {
    var i = offset || 0;
    var bth = byteToHex;
    return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
  }
  /**
   * Generate 16 random bytes to be used as a base for UUID.
   *
   * @ignore
   */
  
  
  var random = function () {
    if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
      // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
      // Moderately fast, high quality
      var _rnds8 = new Uint8Array(16);
  
      return function whatwgRNG() {
        crypto.getRandomValues(_rnds8);
        return _rnds8;
      };
    } // Math.random()-based (RNG)
    //
    // If all else fails, use Math.random().
    // It's fast, but is of unspecified quality.
  
  
    var _rnds = new Array(16);
  
    return function () {
      for (var i = 0, r; i < 16; i++) {
        if ((i & 0x03) === 0) {
          r = Math.random() * 0x100000000;
        }
  
        _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
      }
  
      return _rnds;
    }; //     uuid.js
    //
    //     Copyright (c) 2010-2012 Robert Kieffer
    //     MIT License - http://opensource.org/licenses/mit-license.php
    // Unique ID creation requires a high quality random # generator.  We feature
    // detect to determine the best RNG source, normalizing to a function that
    // returns 128-bits of randomness, since that's what's usually required
    // return require('./rng');
  }();
  
  var byteToHex$1 = [];
  
  for (var i$1 = 0; i$1 < 256; i$1++) {
    byteToHex$1[i$1] = (i$1 + 0x100).toString(16).substr(1);
  } // **`v1()` - Generate time-based UUID**
  //
  // Inspired by https://github.com/LiosK/UUID.js
  // and http://docs.python.org/library/uuid.html
  // random #'s we need to init node and clockseq
  
  
  var seedBytes = random(); // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
  
  var defaultNodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; // Per 4.2.2, randomize (14 bit) clockseq
  
  var defaultClockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; // Previous uuid creation time
  /**
   * UUIDv4 options.
   */
  
  /**
   * Generate UUIDv4
   *
   * @param options - Options to be used instead of default generated values.
   * String 'binary' is a shorthand for uuid4({}, new Array(16)).
   * @param buf - If present the buffer will be filled with the generated UUID.
   * @param offset - Offset of the UUID from the start of the buffer.
   *
   * @returns UUIDv4
   */
  
  
  function uuid4() {
    var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    var buf = arguments.length > 1 ? arguments[1] : undefined;
    var offset = arguments.length > 2 ? arguments[2] : undefined; // Deprecated - 'format' argument, as supported in v1.2
  
    var i = buf && offset || 0;
  
    if (typeof options === 'string') {
      buf = options === 'binary' ? new Array(16) : undefined;
      options = {};
    }
  
    var rnds = options.random || (options.rng || random)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
  
    rnds[6] = rnds[6] & 0x0f | 0x40;
    rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
  
    if (buf) {
      for (var ii = 0; ii < 16; ii++) {
        buf[i + ii] = rnds[ii];
      }
    }
  
    return buf || stringifyUUID(rnds);
  } // Rollup will complain about mixing default and named exports in UMD build,
  
  function _typeof(obj) {
    if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
      _typeof = function (obj) {
        return typeof obj;
      };
    } else {
      _typeof = function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
      };
    }
  
    return _typeof(obj);
  }
  
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
  
  function commonjsRequire() {
    throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
  }
  
  function createCommonjsModule$1(fn, module) {
    return module = {
      exports: {}
    }, fn(module, module.exports), module.exports;
  }
  
  var moment = createCommonjsModule$1(function (module, exports) {
    (function (global, factory) {
      module.exports = factory();
    })(commonjsGlobal, function () {
      var hookCallback;
  
      function hooks() {
        return hookCallback.apply(null, arguments);
      } // This is done to register the method called with moment()
      // without creating circular dependencies.
  
  
      function setHookCallback(callback) {
        hookCallback = callback;
      }
  
      function isArray(input) {
        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
      }
  
      function isObject(input) {
        // IE8 will treat undefined and null as object if it wasn't for
        // input != null
        return input != null && Object.prototype.toString.call(input) === '[object Object]';
      }
  
      function isObjectEmpty(obj) {
        if (Object.getOwnPropertyNames) {
          return Object.getOwnPropertyNames(obj).length === 0;
        } else {
          var k;
  
          for (k in obj) {
            if (obj.hasOwnProperty(k)) {
              return false;
            }
          }
  
          return true;
        }
      }
  
      function isUndefined(input) {
        return input === void 0;
      }
  
      function isNumber(input) {
        return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
      }
  
      function isDate(input) {
        return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
      }
  
      function map(arr, fn) {
        var res = [],
            i;
  
        for (i = 0; i < arr.length; ++i) {
          res.push(fn(arr[i], i));
        }
  
        return res;
      }
  
      function hasOwnProp(a, b) {
        return Object.prototype.hasOwnProperty.call(a, b);
      }
  
      function extend(a, b) {
        for (var i in b) {
          if (hasOwnProp(b, i)) {
            a[i] = b[i];
          }
        }
  
        if (hasOwnProp(b, 'toString')) {
          a.toString = b.toString;
        }
  
        if (hasOwnProp(b, 'valueOf')) {
          a.valueOf = b.valueOf;
        }
  
        return a;
      }
  
      function createUTC(input, format, locale, strict) {
        return createLocalOrUTC(input, format, locale, strict, true).utc();
      }
  
      function defaultParsingFlags() {
        // We need to deep clone this object.
        return {
          empty: false,
          unusedTokens: [],
          unusedInput: [],
          overflow: -2,
          charsLeftOver: 0,
          nullInput: false,
          invalidMonth: null,
          invalidFormat: false,
          userInvalidated: false,
          iso: false,
          parsedDateParts: [],
          meridiem: null,
          rfc2822: false,
          weekdayMismatch: false
        };
      }
  
      function getParsingFlags(m) {
        if (m._pf == null) {
          m._pf = defaultParsingFlags();
        }
  
        return m._pf;
      }
  
      var some;
  
      if (Array.prototype.some) {
        some = Array.prototype.some;
      } else {
        some = function (fun) {
          var t = Object(this);
          var len = t.length >>> 0;
  
          for (var i = 0; i < len; i++) {
            if (i in t && fun.call(this, t[i], i, t)) {
              return true;
            }
          }
  
          return false;
        };
      }
  
      function isValid(m) {
        if (m._isValid == null) {
          var flags = getParsingFlags(m);
          var parsedParts = some.call(flags.parsedDateParts, function (i) {
            return i != null;
          });
          var isNowValid = !isNaN(m._d.getTime()) && flags.overflow < 0 && !flags.empty && !flags.invalidMonth && !flags.invalidWeekday && !flags.weekdayMismatch && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated && (!flags.meridiem || flags.meridiem && parsedParts);
  
          if (m._strict) {
            isNowValid = isNowValid && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0 && flags.bigHour === undefined;
          }
  
          if (Object.isFrozen == null || !Object.isFrozen(m)) {
            m._isValid = isNowValid;
          } else {
            return isNowValid;
          }
        }
  
        return m._isValid;
      }
  
      function createInvalid(flags) {
        var m = createUTC(NaN);
  
        if (flags != null) {
          extend(getParsingFlags(m), flags);
        } else {
          getParsingFlags(m).userInvalidated = true;
        }
  
        return m;
      } // Plugins that add properties should also add the key here (null value),
      // so we can properly clone ourselves.
  
  
      var momentProperties = hooks.momentProperties = [];
  
      function copyConfig(to, from) {
        var i, prop, val;
  
        if (!isUndefined(from._isAMomentObject)) {
          to._isAMomentObject = from._isAMomentObject;
        }
  
        if (!isUndefined(from._i)) {
          to._i = from._i;
        }
  
        if (!isUndefined(from._f)) {
          to._f = from._f;
        }
  
        if (!isUndefined(from._l)) {
          to._l = from._l;
        }
  
        if (!isUndefined(from._strict)) {
          to._strict = from._strict;
        }
  
        if (!isUndefined(from._tzm)) {
          to._tzm = from._tzm;
        }
  
        if (!isUndefined(from._isUTC)) {
          to._isUTC = from._isUTC;
        }
  
        if (!isUndefined(from._offset)) {
          to._offset = from._offset;
        }
  
        if (!isUndefined(from._pf)) {
          to._pf = getParsingFlags(from);
        }
  
        if (!isUndefined(from._locale)) {
          to._locale = from._locale;
        }
  
        if (momentProperties.length > 0) {
          for (i = 0; i < momentProperties.length; i++) {
            prop = momentProperties[i];
            val = from[prop];
  
            if (!isUndefined(val)) {
              to[prop] = val;
            }
          }
        }
  
        return to;
      }
  
      var updateInProgress = false; // Moment prototype object
  
      function Moment(config) {
        copyConfig(this, config);
        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
  
        if (!this.isValid()) {
          this._d = new Date(NaN);
        } // Prevent infinite loop in case updateOffset creates new moment
        // objects.
  
  
        if (updateInProgress === false) {
          updateInProgress = true;
          hooks.updateOffset(this);
          updateInProgress = false;
        }
      }
  
      function isMoment(obj) {
        return obj instanceof Moment || obj != null && obj._isAMomentObject != null;
      }
  
      function absFloor(number) {
        if (number < 0) {
          // -0 -> 0
          return Math.ceil(number) || 0;
        } else {
          return Math.floor(number);
        }
      }
  
      function toInt(argumentForCoercion) {
        var coercedNumber = +argumentForCoercion,
            value = 0;
  
        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
          value = absFloor(coercedNumber);
        }
  
        return value;
      } // compare two arrays, return the number of differences
  
  
      function compareArrays(array1, array2, dontConvert) {
        var len = Math.min(array1.length, array2.length),
            lengthDiff = Math.abs(array1.length - array2.length),
            diffs = 0,
            i;
  
        for (i = 0; i < len; i++) {
          if (dontConvert && array1[i] !== array2[i] || !dontConvert && toInt(array1[i]) !== toInt(array2[i])) {
            diffs++;
          }
        }
  
        return diffs + lengthDiff;
      }
  
      function warn(msg) {
        if (hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) {
          console.warn('Deprecation warning: ' + msg);
        }
      }
  
      function deprecate(msg, fn) {
        var firstTime = true;
        return extend(function () {
          if (hooks.deprecationHandler != null) {
            hooks.deprecationHandler(null, msg);
          }
  
          if (firstTime) {
            var args = [];
            var arg;
  
            for (var i = 0; i < arguments.length; i++) {
              arg = '';
  
              if (typeof arguments[i] === 'object') {
                arg += '\n[' + i + '] ';
  
                for (var key in arguments[0]) {
                  arg += key + ': ' + arguments[0][key] + ', ';
                }
  
                arg = arg.slice(0, -2); // Remove trailing comma and space
              } else {
                arg = arguments[i];
              }
  
              args.push(arg);
            }
  
            warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + new Error().stack);
            firstTime = false;
          }
  
          return fn.apply(this, arguments);
        }, fn);
      }
  
      var deprecations = {};
  
      function deprecateSimple(name, msg) {
        if (hooks.deprecationHandler != null) {
          hooks.deprecationHandler(name, msg);
        }
  
        if (!deprecations[name]) {
          warn(msg);
          deprecations[name] = true;
        }
      }
  
      hooks.suppressDeprecationWarnings = false;
      hooks.deprecationHandler = null;
  
      function isFunction(input) {
        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
      }
  
      function set(config) {
        var prop, i;
  
        for (i in config) {
          prop = config[i];
  
          if (isFunction(prop)) {
            this[i] = prop;
          } else {
            this['_' + i] = prop;
          }
        }
  
        this._config = config; // Lenient ordinal parsing accepts just a number in addition to
        // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
        // TODO: Remove "ordinalParse" fallback in next major release.
  
        this._dayOfMonthOrdinalParseLenient = new RegExp((this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + '|' + /\d{1,2}/.source);
      }
  
      function mergeConfigs(parentConfig, childConfig) {
        var res = extend({}, parentConfig),
            prop;
  
        for (prop in childConfig) {
          if (hasOwnProp(childConfig, prop)) {
            if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
              res[prop] = {};
              extend(res[prop], parentConfig[prop]);
              extend(res[prop], childConfig[prop]);
            } else if (childConfig[prop] != null) {
              res[prop] = childConfig[prop];
            } else {
              delete res[prop];
            }
          }
        }
  
        for (prop in parentConfig) {
          if (hasOwnProp(parentConfig, prop) && !hasOwnProp(childConfig, prop) && isObject(parentConfig[prop])) {
            // make sure changes to properties don't modify parent config
            res[prop] = extend({}, res[prop]);
          }
        }
  
        return res;
      }
  
      function Locale(config) {
        if (config != null) {
          this.set(config);
        }
      }
  
      var keys;
  
      if (Object.keys) {
        keys = Object.keys;
      } else {
        keys = function (obj) {
          var i,
              res = [];
  
          for (i in obj) {
            if (hasOwnProp(obj, i)) {
              res.push(i);
            }
          }
  
          return res;
        };
      }
  
      var defaultCalendar = {
        sameDay: '[Today at] LT',
        nextDay: '[Tomorrow at] LT',
        nextWeek: 'dddd [at] LT',
        lastDay: '[Yesterday at] LT',
        lastWeek: '[Last] dddd [at] LT',
        sameElse: 'L'
      };
  
      function calendar(key, mom, now) {
        var output = this._calendar[key] || this._calendar['sameElse'];
        return isFunction(output) ? output.call(mom, now) : output;
      }
  
      var defaultLongDateFormat = {
        LTS: 'h:mm:ss A',
        LT: 'h:mm A',
        L: 'MM/DD/YYYY',
        LL: 'MMMM D, YYYY',
        LLL: 'MMMM D, YYYY h:mm A',
        LLLL: 'dddd, MMMM D, YYYY h:mm A'
      };
  
      function longDateFormat(key) {
        var format = this._longDateFormat[key],
            formatUpper = this._longDateFormat[key.toUpperCase()];
  
        if (format || !formatUpper) {
          return format;
        }
  
        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
          return val.slice(1);
        });
        return this._longDateFormat[key];
      }
  
      var defaultInvalidDate = 'Invalid date';
  
      function invalidDate() {
        return this._invalidDate;
      }
  
      var defaultOrdinal = '%d';
      var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
  
      function ordinal(number) {
        return this._ordinal.replace('%d', number);
      }
  
      var defaultRelativeTime = {
        future: 'in %s',
        past: '%s ago',
        s: 'a few seconds',
        ss: '%d seconds',
        m: 'a minute',
        mm: '%d minutes',
        h: 'an hour',
        hh: '%d hours',
        d: 'a day',
        dd: '%d days',
        M: 'a month',
        MM: '%d months',
        y: 'a year',
        yy: '%d years'
      };
  
      function relativeTime(number, withoutSuffix, string, isFuture) {
        var output = this._relativeTime[string];
        return isFunction(output) ? output(number, withoutSuffix, string, isFuture) : output.replace(/%d/i, number);
      }
  
      function pastFuture(diff, output) {
        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
      }
  
      var aliases = {};
  
      function addUnitAlias(unit, shorthand) {
        var lowerCase = unit.toLowerCase();
        aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
      }
  
      function normalizeUnits(units) {
        return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
      }
  
      function normalizeObjectUnits(inputObject) {
        var normalizedInput = {},
            normalizedProp,
            prop;
  
        for (prop in inputObject) {
          if (hasOwnProp(inputObject, prop)) {
            normalizedProp = normalizeUnits(prop);
  
            if (normalizedProp) {
              normalizedInput[normalizedProp] = inputObject[prop];
            }
          }
        }
  
        return normalizedInput;
      }
  
      var priorities = {};
  
      function addUnitPriority(unit, priority) {
        priorities[unit] = priority;
      }
  
      function getPrioritizedUnits(unitsObj) {
        var units = [];
  
        for (var u in unitsObj) {
          units.push({
            unit: u,
            priority: priorities[u]
          });
        }
  
        units.sort(function (a, b) {
          return a.priority - b.priority;
        });
        return units;
      }
  
      function zeroFill(number, targetLength, forceSign) {
        var absNumber = '' + Math.abs(number),
            zerosToFill = targetLength - absNumber.length,
            sign = number >= 0;
        return (sign ? forceSign ? '+' : '' : '-') + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
      }
  
      var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
      var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
      var formatFunctions = {};
      var formatTokenFunctions = {}; // token:    'M'
      // padded:   ['MM', 2]
      // ordinal:  'Mo'
      // callback: function () { this.month() + 1 }
  
      function addFormatToken(token, padded, ordinal, callback) {
        var func = callback;
  
        if (typeof callback === 'string') {
          func = function () {
            return this[callback]();
          };
        }
  
        if (token) {
          formatTokenFunctions[token] = func;
        }
  
        if (padded) {
          formatTokenFunctions[padded[0]] = function () {
            return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
          };
        }
  
        if (ordinal) {
          formatTokenFunctions[ordinal] = function () {
            return this.localeData().ordinal(func.apply(this, arguments), token);
          };
        }
      }
  
      function removeFormattingTokens(input) {
        if (input.match(/\[[\s\S]/)) {
          return input.replace(/^\[|\]$/g, '');
        }
  
        return input.replace(/\\/g, '');
      }
  
      function makeFormatFunction(format) {
        var array = format.match(formattingTokens),
            i,
            length;
  
        for (i = 0, length = array.length; i < length; i++) {
          if (formatTokenFunctions[array[i]]) {
            array[i] = formatTokenFunctions[array[i]];
          } else {
            array[i] = removeFormattingTokens(array[i]);
          }
        }
  
        return function (mom) {
          var output = '',
              i;
  
          for (i = 0; i < length; i++) {
            output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
          }
  
          return output;
        };
      } // format date using native date object
  
  
      function formatMoment(m, format) {
        if (!m.isValid()) {
          return m.localeData().invalidDate();
        }
  
        format = expandFormat(format, m.localeData());
        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
        return formatFunctions[format](m);
      }
  
      function expandFormat(format, locale) {
        var i = 5;
  
        function replaceLongDateFormatTokens(input) {
          return locale.longDateFormat(input) || input;
        }
  
        localFormattingTokens.lastIndex = 0;
  
        while (i >= 0 && localFormattingTokens.test(format)) {
          format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
          localFormattingTokens.lastIndex = 0;
          i -= 1;
        }
  
        return format;
      }
  
      var match1 = /\d/; //       0 - 9
  
      var match2 = /\d\d/; //      00 - 99
  
      var match3 = /\d{3}/; //     000 - 999
  
      var match4 = /\d{4}/; //    0000 - 9999
  
      var match6 = /[+-]?\d{6}/; // -999999 - 999999
  
      var match1to2 = /\d\d?/; //       0 - 99
  
      var match3to4 = /\d\d\d\d?/; //     999 - 9999
  
      var match5to6 = /\d\d\d\d\d\d?/; //   99999 - 999999
  
      var match1to3 = /\d{1,3}/; //       0 - 999
  
      var match1to4 = /\d{1,4}/; //       0 - 9999
  
      var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
  
      var matchUnsigned = /\d+/; //       0 - inf
  
      var matchSigned = /[+-]?\d+/; //    -inf - inf
  
      var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
  
      var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
  
      var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
      // any word (or two) characters or numbers including two/three word month in arabic.
      // includes scottish gaelic two word and hyphenated months
  
      var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
      var regexes = {};
  
      function addRegexToken(token, regex, strictRegex) {
        regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
          return isStrict && strictRegex ? strictRegex : regex;
        };
      }
  
      function getParseRegexForToken(token, config) {
        if (!hasOwnProp(regexes, token)) {
          return new RegExp(unescapeFormat(token));
        }
  
        return regexes[token](config._strict, config._locale);
      } // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
  
  
      function unescapeFormat(s) {
        return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
          return p1 || p2 || p3 || p4;
        }));
      }
  
      function regexEscape(s) {
        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
      }
  
      var tokens = {};
  
      function addParseToken(token, callback) {
        var i,
            func = callback;
  
        if (typeof token === 'string') {
          token = [token];
        }
  
        if (isNumber(callback)) {
          func = function (input, array) {
            array[callback] = toInt(input);
          };
        }
  
        for (i = 0; i < token.length; i++) {
          tokens[token[i]] = func;
        }
      }
  
      function addWeekParseToken(token, callback) {
        addParseToken(token, function (input, array, config, token) {
          config._w = config._w || {};
          callback(input, config._w, config, token);
        });
      }
  
      function addTimeToArrayFromToken(token, input, config) {
        if (input != null && hasOwnProp(tokens, token)) {
          tokens[token](input, config._a, config, token);
        }
      }
  
      var YEAR = 0;
      var MONTH = 1;
      var DATE = 2;
      var HOUR = 3;
      var MINUTE = 4;
      var SECOND = 5;
      var MILLISECOND = 6;
      var WEEK = 7;
      var WEEKDAY = 8; // FORMATTING
  
      addFormatToken('Y', 0, 0, function () {
        var y = this.year();
        return y <= 9999 ? '' + y : '+' + y;
      });
      addFormatToken(0, ['YY', 2], 0, function () {
        return this.year() % 100;
      });
      addFormatToken(0, ['YYYY', 4], 0, 'year');
      addFormatToken(0, ['YYYYY', 5], 0, 'year');
      addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); // ALIASES
  
      addUnitAlias('year', 'y'); // PRIORITIES
  
      addUnitPriority('year', 1); // PARSING
  
      addRegexToken('Y', matchSigned);
      addRegexToken('YY', match1to2, match2);
      addRegexToken('YYYY', match1to4, match4);
      addRegexToken('YYYYY', match1to6, match6);
      addRegexToken('YYYYYY', match1to6, match6);
      addParseToken(['YYYYY', 'YYYYYY'], YEAR);
      addParseToken('YYYY', function (input, array) {
        array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
      });
      addParseToken('YY', function (input, array) {
        array[YEAR] = hooks.parseTwoDigitYear(input);
      });
      addParseToken('Y', function (input, array) {
        array[YEAR] = parseInt(input, 10);
      }); // HELPERS
  
      function daysInYear(year) {
        return isLeapYear(year) ? 366 : 365;
      }
  
      function isLeapYear(year) {
        return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
      } // HOOKS
  
  
      hooks.parseTwoDigitYear = function (input) {
        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
      }; // MOMENTS
  
  
      var getSetYear = makeGetSet('FullYear', true);
  
      function getIsLeapYear() {
        return isLeapYear(this.year());
      }
  
      function makeGetSet(unit, keepTime) {
        return function (value) {
          if (value != null) {
            set$1(this, unit, value);
            hooks.updateOffset(this, keepTime);
            return this;
          } else {
            return get(this, unit);
          }
        };
      }
  
      function get(mom, unit) {
        return mom.isValid() ? mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
      }
  
      function set$1(mom, unit, value) {
        if (mom.isValid() && !isNaN(value)) {
          if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
          } else {
            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
          }
        }
      } // MOMENTS
  
  
      function stringGet(units) {
        units = normalizeUnits(units);
  
        if (isFunction(this[units])) {
          return this[units]();
        }
  
        return this;
      }
  
      function stringSet(units, value) {
        if (typeof units === 'object') {
          units = normalizeObjectUnits(units);
          var prioritized = getPrioritizedUnits(units);
  
          for (var i = 0; i < prioritized.length; i++) {
            this[prioritized[i].unit](units[prioritized[i].unit]);
          }
        } else {
          units = normalizeUnits(units);
  
          if (isFunction(this[units])) {
            return this[units](value);
          }
        }
  
        return this;
      }
  
      function mod(n, x) {
        return (n % x + x) % x;
      }
  
      var indexOf;
  
      if (Array.prototype.indexOf) {
        indexOf = Array.prototype.indexOf;
      } else {
        indexOf = function (o) {
          // I know
          var i;
  
          for (i = 0; i < this.length; ++i) {
            if (this[i] === o) {
              return i;
            }
          }
  
          return -1;
        };
      }
  
      function daysInMonth(year, month) {
        if (isNaN(year) || isNaN(month)) {
          return NaN;
        }
  
        var modMonth = mod(month, 12);
        year += (month - modMonth) / 12;
        return modMonth === 1 ? isLeapYear(year) ? 29 : 28 : 31 - modMonth % 7 % 2;
      } // FORMATTING
  
  
      addFormatToken('M', ['MM', 2], 'Mo', function () {
        return this.month() + 1;
      });
      addFormatToken('MMM', 0, 0, function (format) {
        return this.localeData().monthsShort(this, format);
      });
      addFormatToken('MMMM', 0, 0, function (format) {
        return this.localeData().months(this, format);
      }); // ALIASES
  
      addUnitAlias('month', 'M'); // PRIORITY
  
      addUnitPriority('month', 8); // PARSING
  
      addRegexToken('M', match1to2);
      addRegexToken('MM', match1to2, match2);
      addRegexToken('MMM', function (isStrict, locale) {
        return locale.monthsShortRegex(isStrict);
      });
      addRegexToken('MMMM', function (isStrict, locale) {
        return locale.monthsRegex(isStrict);
      });
      addParseToken(['M', 'MM'], function (input, array) {
        array[MONTH] = toInt(input) - 1;
      });
      addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
        var month = config._locale.monthsParse(input, token, config._strict); // if we didn't find a month name, mark the date as invalid.
  
  
        if (month != null) {
          array[MONTH] = month;
        } else {
          getParsingFlags(config).invalidMonth = input;
        }
      }); // LOCALES
  
      var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
      var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
  
      function localeMonths(m, format) {
        if (!m) {
          return isArray(this._months) ? this._months : this._months['standalone'];
        }
  
        return isArray(this._months) ? this._months[m.month()] : this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
      }
  
      var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
  
      function localeMonthsShort(m, format) {
        if (!m) {
          return isArray(this._monthsShort) ? this._monthsShort : this._monthsShort['standalone'];
        }
  
        return isArray(this._monthsShort) ? this._monthsShort[m.month()] : this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
      }
  
      function handleStrictParse(monthName, format, strict) {
        var i,
            ii,
            mom,
            llc = monthName.toLocaleLowerCase();
  
        if (!this._monthsParse) {
          // this is not used
          this._monthsParse = [];
          this._longMonthsParse = [];
          this._shortMonthsParse = [];
  
          for (i = 0; i < 12; ++i) {
            mom = createUTC([2000, i]);
            this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
            this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
          }
        }
  
        if (strict) {
          if (format === 'MMM') {
            ii = indexOf.call(this._shortMonthsParse, llc);
            return ii !== -1 ? ii : null;
          } else {
            ii = indexOf.call(this._longMonthsParse, llc);
            return ii !== -1 ? ii : null;
          }
        } else {
          if (format === 'MMM') {
            ii = indexOf.call(this._shortMonthsParse, llc);
  
            if (ii !== -1) {
              return ii;
            }
  
            ii = indexOf.call(this._longMonthsParse, llc);
            return ii !== -1 ? ii : null;
          } else {
            ii = indexOf.call(this._longMonthsParse, llc);
  
            if (ii !== -1) {
              return ii;
            }
  
            ii = indexOf.call(this._shortMonthsParse, llc);
            return ii !== -1 ? ii : null;
          }
        }
      }
  
      function localeMonthsParse(monthName, format, strict) {
        var i, mom, regex;
  
        if (this._monthsParseExact) {
          return handleStrictParse.call(this, monthName, format, strict);
        }
  
        if (!this._monthsParse) {
          this._monthsParse = [];
          this._longMonthsParse = [];
          this._shortMonthsParse = [];
        } // TODO: add sorting
        // Sorting makes sure if one month (or abbr) is a prefix of another
        // see sorting in computeMonthsParse
  
  
        for (i = 0; i < 12; i++) {
          // make the regex if we don't have it already
          mom = createUTC([2000, i]);
  
          if (strict && !this._longMonthsParse[i]) {
            this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
            this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
          }
  
          if (!strict && !this._monthsParse[i]) {
            regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
            this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
          } // test the regex
  
  
          if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
            return i;
          } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
            return i;
          } else if (!strict && this._monthsParse[i].test(monthName)) {
            return i;
          }
        }
      } // MOMENTS
  
  
      function setMonth(mom, value) {
        var dayOfMonth;
  
        if (!mom.isValid()) {
          // No op
          return mom;
        }
  
        if (typeof value === 'string') {
          if (/^\d+$/.test(value)) {
            value = toInt(value);
          } else {
            value = mom.localeData().monthsParse(value); // TODO: Another silent failure?
  
            if (!isNumber(value)) {
              return mom;
            }
          }
        }
  
        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
  
        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
  
        return mom;
      }
  
      function getSetMonth(value) {
        if (value != null) {
          setMonth(this, value);
          hooks.updateOffset(this, true);
          return this;
        } else {
          return get(this, 'Month');
        }
      }
  
      function getDaysInMonth() {
        return daysInMonth(this.year(), this.month());
      }
  
      var defaultMonthsShortRegex = matchWord;
  
      function monthsShortRegex(isStrict) {
        if (this._monthsParseExact) {
          if (!hasOwnProp(this, '_monthsRegex')) {
            computeMonthsParse.call(this);
          }
  
          if (isStrict) {
            return this._monthsShortStrictRegex;
          } else {
            return this._monthsShortRegex;
          }
        } else {
          if (!hasOwnProp(this, '_monthsShortRegex')) {
            this._monthsShortRegex = defaultMonthsShortRegex;
          }
  
          return this._monthsShortStrictRegex && isStrict ? this._monthsShortStrictRegex : this._monthsShortRegex;
        }
      }
  
      var defaultMonthsRegex = matchWord;
  
      function monthsRegex(isStrict) {
        if (this._monthsParseExact) {
          if (!hasOwnProp(this, '_monthsRegex')) {
            computeMonthsParse.call(this);
          }
  
          if (isStrict) {
            return this._monthsStrictRegex;
          } else {
            return this._monthsRegex;
          }
        } else {
          if (!hasOwnProp(this, '_monthsRegex')) {
            this._monthsRegex = defaultMonthsRegex;
          }
  
          return this._monthsStrictRegex && isStrict ? this._monthsStrictRegex : this._monthsRegex;
        }
      }
  
      function computeMonthsParse() {
        function cmpLenRev(a, b) {
          return b.length - a.length;
        }
  
        var shortPieces = [],
            longPieces = [],
            mixedPieces = [],
            i,
            mom;
  
        for (i = 0; i < 12; i++) {
          // make the regex if we don't have it already
          mom = createUTC([2000, i]);
          shortPieces.push(this.monthsShort(mom, ''));
          longPieces.push(this.months(mom, ''));
          mixedPieces.push(this.months(mom, ''));
          mixedPieces.push(this.monthsShort(mom, ''));
        } // Sorting makes sure if one month (or abbr) is a prefix of another it
        // will match the longer piece.
  
  
        shortPieces.sort(cmpLenRev);
        longPieces.sort(cmpLenRev);
        mixedPieces.sort(cmpLenRev);
  
        for (i = 0; i < 12; i++) {
          shortPieces[i] = regexEscape(shortPieces[i]);
          longPieces[i] = regexEscape(longPieces[i]);
        }
  
        for (i = 0; i < 24; i++) {
          mixedPieces[i] = regexEscape(mixedPieces[i]);
        }
  
        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
        this._monthsShortRegex = this._monthsRegex;
        this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
        this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
      }
  
      function createDate(y, m, d, h, M, s, ms) {
        // can't just apply() to create a date:
        // https://stackoverflow.com/q/181348
        var date; // the date constructor remaps years 0-99 to 1900-1999
  
        if (y < 100 && y >= 0) {
          // preserve leap years using a full 400 year cycle, then reset
          date = new Date(y + 400, m, d, h, M, s, ms);
  
          if (isFinite(date.getFullYear())) {
            date.setFullYear(y);
          }
        } else {
          date = new Date(y, m, d, h, M, s, ms);
        }
  
        return date;
      }
  
      function createUTCDate(y) {
        var date; // the Date.UTC function remaps years 0-99 to 1900-1999
  
        if (y < 100 && y >= 0) {
          var args = Array.prototype.slice.call(arguments); // preserve leap years using a full 400 year cycle, then reset
  
          args[0] = y + 400;
          date = new Date(Date.UTC.apply(null, args));
  
          if (isFinite(date.getUTCFullYear())) {
            date.setUTCFullYear(y);
          }
        } else {
          date = new Date(Date.UTC.apply(null, arguments));
        }
  
        return date;
      } // start-of-first-week - start-of-year
  
  
      function firstWeekOffset(year, dow, doy) {
        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
        fwd = 7 + dow - doy,
            // first-week day local weekday -- which local weekday is fwd
        fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
        return -fwdlw + fwd - 1;
      } // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
  
  
      function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
        var localWeekday = (7 + weekday - dow) % 7,
            weekOffset = firstWeekOffset(year, dow, doy),
            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
            resYear,
            resDayOfYear;
  
        if (dayOfYear <= 0) {
          resYear = year - 1;
          resDayOfYear = daysInYear(resYear) + dayOfYear;
        } else if (dayOfYear > daysInYear(year)) {
          resYear = year + 1;
          resDayOfYear = dayOfYear - daysInYear(year);
        } else {
          resYear = year;
          resDayOfYear = dayOfYear;
        }
  
        return {
          year: resYear,
          dayOfYear: resDayOfYear
        };
      }
  
      function weekOfYear(mom, dow, doy) {
        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
            resWeek,
            resYear;
  
        if (week < 1) {
          resYear = mom.year() - 1;
          resWeek = week + weeksInYear(resYear, dow, doy);
        } else if (week > weeksInYear(mom.year(), dow, doy)) {
          resWeek = week - weeksInYear(mom.year(), dow, doy);
          resYear = mom.year() + 1;
        } else {
          resYear = mom.year();
          resWeek = week;
        }
  
        return {
          week: resWeek,
          year: resYear
        };
      }
  
      function weeksInYear(year, dow, doy) {
        var weekOffset = firstWeekOffset(year, dow, doy),
            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
      } // FORMATTING
  
  
      addFormatToken('w', ['ww', 2], 'wo', 'week');
      addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); // ALIASES
  
      addUnitAlias('week', 'w');
      addUnitAlias('isoWeek', 'W'); // PRIORITIES
  
      addUnitPriority('week', 5);
      addUnitPriority('isoWeek', 5); // PARSING
  
      addRegexToken('w', match1to2);
      addRegexToken('ww', match1to2, match2);
      addRegexToken('W', match1to2);
      addRegexToken('WW', match1to2, match2);
      addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
        week[token.substr(0, 1)] = toInt(input);
      }); // HELPERS
      // LOCALES
  
      function localeWeek(mom) {
        return weekOfYear(mom, this._week.dow, this._week.doy).week;
      }
  
      var defaultLocaleWeek = {
        dow: 0,
        // Sunday is the first day of the week.
        doy: 6 // The week that contains Jan 6th is the first week of the year.
  
      };
  
      function localeFirstDayOfWeek() {
        return this._week.dow;
      }
  
      function localeFirstDayOfYear() {
        return this._week.doy;
      } // MOMENTS
  
  
      function getSetWeek(input) {
        var week = this.localeData().week(this);
        return input == null ? week : this.add((input - week) * 7, 'd');
      }
  
      function getSetISOWeek(input) {
        var week = weekOfYear(this, 1, 4).week;
        return input == null ? week : this.add((input - week) * 7, 'd');
      } // FORMATTING
  
  
      addFormatToken('d', 0, 'do', 'day');
      addFormatToken('dd', 0, 0, function (format) {
        return this.localeData().weekdaysMin(this, format);
      });
      addFormatToken('ddd', 0, 0, function (format) {
        return this.localeData().weekdaysShort(this, format);
      });
      addFormatToken('dddd', 0, 0, function (format) {
        return this.localeData().weekdays(this, format);
      });
      addFormatToken('e', 0, 0, 'weekday');
      addFormatToken('E', 0, 0, 'isoWeekday'); // ALIASES
  
      addUnitAlias('day', 'd');
      addUnitAlias('weekday', 'e');
      addUnitAlias('isoWeekday', 'E'); // PRIORITY
  
      addUnitPriority('day', 11);
      addUnitPriority('weekday', 11);
      addUnitPriority('isoWeekday', 11); // PARSING
  
      addRegexToken('d', match1to2);
      addRegexToken('e', match1to2);
      addRegexToken('E', match1to2);
      addRegexToken('dd', function (isStrict, locale) {
        return locale.weekdaysMinRegex(isStrict);
      });
      addRegexToken('ddd', function (isStrict, locale) {
        return locale.weekdaysShortRegex(isStrict);
      });
      addRegexToken('dddd', function (isStrict, locale) {
        return locale.weekdaysRegex(isStrict);
      });
      addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
        var weekday = config._locale.weekdaysParse(input, token, config._strict); // if we didn't get a weekday name, mark the date as invalid
  
  
        if (weekday != null) {
          week.d = weekday;
        } else {
          getParsingFlags(config).invalidWeekday = input;
        }
      });
      addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
        week[token] = toInt(input);
      }); // HELPERS
  
      function parseWeekday(input, locale) {
        if (typeof input !== 'string') {
          return input;
        }
  
        if (!isNaN(input)) {
          return parseInt(input, 10);
        }
  
        input = locale.weekdaysParse(input);
  
        if (typeof input === 'number') {
          return input;
        }
  
        return null;
      }
  
      function parseIsoWeekday(input, locale) {
        if (typeof input === 'string') {
          return locale.weekdaysParse(input) % 7 || 7;
        }
  
        return isNaN(input) ? null : input;
      } // LOCALES
  
  
      function shiftWeekdays(ws, n) {
        return ws.slice(n, 7).concat(ws.slice(0, n));
      }
  
      var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
  
      function localeWeekdays(m, format) {
        var weekdays = isArray(this._weekdays) ? this._weekdays : this._weekdays[m && m !== true && this._weekdays.isFormat.test(format) ? 'format' : 'standalone'];
        return m === true ? shiftWeekdays(weekdays, this._week.dow) : m ? weekdays[m.day()] : weekdays;
      }
  
      var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
  
      function localeWeekdaysShort(m) {
        return m === true ? shiftWeekdays(this._weekdaysShort, this._week.dow) : m ? this._weekdaysShort[m.day()] : this._weekdaysShort;
      }
  
      var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
  
      function localeWeekdaysMin(m) {
        return m === true ? shiftWeekdays(this._weekdaysMin, this._week.dow) : m ? this._weekdaysMin[m.day()] : this._weekdaysMin;
      }
  
      function handleStrictParse$1(weekdayName, format, strict) {
        var i,
            ii,
            mom,
            llc = weekdayName.toLocaleLowerCase();
  
        if (!this._weekdaysParse) {
          this._weekdaysParse = [];
          this._shortWeekdaysParse = [];
          this._minWeekdaysParse = [];
  
          for (i = 0; i < 7; ++i) {
            mom = createUTC([2000, 1]).day(i);
            this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
            this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
            this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
          }
        }
  
        if (strict) {
          if (format === 'dddd') {
            ii = indexOf.call(this._weekdaysParse, llc);
            return ii !== -1 ? ii : null;
          } else if (format === 'ddd') {
            ii = indexOf.call(this._shortWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
          } else {
            ii = indexOf.call(this._minWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
          }
        } else {
          if (format === 'dddd') {
            ii = indexOf.call(this._weekdaysParse, llc);
  
            if (ii !== -1) {
              return ii;
            }
  
            ii = indexOf.call(this._shortWeekdaysParse, llc);
  
            if (ii !== -1) {
              return ii;
            }
  
            ii = indexOf.call(this._minWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
          } else if (format === 'ddd') {
            ii = indexOf.call(this._shortWeekdaysParse, llc);
  
            if (ii !== -1) {
              return ii;
            }
  
            ii = indexOf.call(this._weekdaysParse, llc);
  
            if (ii !== -1) {
              return ii;
            }
  
            ii = indexOf.call(this._minWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
          } else {
            ii = indexOf.call(this._minWeekdaysParse, llc);
  
            if (ii !== -1) {
              return ii;
            }
  
            ii = indexOf.call(this._weekdaysParse, llc);
  
            if (ii !== -1) {
              return ii;
            }
  
            ii = indexOf.call(this._shortWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
          }
        }
      }
  
      function localeWeekdaysParse(weekdayName, format, strict) {
        var i, mom, regex;
  
        if (this._weekdaysParseExact) {
          return handleStrictParse$1.call(this, weekdayName, format, strict);
        }
  
        if (!this._weekdaysParse) {
          this._weekdaysParse = [];
          this._minWeekdaysParse = [];
          this._shortWeekdaysParse = [];
          this._fullWeekdaysParse = [];
        }
  
        for (i = 0; i < 7; i++) {
          // make the regex if we don't have it already
          mom = createUTC([2000, 1]).day(i);
  
          if (strict && !this._fullWeekdaysParse[i]) {
            this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');
            this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');
            this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');
          }
  
          if (!this._weekdaysParse[i]) {
            regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
            this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
          } // test the regex
  
  
          if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
            return i;
          } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
            return i;
          } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
            return i;
          } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
            return i;
          }
        }
      } // MOMENTS
  
  
      function getSetDayOfWeek(input) {
        if (!this.isValid()) {
          return input != null ? this : NaN;
        }
  
        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
  
        if (input != null) {
          input = parseWeekday(input, this.localeData());
          return this.add(input - day, 'd');
        } else {
          return day;
        }
      }
  
      function getSetLocaleDayOfWeek(input) {
        if (!this.isValid()) {
          return input != null ? this : NaN;
        }
  
        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
        return input == null ? weekday : this.add(input - weekday, 'd');
      }
  
      function getSetISODayOfWeek(input) {
        if (!this.isValid()) {
          return input != null ? this : NaN;
        } // behaves the same as moment#day except
        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
        // as a setter, sunday should belong to the previous week.
  
  
        if (input != null) {
          var weekday = parseIsoWeekday(input, this.localeData());
          return this.day(this.day() % 7 ? weekday : weekday - 7);
        } else {
          return this.day() || 7;
        }
      }
  
      var defaultWeekdaysRegex = matchWord;
  
      function weekdaysRegex(isStrict) {
        if (this._weekdaysParseExact) {
          if (!hasOwnProp(this, '_weekdaysRegex')) {
            computeWeekdaysParse.call(this);
          }
  
          if (isStrict) {
            return this._weekdaysStrictRegex;
          } else {
            return this._weekdaysRegex;
          }
        } else {
          if (!hasOwnProp(this, '_weekdaysRegex')) {
            this._weekdaysRegex = defaultWeekdaysRegex;
          }
  
          return this._weekdaysStrictRegex && isStrict ? this._weekdaysStrictRegex : this._weekdaysRegex;
        }
      }
  
      var defaultWeekdaysShortRegex = matchWord;
  
      function weekdaysShortRegex(isStrict) {
        if (this._weekdaysParseExact) {
          if (!hasOwnProp(this, '_weekdaysRegex')) {
            computeWeekdaysParse.call(this);
          }
  
          if (isStrict) {
            return this._weekdaysShortStrictRegex;
          } else {
            return this._weekdaysShortRegex;
          }
        } else {
          if (!hasOwnProp(this, '_weekdaysShortRegex')) {
            this._weekdaysShortRegex = defaultWeekdaysShortRegex;
          }
  
          return this._weekdaysShortStrictRegex && isStrict ? this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
        }
      }
  
      var defaultWeekdaysMinRegex = matchWord;
  
      function weekdaysMinRegex(isStrict) {
        if (this._weekdaysParseExact) {
          if (!hasOwnProp(this, '_weekdaysRegex')) {
            computeWeekdaysParse.call(this);
          }
  
          if (isStrict) {
            return this._weekdaysMinStrictRegex;
          } else {
            return this._weekdaysMinRegex;
          }
        } else {
          if (!hasOwnProp(this, '_weekdaysMinRegex')) {
            this._weekdaysMinRegex = defaultWeekdaysMinRegex;
          }
  
          return this._weekdaysMinStrictRegex && isStrict ? this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
        }
      }
  
      function computeWeekdaysParse() {
        function cmpLenRev(a, b) {
          return b.length - a.length;
        }
  
        var minPieces = [],
            shortPieces = [],
            longPieces = [],
            mixedPieces = [],
            i,
            mom,
            minp,
            shortp,
            longp;
  
        for (i = 0; i < 7; i++) {
          // make the regex if we don't have it already
          mom = createUTC([2000, 1]).day(i);
          minp = this.weekdaysMin(mom, '');
          shortp = this.weekdaysShort(mom, '');
          longp = this.weekdays(mom, '');
          minPieces.push(minp);
          shortPieces.push(shortp);
          longPieces.push(longp);
          mixedPieces.push(minp);
          mixedPieces.push(shortp);
          mixedPieces.push(longp);
        } // Sorting makes sure if one weekday (or abbr) is a prefix of another it
        // will match the longer piece.
  
  
        minPieces.sort(cmpLenRev);
        shortPieces.sort(cmpLenRev);
        longPieces.sort(cmpLenRev);
        mixedPieces.sort(cmpLenRev);
  
        for (i = 0; i < 7; i++) {
          shortPieces[i] = regexEscape(shortPieces[i]);
          longPieces[i] = regexEscape(longPieces[i]);
          mixedPieces[i] = regexEscape(mixedPieces[i]);
        }
  
        this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
        this._weekdaysShortRegex = this._weekdaysRegex;
        this._weekdaysMinRegex = this._weekdaysRegex;
        this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
        this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
        this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
      } // FORMATTING
  
  
      function hFormat() {
        return this.hours() % 12 || 12;
      }
  
      function kFormat() {
        return this.hours() || 24;
      }
  
      addFormatToken('H', ['HH', 2], 0, 'hour');
      addFormatToken('h', ['hh', 2], 0, hFormat);
      addFormatToken('k', ['kk', 2], 0, kFormat);
      addFormatToken('hmm', 0, 0, function () {
        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
      });
      addFormatToken('hmmss', 0, 0, function () {
        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
      });
      addFormatToken('Hmm', 0, 0, function () {
        return '' + this.hours() + zeroFill(this.minutes(), 2);
      });
      addFormatToken('Hmmss', 0, 0, function () {
        return '' + this.hours() + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
      });
  
      function meridiem(token, lowercase) {
        addFormatToken(token, 0, 0, function () {
          return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
        });
      }
  
      meridiem('a', true);
      meridiem('A', false); // ALIASES
  
      addUnitAlias('hour', 'h'); // PRIORITY
  
      addUnitPriority('hour', 13); // PARSING
  
      function matchMeridiem(isStrict, locale) {
        return locale._meridiemParse;
      }
  
      addRegexToken('a', matchMeridiem);
      addRegexToken('A', matchMeridiem);
      addRegexToken('H', match1to2);
      addRegexToken('h', match1to2);
      addRegexToken('k', match1to2);
      addRegexToken('HH', match1to2, match2);
      addRegexToken('hh', match1to2, match2);
      addRegexToken('kk', match1to2, match2);
      addRegexToken('hmm', match3to4);
      addRegexToken('hmmss', match5to6);
      addRegexToken('Hmm', match3to4);
      addRegexToken('Hmmss', match5to6);
      addParseToken(['H', 'HH'], HOUR);
      addParseToken(['k', 'kk'], function (input, array, config) {
        var kInput = toInt(input);
        array[HOUR] = kInput === 24 ? 0 : kInput;
      });
      addParseToken(['a', 'A'], function (input, array, config) {
        config._isPm = config._locale.isPM(input);
        config._meridiem = input;
      });
      addParseToken(['h', 'hh'], function (input, array, config) {
        array[HOUR] = toInt(input);
        getParsingFlags(config).bigHour = true;
      });
      addParseToken('hmm', function (input, array, config) {
        var pos = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos));
        array[MINUTE] = toInt(input.substr(pos));
        getParsingFlags(config).bigHour = true;
      });
      addParseToken('hmmss', function (input, array, config) {
        var pos1 = input.length - 4;
        var pos2 = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos1));
        array[MINUTE] = toInt(input.substr(pos1, 2));
        array[SECOND] = toInt(input.substr(pos2));
        getParsingFlags(config).bigHour = true;
      });
      addParseToken('Hmm', function (input, array, config) {
        var pos = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos));
        array[MINUTE] = toInt(input.substr(pos));
      });
      addParseToken('Hmmss', function (input, array, config) {
        var pos1 = input.length - 4;
        var pos2 = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos1));
        array[MINUTE] = toInt(input.substr(pos1, 2));
        array[SECOND] = toInt(input.substr(pos2));
      }); // LOCALES
  
      function localeIsPM(input) {
        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
        // Using charAt should be more compatible.
        return (input + '').toLowerCase().charAt(0) === 'p';
      }
  
      var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
  
      function localeMeridiem(hours, minutes, isLower) {
        if (hours > 11) {
          return isLower ? 'pm' : 'PM';
        } else {
          return isLower ? 'am' : 'AM';
        }
      } // MOMENTS
      // Setting the hour should keep the time, because the user explicitly
      // specified which hour they want. So trying to maintain the same hour (in
      // a new timezone) makes sense. Adding/subtracting hours does not follow
      // this rule.
  
  
      var getSetHour = makeGetSet('Hours', true);
      var baseConfig = {
        calendar: defaultCalendar,
        longDateFormat: defaultLongDateFormat,
        invalidDate: defaultInvalidDate,
        ordinal: defaultOrdinal,
        dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
        relativeTime: defaultRelativeTime,
        months: defaultLocaleMonths,
        monthsShort: defaultLocaleMonthsShort,
        week: defaultLocaleWeek,
        weekdays: defaultLocaleWeekdays,
        weekdaysMin: defaultLocaleWeekdaysMin,
        weekdaysShort: defaultLocaleWeekdaysShort,
        meridiemParse: defaultLocaleMeridiemParse
      }; // internal storage for locale config files
  
      var locales = {};
      var localeFamilies = {};
      var globalLocale;
  
      function normalizeLocale(key) {
        return key ? key.toLowerCase().replace('_', '-') : key;
      } // pick the locale from the array
      // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
      // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
  
  
      function chooseLocale(names) {
        var i = 0,
            j,
            next,
            locale,
            split;
  
        while (i < names.length) {
          split = normalizeLocale(names[i]).split('-');
          j = split.length;
          next = normalizeLocale(names[i + 1]);
          next = next ? next.split('-') : null;
  
          while (j > 0) {
            locale = loadLocale(split.slice(0, j).join('-'));
  
            if (locale) {
              return locale;
            }
  
            if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
              //the next array item is better than a shallower substring of this one
              break;
            }
  
            j--;
          }
  
          i++;
        }
  
        return globalLocale;
      }
  
      function loadLocale(name) {
        var oldLocale = null; // TODO: Find a better way to register and load all the locales in Node
  
        if (!locales[name] && 'object' !== 'undefined' && module && module.exports) {
          try {
            oldLocale = globalLocale._abbr;
            var aliasedRequire = commonjsRequire;
            aliasedRequire('./locale/' + name);
            getSetGlobalLocale(oldLocale);
          } catch (e) {}
        }
  
        return locales[name];
      } // This function will load locale and then set the global locale.  If
      // no arguments are passed in, it will simply return the current global
      // locale key.
  
  
      function getSetGlobalLocale(key, values) {
        var data;
  
        if (key) {
          if (isUndefined(values)) {
            data = getLocale(key);
          } else {
            data = defineLocale(key, values);
          }
  
          if (data) {
            // moment.duration._locale = moment._locale = data;
            globalLocale = data;
          } else {
            if (typeof console !== 'undefined' && console.warn) {
              //warn user if arguments are passed but the locale could not be set
              console.warn('Locale ' + key + ' not found. Did you forget to load it?');
            }
          }
        }
  
        return globalLocale._abbr;
      }
  
      function defineLocale(name, config) {
        if (config !== null) {
          var locale,
              parentConfig = baseConfig;
          config.abbr = name;
  
          if (locales[name] != null) {
            deprecateSimple('defineLocaleOverride', 'use moment.updateLocale(localeName, config) to change ' + 'an existing locale. moment.defineLocale(localeName, ' + 'config) should only be used for creating a new locale ' + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
            parentConfig = locales[name]._config;
          } else if (config.parentLocale != null) {
            if (locales[config.parentLocale] != null) {
              parentConfig = locales[config.parentLocale]._config;
            } else {
              locale = loadLocale(config.parentLocale);
  
              if (locale != null) {
                parentConfig = locale._config;
              } else {
                if (!localeFamilies[config.parentLocale]) {
                  localeFamilies[config.parentLocale] = [];
                }
  
                localeFamilies[config.parentLocale].push({
                  name: name,
                  config: config
                });
                return null;
              }
            }
          }
  
          locales[name] = new Locale(mergeConfigs(parentConfig, config));
  
          if (localeFamilies[name]) {
            localeFamilies[name].forEach(function (x) {
              defineLocale(x.name, x.config);
            });
          } // backwards compat for now: also set the locale
          // make sure we set the locale AFTER all child locales have been
          // created, so we won't end up with the child locale set.
  
  
          getSetGlobalLocale(name);
          return locales[name];
        } else {
          // useful for testing
          delete locales[name];
          return null;
        }
      }
  
      function updateLocale(name, config) {
        if (config != null) {
          var locale,
              tmpLocale,
              parentConfig = baseConfig; // MERGE
  
          tmpLocale = loadLocale(name);
  
          if (tmpLocale != null) {
            parentConfig = tmpLocale._config;
          }
  
          config = mergeConfigs(parentConfig, config);
          locale = new Locale(config);
          locale.parentLocale = locales[name];
          locales[name] = locale; // backwards compat for now: also set the locale
  
          getSetGlobalLocale(name);
        } else {
          // pass null for config to unupdate, useful for tests
          if (locales[name] != null) {
            if (locales[name].parentLocale != null) {
              locales[name] = locales[name].parentLocale;
            } else if (locales[name] != null) {
              delete locales[name];
            }
          }
        }
  
        return locales[name];
      } // returns locale data
  
  
      function getLocale(key) {
        var locale;
  
        if (key && key._locale && key._locale._abbr) {
          key = key._locale._abbr;
        }
  
        if (!key) {
          return globalLocale;
        }
  
        if (!isArray(key)) {
          //short-circuit everything else
          locale = loadLocale(key);
  
          if (locale) {
            return locale;
          }
  
          key = [key];
        }
  
        return chooseLocale(key);
      }
  
      function listLocales() {
        return keys(locales);
      }
  
      function checkOverflow(m) {
        var overflow;
        var a = m._a;
  
        if (a && getParsingFlags(m).overflow === -2) {
          overflow = a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : a[HOUR] < 0 || a[HOUR] > 24 || a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0) ? HOUR : a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : -1;
  
          if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
            overflow = DATE;
          }
  
          if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
            overflow = WEEK;
          }
  
          if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
            overflow = WEEKDAY;
          }
  
          getParsingFlags(m).overflow = overflow;
        }
  
        return m;
      } // Pick the first defined of two or three arguments.
  
  
      function defaults(a, b, c) {
        if (a != null) {
          return a;
        }
  
        if (b != null) {
          return b;
        }
  
        return c;
      }
  
      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()];
        }
  
        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
      } // convert an array to a date.
      // the array should mirror the parameters below
      // note: all values past the year are optional and will default to the lowest possible value.
      // [year, month, day , hour, minute, second, millisecond]
  
  
      function configFromArray(config) {
        var i,
            date,
            input = [],
            currentDate,
            expectedWeekday,
            yearToUse;
  
        if (config._d) {
          return;
        }
  
        currentDate = currentDateArray(config); //compute day of the year from weeks and weekdays
  
        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
          dayOfYearFromWeekInfo(config);
        } //if the day of the year is set, figure out what it is
  
  
        if (config._dayOfYear != null) {
          yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
  
          if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
            getParsingFlags(config)._overflowDayOfYear = true;
          }
  
          date = createUTCDate(yearToUse, 0, config._dayOfYear);
          config._a[MONTH] = date.getUTCMonth();
          config._a[DATE] = date.getUTCDate();
        } // Default to current date.
        // * if no year, month, day of month are given, default to today
        // * if day of month is given, default month and year
        // * if month is given, default only year
        // * if year is given, don't default anything
  
  
        for (i = 0; i < 3 && config._a[i] == null; ++i) {
          config._a[i] = input[i] = currentDate[i];
        } // Zero out whatever was not defaulted, including time
  
  
        for (; i < 7; i++) {
          config._a[i] = input[i] = config._a[i] == null ? i === 2 ? 1 : 0 : config._a[i];
        } // Check for 24:00:00.000
  
  
        if (config._a[HOUR] === 24 && config._a[MINUTE] === 0 && config._a[SECOND] === 0 && config._a[MILLISECOND] === 0) {
          config._nextDay = true;
          config._a[HOUR] = 0;
        }
  
        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
        expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); // Apply timezone offset from input. The actual utcOffset can be changed
        // with parseZone.
  
        if (config._tzm != null) {
          config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
        }
  
        if (config._nextDay) {
          config._a[HOUR] = 24;
        } // check for mismatching day of week
  
  
        if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
          getParsingFlags(config).weekdayMismatch = true;
        }
      }
  
      function dayOfYearFromWeekInfo(config) {
        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
        w = config._w;
  
        if (w.GG != null || w.W != null || w.E != null) {
          dow = 1;
          doy = 4; // 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
          // create now).
  
          weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
          week = defaults(w.W, 1);
          weekday = defaults(w.E, 1);
  
          if (weekday < 1 || weekday > 7) {
            weekdayOverflow = true;
          }
        } else {
          dow = config._locale._week.dow;
          doy = config._locale._week.doy;
          var curWeek = weekOfYear(createLocal(), dow, doy);
          weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); // Default to current week.
  
          week = defaults(w.w, curWeek.week);
  
          if (w.d != null) {
            // weekday -- low day numbers are considered next week
            weekday = w.d;
  
            if (weekday < 0 || weekday > 6) {
              weekdayOverflow = true;
            }
          } else if (w.e != null) {
            // local weekday -- counting starts from beginning of week
            weekday = w.e + dow;
  
            if (w.e < 0 || w.e > 6) {
              weekdayOverflow = true;
            }
          } else {
            // default to beginning of week
            weekday = dow;
          }
        }
  
        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
          getParsingFlags(config)._overflowWeeks = true;
        } else if (weekdayOverflow != null) {
          getParsingFlags(config)._overflowWeekday = true;
        } else {
          temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
          config._a[YEAR] = temp.year;
          config._dayOfYear = temp.dayOfYear;
        }
      } // iso 8601 regex
      // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
  
  
      var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
      var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
      var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
      var isoDates = [['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], ['GGGG-[W]WW', /\d{4}-W\d\d/, false], ['YYYY-DDD', /\d{4}-\d{3}/], ['YYYY-MM', /\d{4}-\d\d/, false], ['YYYYYYMMDD', /[+-]\d{10}/], ['YYYYMMDD', /\d{8}/], // YYYYMM is NOT allowed by the standard
      ['GGGG[W]WWE', /\d{4}W\d{3}/], ['GGGG[W]WW', /\d{4}W\d{2}/, false], ['YYYYDDD', /\d{7}/]]; // iso time formats and regexes
  
      var isoTimes = [['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], ['HH:mm:ss', /\d\d:\d\d:\d\d/], ['HH:mm', /\d\d:\d\d/], ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], ['HHmmss', /\d\d\d\d\d\d/], ['HHmm', /\d\d\d\d/], ['HH', /\d\d/]];
      var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; // date from iso format
  
      function configFromISO(config) {
        var i,
            l,
            string = config._i,
            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
            allowTime,
            dateFormat,
            timeFormat,
            tzFormat;
  
        if (match) {
          getParsingFlags(config).iso = true;
  
          for (i = 0, l = isoDates.length; i < l; i++) {
            if (isoDates[i][1].exec(match[1])) {
              dateFormat = isoDates[i][0];
              allowTime = isoDates[i][2] !== false;
              break;
            }
          }
  
          if (dateFormat == null) {
            config._isValid = false;
            return;
          }
  
          if (match[3]) {
            for (i = 0, l = isoTimes.length; i < l; i++) {
              if (isoTimes[i][1].exec(match[3])) {
                // match[2] should be 'T' or space
                timeFormat = (match[2] || ' ') + isoTimes[i][0];
                break;
              }
            }
  
            if (timeFormat == null) {
              config._isValid = false;
              return;
            }
          }
  
          if (!allowTime && timeFormat != null) {
            config._isValid = false;
            return;
          }
  
          if (match[4]) {
            if (tzRegex.exec(match[4])) {
              tzFormat = 'Z';
            } else {
              config._isValid = false;
              return;
            }
          }
  
          config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
          configFromStringAndFormat(config);
        } else {
          config._isValid = false;
        }
      } // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
  
  
      var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
  
      function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
        var result = [untruncateYear(yearStr), defaultLocaleMonthsShort.indexOf(monthStr), parseInt(dayStr, 10), parseInt(hourStr, 10), parseInt(minuteStr, 10)];
  
        if (secondStr) {
          result.push(parseInt(secondStr, 10));
        }
  
        return result;
      }
  
      function untruncateYear(yearStr) {
        var year = parseInt(yearStr, 10);
  
        if (year <= 49) {
          return 2000 + year;
        } else if (year <= 999) {
          return 1900 + year;
        }
  
        return year;
      }
  
      function preprocessRFC2822(s) {
        // Remove comments and folding whitespace and replace multiple-spaces with a single space
        return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
      }
  
      function checkWeekday(weekdayStr, parsedInput, config) {
        if (weekdayStr) {
          // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
          var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
              weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
  
          if (weekdayProvided !== weekdayActual) {
            getParsingFlags(config).weekdayMismatch = true;
            config._isValid = false;
            return false;
          }
        }
  
        return true;
      }
  
      var obsOffsets = {
        UT: 0,
        GMT: 0,
        EDT: -4 * 60,
        EST: -5 * 60,
        CDT: -5 * 60,
        CST: -6 * 60,
        MDT: -6 * 60,
        MST: -7 * 60,
        PDT: -7 * 60,
        PST: -8 * 60
      };
  
      function calculateOffset(obsOffset, militaryOffset, numOffset) {
        if (obsOffset) {
          return obsOffsets[obsOffset];
        } else if (militaryOffset) {
          // the only allowed military tz is Z
          return 0;
        } else {
          var hm = parseInt(numOffset, 10);
          var m = hm % 100,
              h = (hm - m) / 100;
          return h * 60 + m;
        }
      } // date and time from ref 2822 format
  
  
      function configFromRFC2822(config) {
        var match = rfc2822.exec(preprocessRFC2822(config._i));
  
        if (match) {
          var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
  
          if (!checkWeekday(match[1], parsedArray, config)) {
            return;
          }
  
          config._a = parsedArray;
          config._tzm = calculateOffset(match[8], match[9], match[10]);
          config._d = createUTCDate.apply(null, config._a);
  
          config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
  
          getParsingFlags(config).rfc2822 = true;
        } else {
          config._isValid = false;
        }
      } // date from iso format or fallback
  
  
      function configFromString(config) {
        var matched = aspNetJsonRegex.exec(config._i);
  
        if (matched !== null) {
          config._d = new Date(+matched[1]);
          return;
        }
  
        configFromISO(config);
  
        if (config._isValid === false) {
          delete config._isValid;
        } else {
          return;
        }
  
        configFromRFC2822(config);
  
        if (config._isValid === false) {
          delete config._isValid;
        } else {
          return;
        } // Final attempt, use Input Fallback
  
  
        hooks.createFromInputFallback(config);
      }
  
      hooks.createFromInputFallback = deprecate('value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + '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' : ''));
      }); // constant that refers to the ISO standard
  
      hooks.ISO_8601 = function () {}; // constant that refers to the RFC 2822 form
  
  
      hooks.RFC_2822 = function () {}; // date from string and format string
  
  
      function configFromStringAndFormat(config) {
        // TODO: Move this to another part of the creation flow to prevent circular deps
        if (config._f === hooks.ISO_8601) {
          configFromISO(config);
          return;
        }
  
        if (config._f === hooks.RFC_2822) {
          configFromRFC2822(config);
          return;
        }
  
        config._a = [];
        getParsingFlags(config).empty = true; // This array is used to make a Date, either with `new Date` or `Date.UTC`
  
        var string = '' + config._i,
            i,
            parsedInput,
            tokens,
            token,
            skipped,
            stringLength = string.length,
            totalParsedInputLength = 0;
        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
  
        for (i = 0; i < tokens.length; i++) {
          token = tokens[i];
          parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; // console.log('token', token, 'parsedInput', parsedInput,
          //         'regex', getParseRegexForToken(token, config));
  
          if (parsedInput) {
            skipped = string.substr(0, string.indexOf(parsedInput));
  
            if (skipped.length > 0) {
              getParsingFlags(config).unusedInput.push(skipped);
            }
  
            string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
            totalParsedInputLength += parsedInput.length;
          } // don't parse if it's not a known token
  
  
          if (formatTokenFunctions[token]) {
            if (parsedInput) {
              getParsingFlags(config).empty = false;
            } else {
              getParsingFlags(config).unusedTokens.push(token);
            }
  
            addTimeToArrayFromToken(token, parsedInput, config);
          } else if (config._strict && !parsedInput) {
            getParsingFlags(config).unusedTokens.push(token);
          }
        } // add remaining unparsed input length to the string
  
  
        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
  
        if (string.length > 0) {
          getParsingFlags(config).unusedInput.push(string);
        } // clear _12h flag if hour is <= 12
  
  
        if (config._a[HOUR] <= 12 && getParsingFlags(config).bigHour === true && config._a[HOUR] > 0) {
          getParsingFlags(config).bigHour = undefined;
        }
  
        getParsingFlags(config).parsedDateParts = config._a.slice(0);
        getParsingFlags(config).meridiem = config._meridiem; // handle meridiem
  
        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
        configFromArray(config);
        checkOverflow(config);
      }
  
      function meridiemFixWrap(locale, hour, meridiem) {
        var isPm;
  
        if (meridiem == null) {
          // nothing to do
          return hour;
        }
  
        if (locale.meridiemHour != null) {
          return locale.meridiemHour(hour, meridiem);
        } else if (locale.isPM != null) {
          // Fallback
          isPm = locale.isPM(meridiem);
  
          if (isPm && hour < 12) {
            hour += 12;
          }
  
          if (!isPm && hour === 12) {
            hour = 0;
          }
  
          return hour;
        } else {
          // this is not supposed to happen
          return hour;
        }
      } // date from string and array of format strings
  
  
      function configFromStringAndArray(config) {
        var tempConfig, bestMoment, scoreToBeat, i, currentScore;
  
        if (config._f.length === 0) {
          getParsingFlags(config).invalidFormat = true;
          config._d = new Date(NaN);
          return;
        }
  
        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);
  
          if (!isValid(tempConfig)) {
            continue;
          } // if there is any input that was not parsed add a penalty for that format
  
  
          currentScore += getParsingFlags(tempConfig).charsLeftOver; //or tokens
  
          currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
          getParsingFlags(tempConfig).score = currentScore;
  
          if (scoreToBeat == null || currentScore < scoreToBeat) {
            scoreToBeat = currentScore;
            bestMoment = tempConfig;
          }
        }
  
        extend(config, bestMoment || tempConfig);
      }
  
      function configFromObject(config) {
        if (config._d) {
          return;
        }
  
        var i = normalizeObjectUnits(config._i);
        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
          return obj && parseInt(obj, 10);
        });
        configFromArray(config);
      }
  
      function createFromConfig(config) {
        var res = new Moment(checkOverflow(prepareConfig(config)));
  
        if (res._nextDay) {
          // Adding is smart enough around DST
          res.add(1, 'd');
          res._nextDay = undefined;
        }
  
        return res;
      }
  
      function prepareConfig(config) {
        var input = config._i,
            format = config._f;
        config._locale = config._locale || getLocale(config._l);
  
        if (input === null || format === undefined && input === '') {
          return createInvalid({
            nullInput: true
          });
        }
  
        if (typeof input === 'string') {
          config._i = input = config._locale.preparse(input);
        }
  
        if (isMoment(input)) {
          return new Moment(checkOverflow(input));
        } else if (isDate(input)) {
          config._d = input;
        } else if (isArray(format)) {
          configFromStringAndArray(config);
        } else if (format) {
          configFromStringAndFormat(config);
        } else {
          configFromInput(config);
        }
  
        if (!isValid(config)) {
          config._d = null;
        }
  
        return config;
      }
  
      function configFromInput(config) {
        var input = config._i;
  
        if (isUndefined(input)) {
          config._d = new Date(hooks.now());
        } else if (isDate(input)) {
          config._d = new Date(input.valueOf());
        } else if (typeof input === 'string') {
          configFromString(config);
        } else if (isArray(input)) {
          config._a = map(input.slice(0), function (obj) {
            return parseInt(obj, 10);
          });
          configFromArray(config);
        } else if (isObject(input)) {
          configFromObject(config);
        } else if (isNumber(input)) {
          // from milliseconds
          config._d = new Date(input);
        } else {
          hooks.createFromInputFallback(config);
        }
      }
  
      function createLocalOrUTC(input, format, locale, strict, isUTC) {
        var c = {};
  
        if (locale === true || locale === false) {
          strict = locale;
          locale = undefined;
        }
  
        if (isObject(input) && isObjectEmpty(input) || isArray(input) && input.length === 0) {
          input = undefined;
        } // object construction must be done this way.
        // https://github.com/moment/moment/issues/1423
  
  
        c._isAMomentObject = true;
        c._useUTC = c._isUTC = isUTC;
        c._l = locale;
        c._i = input;
        c._f = format;
        c._strict = strict;
        return createFromConfig(c);
      }
  
      function createLocal(input, format, locale, strict) {
        return createLocalOrUTC(input, format, locale, strict, false);
      }
  
      var prototypeMin = deprecate('moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', function () {
        var other = createLocal.apply(null, arguments);
  
        if (this.isValid() && other.isValid()) {
          return other < this ? this : other;
        } else {
          return createInvalid();
        }
      });
      var prototypeMax = deprecate('moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', function () {
        var other = createLocal.apply(null, arguments);
  
        if (this.isValid() && other.isValid()) {
          return other > this ? this : other;
        } else {
          return createInvalid();
        }
      }); // Pick a moment m from moments so that m[fn](other) is true for all
      // other. This relies on the function fn to be transitive.
      //
      // moments should either be an array of moment objects or an array, whose
      // first element is an array of moment objects.
  
      function pickBy(fn, moments) {
        var res, i;
  
        if (moments.length === 1 && isArray(moments[0])) {
          moments = moments[0];
        }
  
        if (!moments.length) {
          return createLocal();
        }
  
        res = moments[0];
  
        for (i = 1; i < moments.length; ++i) {
          if (!moments[i].isValid() || moments[i][fn](res)) {
            res = moments[i];
          }
        }
  
        return res;
      } // TODO: Use [].sort instead?
  
  
      function min() {
        var args = [].slice.call(arguments, 0);
        return pickBy('isBefore', args);
      }
  
      function max() {
        var args = [].slice.call(arguments, 0);
        return pickBy('isAfter', args);
      }
  
      var now = function () {
        return Date.now ? Date.now() : +new Date();
      };
  
      var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
  
      function isDurationValid(m) {
        for (var key in m) {
          if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
            return false;
          }
        }
  
        var unitHasDecimal = false;
  
        for (var i = 0; i < ordering.length; ++i) {
          if (m[ordering[i]]) {
            if (unitHasDecimal) {
              return false; // only allow non-integers for smallest unit
            }
  
            if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
              unitHasDecimal = true;
            }
          }
        }
  
        return true;
      }
  
      function isValid$1() {
        return this._isValid;
      }
  
      function createInvalid$1() {
        return createDuration(NaN);
      }
  
      function Duration(duration) {
        var normalizedInput = normalizeObjectUnits(duration),
            years = normalizedInput.year || 0,
            quarters = normalizedInput.quarter || 0,
            months = normalizedInput.month || 0,
            weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
            days = normalizedInput.day || 0,
            hours = normalizedInput.hour || 0,
            minutes = normalizedInput.minute || 0,
            seconds = normalizedInput.second || 0,
            milliseconds = normalizedInput.millisecond || 0;
        this._isValid = isDurationValid(normalizedInput); // representation for dateAddRemove
  
        this._milliseconds = +milliseconds + seconds * 1e3 + // 1000
        minutes * 6e4 + // 1000 * 60
        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
        // Because of dateAddRemove treats 24 hours as different from a
        // day when working around DST, we need to store them separately
  
        this._days = +days + weeks * 7; // It is impossible to translate months into days without knowing
        // which months you are are talking about, so we have to store
        // it separately.
  
        this._months = +months + quarters * 3 + years * 12;
        this._data = {};
        this._locale = getLocale();
  
        this._bubble();
      }
  
      function isDuration(obj) {
        return obj instanceof Duration;
      }
  
      function absRound(number) {
        if (number < 0) {
          return Math.round(-1 * number) * -1;
        } else {
          return Math.round(number);
        }
      } // 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', matchShortOffset);
      addRegexToken('ZZ', matchShortOffset);
      addParseToken(['Z', 'ZZ'], function (input, array, config) {
        config._useUTC = true;
        config._tzm = offsetFromString(matchShortOffset, input);
      }); // HELPERS
      // timezone chunker
      // '+10:00' > ['10',  '00']
      // '-1530'  > ['-15', '30']
  
      var chunkOffset = /([\+\-]|\d\d)/gi;
  
      function offsetFromString(matcher, string) {
        var matches = (string || '').match(matcher);
  
        if (matches === null) {
          return null;
        }
  
        var chunk = matches[matches.length - 1] || [];
        var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
        var minutes = +(parts[1] * 60) + toInt(parts[2]);
        return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
      } // Return a moment from input, that is local/utc/zone equivalent to model.
  
  
      function cloneWithOffset(input, model) {
        var res, diff;
  
        if (model._isUTC) {
          res = model.clone();
          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);
  
          hooks.updateOffset(res, false);
          return res;
        } else {
          return 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.
  
  
      function getSetOffset(input, keepLocalTime, keepMinutes) {
        var offset = this._offset || 0,
            localAdjust;
  
        if (!this.isValid()) {
          return input != null ? this : NaN;
        }
  
        if (input != null) {
          if (typeof input === 'string') {
            input = offsetFromString(matchShortOffset, input);
  
            if (input === null) {
              return this;
            }
          } else if (Math.abs(input) < 16 && !keepMinutes) {
            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);
        }
      }
  
      function getSetZone(input, keepLocalTime) {
        if (input != null) {
          if (typeof input !== 'string') {
            input = -input;
          }
  
          this.utcOffset(input, keepLocalTime);
          return this;
        } else {
          return -this.utcOffset();
        }
      }
  
      function setOffsetToUTC(keepLocalTime) {
        return this.utcOffset(0, keepLocalTime);
      }
  
      function setOffsetToLocal(keepLocalTime) {
        if (this._isUTC) {
          this.utcOffset(0, keepLocalTime);
          this._isUTC = false;
  
          if (keepLocalTime) {
            this.subtract(getDateOffset(this), 'm');
          }
        }
  
        return this;
      }
  
      function setOffsetToParsedOffset() {
        if (this._tzm != null) {
          this.utcOffset(this._tzm, false, true);
        } else if (typeof this._i === 'string') {
          var tZone = offsetFromString(matchOffset, this._i);
  
          if (tZone != null) {
            this.utcOffset(tZone);
          } else {
            this.utcOffset(0, true);
          }
        }
  
        return this;
      }
  
      function hasAlignedHourOffset(input) {
        if (!this.isValid()) {
          return false;
        }
  
        input = input ? createLocal(input).utcOffset() : 0;
        return (this.utcOffset() - input) % 60 === 0;
      }
  
      function isDaylightSavingTime() {
        return this.utcOffset() > this.clone().month(0).utcOffset() || this.utcOffset() > this.clone().month(5).utcOffset();
      }
  
      function isDaylightSavingTimeShifted() {
        if (!isUndefined(this._isDSTShifted)) {
          return this._isDSTShifted;
        }
  
        var 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;
        }
  
        return this._isDSTShifted;
      }
  
      function isLocal() {
        return this.isValid() ? !this._isUTC : false;
      }
  
      function isUtcOffset() {
        return this.isValid() ? this._isUTC : false;
      }
  
      function isUtc() {
        return this.isValid() ? this._isUTC && this._offset === 0 : false;
      } // 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)?)?$/;
  
      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 : 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 = createInvalid$1;
  
      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 = {};
        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;
      } // TODO: remove 'name' arg after deprecation is removed
  
  
      function createAdder(direction, name) {
        return function (val, period) {
          var dur, tmp; //invert the arguments, but complain about it
  
          if (period !== null && !isNaN(+period)) {
            deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
            tmp = val;
            val = period;
            period = tmp;
          }
  
          val = typeof val === 'string' ? +val : val;
          dur = createDuration(val, period);
          addSubtract(this, dur, direction);
          return this;
        };
      }
  
      function addSubtract(mom, duration, isAdding, updateOffset) {
        var milliseconds = duration._milliseconds,
            days = absRound(duration._days),
            months = absRound(duration._months);
  
        if (!mom.isValid()) {
          // No op
          return;
        }
  
        updateOffset = updateOffset == null ? true : updateOffset;
  
        if (months) {
          setMonth(mom, get(mom, 'Month') + months * isAdding);
        }
  
        if (days) {
          set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
        }
  
        if (milliseconds) {
          mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
        }
  
        if (updateOffset) {
          hooks.updateOffset(mom, days || months);
        }
      }
  
      var add = createAdder(1, 'add');
      var subtract = createAdder(-1, 'subtract');
  
      function getCalendarFormat(myMoment, now) {
        var diff = myMoment.diff(now, 'days', true);
        return diff < -6 ? 'sameElse' : diff < -1 ? 'lastWeek' : diff < 0 ? 'lastDay' : diff < 1 ? 'sameDay' : diff < 2 ? 'nextDay' : diff < 7 ? 'nextWeek' : 'sameElse';
      }
  
      function calendar$1(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(),
            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)));
      }
  
      function clone() {
        return new Moment(this);
      }
  
      function isAfter(input, units) {
        var localInput = isMoment(input) ? input : createLocal(input);
  
        if (!(this.isValid() && localInput.isValid())) {
          return false;
        }
  
        units = normalizeUnits(units) || 'millisecond';
  
        if (units === 'millisecond') {
          return this.valueOf() > localInput.valueOf();
        } else {
          return localInput.valueOf() < this.clone().startOf(units).valueOf();
        }
      }
  
      function isBefore(input, units) {
        var localInput = isMoment(input) ? input : createLocal(input);
  
        if (!(this.isValid() && localInput.isValid())) {
          return false;
        }
  
        units = normalizeUnits(units) || 'millisecond';
  
        if (units === 'millisecond') {
          return this.valueOf() < localInput.valueOf();
        } else {
          return this.clone().endOf(units).valueOf() < localInput.valueOf();
        }
      }
  
      function isBetween(from, to, units, inclusivity) {
        var localFrom = isMoment(from) ? from : createLocal(from),
            localTo = isMoment(to) ? to : createLocal(to);
  
        if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
          return false;
        }
  
        inclusivity = inclusivity || '()';
        return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) && (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
      }
  
      function isSame(input, units) {
        var localInput = isMoment(input) ? input : createLocal(input),
            inputMs;
  
        if (!(this.isValid() && localInput.isValid())) {
          return false;
        }
  
        units = normalizeUnits(units) || 'millisecond';
  
        if (units === 'millisecond') {
          return this.valueOf() === localInput.valueOf();
        } else {
          inputMs = localInput.valueOf();
          return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
        }
      }
  
      function isSameOrAfter(input, units) {
        return this.isSame(input, units) || this.isAfter(input, units);
      }
  
      function isSameOrBefore(input, units) {
        return this.isSame(input, units) || this.isBefore(input, units);
      }
  
      function diff(input, units, asFloat) {
        var that, zoneDelta, output;
  
        if (!this.isValid()) {
          return NaN;
        }
  
        that = cloneWithOffset(input, this);
  
        if (!that.isValid()) {
          return NaN;
        }
  
        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
        units = normalizeUnits(units);
  
        switch (units) {
          case 'year':
            output = monthDiff(this, that) / 12;
            break;
  
          case 'month':
            output = monthDiff(this, that);
            break;
  
          case 'quarter':
            output = monthDiff(this, that) / 3;
            break;
  
          case 'second':
            output = (this - that) / 1e3;
            break;
          // 1000
  
          case 'minute':
            output = (this - that) / 6e4;
            break;
          // 1000 * 60
  
          case 'hour':
            output = (this - that) / 36e5;
            break;
          // 1000 * 60 * 60
  
          case 'day':
            output = (this - that - zoneDelta) / 864e5;
            break;
          // 1000 * 60 * 60 * 24, negate dst
  
          case 'week':
            output = (this - that - zoneDelta) / 6048e5;
            break;
          // 1000 * 60 * 60 * 24 * 7, negate dst
  
          default:
            output = this - that;
        }
  
        return asFloat ? output : absFloor(output);
      }
  
      function monthDiff(a, b) {
        // difference in months
        var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
            // b is in (anchor - 1 month, anchor + 1 month)
        anchor = a.clone().add(wholeMonthDiff, 'months'),
            anchor2,
            adjust;
  
        if (b - anchor < 0) {
          anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); // linear across the month
  
          adjust = (b - anchor) / (anchor - anchor2);
        } else {
          anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); // linear across the month
  
          adjust = (b - anchor) / (anchor2 - anchor);
        } //check for negative zero, return zero if negative zero
  
  
        return -(wholeMonthDiff + adjust) || 0;
      }
  
      hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
      hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
  
      function toString() {
        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
      }
  
      function toISOString(keepOffset) {
        if (!this.isValid()) {
          return null;
        }
  
        var utc = keepOffset !== true;
        var m = utc ? this.clone().utc() : this;
  
        if (m.year() < 0 || m.year() > 9999) {
          return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
        }
  
        if (isFunction(Date.prototype.toISOString)) {
          // native implementation is ~50x faster, use it when we can
          if (utc) {
            return this.toDate().toISOString();
          } else {
            return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
          }
        }
  
        return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
      }
      /**
       * Return a human readable representation of a moment that can
       * also be evaluated to get a new moment which is the same
       *
       * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
       */
  
  
      function inspect() {
        if (!this.isValid()) {
          return 'moment.invalid(/* ' + this._i + ' */)';
        }
  
        var func = 'moment';
        var zone = '';
  
        if (!this.isLocal()) {
          func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
          zone = 'Z';
        }
  
        var prefix = '[' + func + '("]';
        var year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
        var datetime = '-MM-DD[T]HH:mm:ss.SSS';
        var suffix = zone + '[")]';
        return this.format(prefix + year + datetime + suffix);
      }
  
      function format(inputString) {
        if (!inputString) {
          inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
        }
  
        var output = formatMoment(this, inputString);
        return this.localeData().postformat(output);
      }
  
      function from(time, withoutSuffix) {
        if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
          return createDuration({
            to: this,
            from: time
          }).locale(this.locale()).humanize(!withoutSuffix);
        } else {
          return this.localeData().invalidDate();
        }
      }
  
      function fromNow(withoutSuffix) {
        return this.from(createLocal(), withoutSuffix);
      }
  
      function to(time, withoutSuffix) {
        if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
          return createDuration({
            from: this,
            to: time
          }).locale(this.locale()).humanize(!withoutSuffix);
        } else {
          return this.localeData().invalidDate();
        }
      }
  
      function toNow(withoutSuffix) {
        return this.to(createLocal(), withoutSuffix);
      } // If passed a locale key, it will set the locale for this
      // instance.  Otherwise, it will return the locale configuration
      // variables for this instance.
  
  
      function locale(key) {
        var newLocaleData;
  
        if (key === undefined) {
          return this._locale._abbr;
        } else {
          newLocaleData = getLocale(key);
  
          if (newLocaleData != null) {
            this._locale = newLocaleData;
          }
  
          return this;
        }
      }
  
      var lang = deprecate('moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', function (key) {
        if (key === undefined) {
          return this.localeData();
        } else {
          return this.locale(key);
        }
      });
  
      function localeData() {
        return this._locale;
      }
  
      var MS_PER_SECOND = 1000;
      var MS_PER_MINUTE = 60 * MS_PER_SECOND;
      var MS_PER_HOUR = 60 * MS_PER_MINUTE;
      var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR; // actual modulo - handles negative numbers (for dates before 1970):
  
      function mod$1(dividend, divisor) {
        return (dividend % divisor + divisor) % divisor;
      }
  
      function localStartOfDate(y, m, d) {
        // the date constructor remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0) {
          // preserve leap years using a full 400 year cycle, then reset
          return new Date(y + 400, m, d) - MS_PER_400_YEARS;
        } else {
          return new Date(y, m, d).valueOf();
        }
      }
  
      function utcStartOfDate(y, m, d) {
        // Date.UTC remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0) {
          // preserve leap years using a full 400 year cycle, then reset
          return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
        } else {
          return Date.UTC(y, m, d);
        }
      }
  
      function startOf(units) {
        var time;
        units = normalizeUnits(units);
  
        if (units === undefined || units === 'millisecond' || !this.isValid()) {
          return this;
        }
  
        var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
  
        switch (units) {
          case 'year':
            time = startOfDate(this.year(), 0, 1);
            break;
  
          case 'quarter':
            time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
            break;
  
          case 'month':
            time = startOfDate(this.year(), this.month(), 1);
            break;
  
          case 'week':
            time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
            break;
  
          case 'isoWeek':
            time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
            break;
  
          case 'day':
          case 'date':
            time = startOfDate(this.year(), this.month(), this.date());
            break;
  
          case 'hour':
            time = this._d.valueOf();
            time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
            break;
  
          case 'minute':
            time = this._d.valueOf();
            time -= mod$1(time, MS_PER_MINUTE);
            break;
  
          case 'second':
            time = this._d.valueOf();
            time -= mod$1(time, MS_PER_SECOND);
            break;
        }
  
        this._d.setTime(time);
  
        hooks.updateOffset(this, true);
        return this;
      }
  
      function endOf(units) {
        var time;
        units = normalizeUnits(units);
  
        if (units === undefined || units === 'millisecond' || !this.isValid()) {
          return this;
        }
  
        var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
  
        switch (units) {
          case 'year':
            time = startOfDate(this.year() + 1, 0, 1) - 1;
            break;
  
          case 'quarter':
            time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
            break;
  
          case 'month':
            time = startOfDate(this.year(), this.month() + 1, 1) - 1;
            break;
  
          case 'week':
            time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
            break;
  
          case 'isoWeek':
            time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
            break;
  
          case 'day':
          case 'date':
            time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
            break;
  
          case 'hour':
            time = this._d.valueOf();
            time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
            break;
  
          case 'minute':
            time = this._d.valueOf();
            time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
            break;
  
          case 'second':
            time = this._d.valueOf();
            time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
            break;
        }
  
        this._d.setTime(time);
  
        hooks.updateOffset(this, true);
        return this;
      }
  
      function valueOf() {
        return this._d.valueOf() - (this._offset || 0) * 60000;
      }
  
      function unix() {
        return Math.floor(this.valueOf() / 1000);
      }
  
      function toDate() {
        return new Date(this.valueOf());
      }
  
      function toArray() {
        var m = this;
        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
      }
  
      function toObject() {
        var m = this;
        return {
          years: m.year(),
          months: m.month(),
          date: m.date(),
          hours: m.hours(),
          minutes: m.minutes(),
          seconds: m.seconds(),
          milliseconds: m.milliseconds()
        };
      }
  
      function toJSON() {
        // new Date(NaN).toJSON() === null
        return this.isValid() ? this.toISOString() : null;
      }
  
      function isValid$2() {
        return isValid(this);
      }
  
      function parsingFlags() {
        return extend({}, getParsingFlags(this));
      }
  
      function invalidAt() {
        return getParsingFlags(this).overflow;
      }
  
      function creationData() {
        return {
          input: this._i,
          format: this._f,
          locale: this._locale,
          isUTC: this._isUTC,
          strict: this._strict
        };
      } // FORMATTING
  
  
      addFormatToken(0, ['gg', 2], 0, function () {
        return this.weekYear() % 100;
      });
      addFormatToken(0, ['GG', 2], 0, function () {
        return this.isoWeekYear() % 100;
      });
  
      function addWeekYearFormatToken(token, getter) {
        addFormatToken(0, [token, token.length], 0, getter);
      }
  
      addWeekYearFormatToken('gggg', 'weekYear');
      addWeekYearFormatToken('ggggg', 'weekYear');
      addWeekYearFormatToken('GGGG', 'isoWeekYear');
      addWeekYearFormatToken('GGGGG', 'isoWeekYear'); // ALIASES
  
      addUnitAlias('weekYear', 'gg');
      addUnitAlias('isoWeekYear', 'GG'); // PRIORITY
  
      addUnitPriority('weekYear', 1);
      addUnitPriority('isoWeekYear', 1); // PARSING
  
      addRegexToken('G', matchSigned);
      addRegexToken('g', matchSigned);
      addRegexToken('GG', match1to2, match2);
      addRegexToken('gg', match1to2, match2);
      addRegexToken('GGGG', match1to4, match4);
      addRegexToken('gggg', match1to4, match4);
      addRegexToken('GGGGG', match1to6, match6);
      addRegexToken('ggggg', match1to6, match6);
      addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
        week[token.substr(0, 2)] = toInt(input);
      });
      addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
        week[token] = hooks.parseTwoDigitYear(input);
      }); // MOMENTS
  
      function getSetWeekYear(input) {
        return getSetWeekYearHelper.call(this, input, this.week(), this.weekday(), this.localeData()._week.dow, this.localeData()._week.doy);
      }
  
      function getSetISOWeekYear(input) {
        return getSetWeekYearHelper.call(this, input, this.isoWeek(), this.isoWeekday(), 1, 4);
      }
  
      function getISOWeeksInYear() {
        return weeksInYear(this.year(), 1, 4);
      }
  
      function getWeeksInYear() {
        var weekInfo = this.localeData()._week;
  
        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
      }
  
      function getSetWeekYearHelper(input, week, weekday, dow, doy) {
        var weeksTarget;
  
        if (input == null) {
          return weekOfYear(this, dow, doy).year;
        } else {
          weeksTarget = weeksInYear(input, dow, doy);
  
          if (week > weeksTarget) {
            week = weeksTarget;
          }
  
          return setWeekAll.call(this, input, week, weekday, dow, doy);
        }
      }
  
      function setWeekAll(weekYear, week, weekday, dow, doy) {
        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
        this.year(date.getUTCFullYear());
        this.month(date.getUTCMonth());
        this.date(date.getUTCDate());
        return this;
      } // FORMATTING
  
  
      addFormatToken('Q', 0, 'Qo', 'quarter'); // ALIASES
  
      addUnitAlias('quarter', 'Q'); // PRIORITY
  
      addUnitPriority('quarter', 7); // PARSING
  
      addRegexToken('Q', match1);
      addParseToken('Q', function (input, array) {
        array[MONTH] = (toInt(input) - 1) * 3;
      }); // MOMENTS
  
      function getSetQuarter(input) {
        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
      } // FORMATTING
  
  
      addFormatToken('D', ['DD', 2], 'Do', 'date'); // ALIASES
  
      addUnitAlias('date', 'D'); // PRIORITY
  
      addUnitPriority('date', 9); // PARSING
  
      addRegexToken('D', match1to2);
      addRegexToken('DD', match1to2, match2);
      addRegexToken('Do', function (isStrict, locale) {
        // TODO: Remove "ordinalParse" fallback in next major release.
        return isStrict ? locale._dayOfMonthOrdinalParse || locale._ordinalParse : locale._dayOfMonthOrdinalParseLenient;
      });
      addParseToken(['D', 'DD'], DATE);
      addParseToken('Do', function (input, array) {
        array[DATE] = toInt(input.match(match1to2)[0]);
      }); // MOMENTS
  
      var getSetDayOfMonth = makeGetSet('Date', true); // FORMATTING
  
      addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); // ALIASES
  
      addUnitAlias('dayOfYear', 'DDD'); // PRIORITY
  
      addUnitPriority('dayOfYear', 4); // PARSING
  
      addRegexToken('DDD', match1to3);
      addRegexToken('DDDD', match3);
      addParseToken(['DDD', 'DDDD'], function (input, array, config) {
        config._dayOfYear = toInt(input);
      }); // HELPERS
      // MOMENTS
  
      function getSetDayOfYear(input) {
        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
        return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');
      } // FORMATTING
  
  
      addFormatToken('m', ['mm', 2], 0, 'minute'); // ALIASES
  
      addUnitAlias('minute', 'm'); // PRIORITY
  
      addUnitPriority('minute', 14); // PARSING
  
      addRegexToken('m', match1to2);
      addRegexToken('mm', match1to2, match2);
      addParseToken(['m', 'mm'], MINUTE); // MOMENTS
  
      var getSetMinute = makeGetSet('Minutes', false); // FORMATTING
  
      addFormatToken('s', ['ss', 2], 0, 'second'); // ALIASES
  
      addUnitAlias('second', 's'); // PRIORITY
  
      addUnitPriority('second', 15); // PARSING
  
      addRegexToken('s', match1to2);
      addRegexToken('ss', match1to2, match2);
      addParseToken(['s', 'ss'], SECOND); // MOMENTS
  
      var getSetSecond = makeGetSet('Seconds', false); // FORMATTING
  
      addFormatToken('S', 0, 0, function () {
        return ~~(this.millisecond() / 100);
      });
      addFormatToken(0, ['SS', 2], 0, function () {
        return ~~(this.millisecond() / 10);
      });
      addFormatToken(0, ['SSS', 3], 0, 'millisecond');
      addFormatToken(0, ['SSSS', 4], 0, function () {
        return this.millisecond() * 10;
      });
      addFormatToken(0, ['SSSSS', 5], 0, function () {
        return this.millisecond() * 100;
      });
      addFormatToken(0, ['SSSSSS', 6], 0, function () {
        return this.millisecond() * 1000;
      });
      addFormatToken(0, ['SSSSSSS', 7], 0, function () {
        return this.millisecond() * 10000;
      });
      addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
        return this.millisecond() * 100000;
      });
      addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
        return this.millisecond() * 1000000;
      }); // ALIASES
  
      addUnitAlias('millisecond', 'ms'); // PRIORITY
  
      addUnitPriority('millisecond', 16); // PARSING
  
      addRegexToken('S', match1to3, match1);
      addRegexToken('SS', match1to3, match2);
      addRegexToken('SSS', match1to3, match3);
      var token;
  
      for (token = 'SSSS'; token.length <= 9; token += 'S') {
        addRegexToken(token, matchUnsigned);
      }
  
      function parseMs(input, array) {
        array[MILLISECOND] = toInt(('0.' + input) * 1000);
      }
  
      for (token = 'S'; token.length <= 9; token += 'S') {
        addParseToken(token, parseMs);
      } // MOMENTS
  
  
      var getSetMillisecond = makeGetSet('Milliseconds', false); // FORMATTING
  
      addFormatToken('z', 0, 0, 'zoneAbbr');
      addFormatToken('zz', 0, 0, 'zoneName'); // MOMENTS
  
      function getZoneAbbr() {
        return this._isUTC ? 'UTC' : '';
      }
  
      function getZoneName() {
        return this._isUTC ? 'Coordinated Universal Time' : '';
      }
  
      var proto = Moment.prototype;
      proto.add = add;
      proto.calendar = calendar$1;
      proto.clone = clone;
      proto.diff = diff;
      proto.endOf = endOf;
      proto.format = format;
      proto.from = from;
      proto.fromNow = fromNow;
      proto.to = to;
      proto.toNow = toNow;
      proto.get = stringGet;
      proto.invalidAt = invalidAt;
      proto.isAfter = isAfter;
      proto.isBefore = isBefore;
      proto.isBetween = isBetween;
      proto.isSame = isSame;
      proto.isSameOrAfter = isSameOrAfter;
      proto.isSameOrBefore = isSameOrBefore;
      proto.isValid = isValid$2;
      proto.lang = lang;
      proto.locale = locale;
      proto.localeData = localeData;
      proto.max = prototypeMax;
      proto.min = prototypeMin;
      proto.parsingFlags = parsingFlags;
      proto.set = stringSet;
      proto.startOf = startOf;
      proto.subtract = subtract;
      proto.toArray = toArray;
      proto.toObject = toObject;
      proto.toDate = toDate;
      proto.toISOString = toISOString;
      proto.inspect = inspect;
      proto.toJSON = toJSON;
      proto.toString = toString;
      proto.unix = unix;
      proto.valueOf = valueOf;
      proto.creationData = creationData;
      proto.year = getSetYear;
      proto.isLeapYear = getIsLeapYear;
      proto.weekYear = getSetWeekYear;
      proto.isoWeekYear = getSetISOWeekYear;
      proto.quarter = proto.quarters = getSetQuarter;
      proto.month = getSetMonth;
      proto.daysInMonth = getDaysInMonth;
      proto.week = proto.weeks = getSetWeek;
      proto.isoWeek = proto.isoWeeks = getSetISOWeek;
      proto.weeksInYear = getWeeksInYear;
      proto.isoWeeksInYear = getISOWeeksInYear;
      proto.date = getSetDayOfMonth;
      proto.day = proto.days = getSetDayOfWeek;
      proto.weekday = getSetLocaleDayOfWeek;
      proto.isoWeekday = getSetISODayOfWeek;
      proto.dayOfYear = getSetDayOfYear;
      proto.hour = proto.hours = getSetHour;
      proto.minute = proto.minutes = getSetMinute;
      proto.second = proto.seconds = getSetSecond;
      proto.millisecond = proto.milliseconds = getSetMillisecond;
      proto.utcOffset = getSetOffset;
      proto.utc = setOffsetToUTC;
      proto.local = setOffsetToLocal;
      proto.parseZone = setOffsetToParsedOffset;
      proto.hasAlignedHourOffset = hasAlignedHourOffset;
      proto.isDST = isDaylightSavingTime;
      proto.isLocal = isLocal;
      proto.isUtcOffset = isUtcOffset;
      proto.isUtc = isUtc;
      proto.isUTC = isUtc;
      proto.zoneAbbr = getZoneAbbr;
      proto.zoneName = getZoneName;
      proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
      proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
      proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
      proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
      proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
  
      function createUnix(input) {
        return createLocal(input * 1000);
      }
  
      function createInZone() {
        return createLocal.apply(null, arguments).parseZone();
      }
  
      function preParsePostFormat(string) {
        return string;
      }
  
      var proto$1 = Locale.prototype;
      proto$1.calendar = calendar;
      proto$1.longDateFormat = longDateFormat;
      proto$1.invalidDate = invalidDate;
      proto$1.ordinal = ordinal;
      proto$1.preparse = preParsePostFormat;
      proto$1.postformat = preParsePostFormat;
      proto$1.relativeTime = relativeTime;
      proto$1.pastFuture = pastFuture;
      proto$1.set = set;
      proto$1.months = localeMonths;
      proto$1.monthsShort = localeMonthsShort;
      proto$1.monthsParse = localeMonthsParse;
      proto$1.monthsRegex = monthsRegex;
      proto$1.monthsShortRegex = monthsShortRegex;
      proto$1.week = localeWeek;
      proto$1.firstDayOfYear = localeFirstDayOfYear;
      proto$1.firstDayOfWeek = localeFirstDayOfWeek;
      proto$1.weekdays = localeWeekdays;
      proto$1.weekdaysMin = localeWeekdaysMin;
      proto$1.weekdaysShort = localeWeekdaysShort;
      proto$1.weekdaysParse = localeWeekdaysParse;
      proto$1.weekdaysRegex = weekdaysRegex;
      proto$1.weekdaysShortRegex = weekdaysShortRegex;
      proto$1.weekdaysMinRegex = weekdaysMinRegex;
      proto$1.isPM = localeIsPM;
      proto$1.meridiem = localeMeridiem;
  
      function get$1(format, index, field, setter) {
        var locale = getLocale();
        var utc = createUTC().set(setter, index);
        return locale[field](utc, format);
      }
  
      function listMonthsImpl(format, index, field) {
        if (isNumber(format)) {
          index = format;
          format = undefined;
        }
  
        format = format || '';
  
        if (index != null) {
          return get$1(format, index, field, 'month');
        }
  
        var i;
        var out = [];
  
        for (i = 0; i < 12; i++) {
          out[i] = get$1(format, i, field, 'month');
        }
  
        return out;
      } // ()
      // (5)
      // (fmt, 5)
      // (fmt)
      // (true)
      // (true, 5)
      // (true, fmt, 5)
      // (true, fmt)
  
  
      function listWeekdaysImpl(localeSorted, format, index, field) {
        if (typeof localeSorted === 'boolean') {
          if (isNumber(format)) {
            index = format;
            format = undefined;
          }
  
          format = format || '';
        } else {
          format = localeSorted;
          index = format;
          localeSorted = false;
  
          if (isNumber(format)) {
            index = format;
            format = undefined;
          }
  
          format = format || '';
        }
  
        var locale = getLocale(),
            shift = localeSorted ? locale._week.dow : 0;
  
        if (index != null) {
          return get$1(format, (index + shift) % 7, field, 'day');
        }
  
        var i;
        var out = [];
  
        for (i = 0; i < 7; i++) {
          out[i] = get$1(format, (i + shift) % 7, field, 'day');
        }
  
        return out;
      }
  
      function listMonths(format, index) {
        return listMonthsImpl(format, index, 'months');
      }
  
      function listMonthsShort(format, index) {
        return listMonthsImpl(format, index, 'monthsShort');
      }
  
      function listWeekdays(localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
      }
  
      function listWeekdaysShort(localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
      }
  
      function listWeekdaysMin(localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
      }
  
      getSetGlobalLocale('en', {
        dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
        ordinal: function (number) {
          var b = number % 10,
              output = toInt(number % 100 / 10) === 1 ? 'th' : b === 1 ? 'st' : b === 2 ? 'nd' : b === 3 ? 'rd' : 'th';
          return number + output;
        }
      }); // Side effect imports
  
      hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
      hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
      var mathAbs = Math.abs;
  
      function abs() {
        var data = this._data;
        this._milliseconds = mathAbs(this._milliseconds);
        this._days = mathAbs(this._days);
        this._months = mathAbs(this._months);
        data.milliseconds = mathAbs(data.milliseconds);
        data.seconds = mathAbs(data.seconds);
        data.minutes = mathAbs(data.minutes);
        data.hours = mathAbs(data.hours);
        data.months = mathAbs(data.months);
        data.years = mathAbs(data.years);
        return this;
      }
  
      function addSubtract$1(duration, input, value, direction) {
        var other = createDuration(input, value);
        duration._milliseconds += direction * other._milliseconds;
        duration._days += direction * other._days;
        duration._months += direction * other._months;
        return duration._bubble();
      } // supports only 2.0-style add(1, 's') or add(duration)
  
  
      function add$1(input, value) {
        return addSubtract$1(this, input, value, 1);
      } // supports only 2.0-style subtract(1, 's') or subtract(duration)
  
  
      function subtract$1(input, value) {
        return addSubtract$1(this, input, value, -1);
      }
  
      function absCeil(number) {
        if (number < 0) {
          return Math.floor(number);
        } else {
          return Math.ceil(number);
        }
      }
  
      function bubble() {
        var milliseconds = this._milliseconds;
        var days = this._days;
        var months = this._months;
        var data = this._data;
        var seconds, minutes, hours, years, monthsFromDays; // if we have a mix of positive and negative values, bubble down first
        // check: https://github.com/moment/moment/issues/2166
  
        if (!(milliseconds >= 0 && days >= 0 && months >= 0 || milliseconds <= 0 && days <= 0 && months <= 0)) {
          milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
          days = 0;
          months = 0;
        } // The following code bubbles up values, see the tests for
        // examples of what that means.
  
  
        data.milliseconds = milliseconds % 1000;
        seconds = absFloor(milliseconds / 1000);
        data.seconds = seconds % 60;
        minutes = absFloor(seconds / 60);
        data.minutes = minutes % 60;
        hours = absFloor(minutes / 60);
        data.hours = hours % 24;
        days += absFloor(hours / 24); // convert days to months
  
        monthsFromDays = absFloor(daysToMonths(days));
        months += monthsFromDays;
        days -= absCeil(monthsToDays(monthsFromDays)); // 12 months -> 1 year
  
        years = absFloor(months / 12);
        months %= 12;
        data.days = days;
        data.months = months;
        data.years = years;
        return this;
      }
  
      function daysToMonths(days) {
        // 400 years have 146097 days (taking into account leap year rules)
        // 400 years have 12 months === 4800
        return days * 4800 / 146097;
      }
  
      function monthsToDays(months) {
        // the reverse of daysToMonths
        return months * 146097 / 4800;
      }
  
      function as(units) {
        if (!this.isValid()) {
          return NaN;
        }
  
        var days;
        var months;
        var milliseconds = this._milliseconds;
        units = normalizeUnits(units);
  
        if (units === 'month' || units === 'quarter' || units === 'year') {
          days = this._days + milliseconds / 864e5;
          months = this._months + daysToMonths(days);
  
          switch (units) {
            case 'month':
              return months;
  
            case 'quarter':
              return months / 3;
  
            case 'year':
              return months / 12;
          }
        } else {
          // handle milliseconds separately because of floating point math errors (issue #1867)
          days = this._days + Math.round(monthsToDays(this._months));
  
          switch (units) {
            case 'week':
              return days / 7 + milliseconds / 6048e5;
  
            case 'day':
              return days + milliseconds / 864e5;
  
            case 'hour':
              return days * 24 + milliseconds / 36e5;
  
            case 'minute':
              return days * 1440 + milliseconds / 6e4;
  
            case 'second':
              return days * 86400 + milliseconds / 1000;
            // Math.floor prevents floating point math errors here
  
            case 'millisecond':
              return Math.floor(days * 864e5) + milliseconds;
  
            default:
              throw new Error('Unknown unit ' + units);
          }
        }
      } // TODO: Use this.as('ms')?
  
  
      function valueOf$1() {
        if (!this.isValid()) {
          return NaN;
        }
  
        return this._milliseconds + this._days * 864e5 + this._months % 12 * 2592e6 + toInt(this._months / 12) * 31536e6;
      }
  
      function makeAs(alias) {
        return function () {
          return this.as(alias);
        };
      }
  
      var asMilliseconds = makeAs('ms');
      var asSeconds = makeAs('s');
      var asMinutes = makeAs('m');
      var asHours = makeAs('h');
      var asDays = makeAs('d');
      var asWeeks = makeAs('w');
      var asMonths = makeAs('M');
      var asQuarters = makeAs('Q');
      var asYears = makeAs('y');
  
      function clone$1() {
        return createDuration(this);
      }
  
      function get$2(units) {
        units = normalizeUnits(units);
        return this.isValid() ? this[units + 's']() : NaN;
      }
  
      function makeGetter(name) {
        return function () {
          return this.isValid() ? this._data[name] : NaN;
        };
      }
  
      var milliseconds = makeGetter('milliseconds');
      var seconds = makeGetter('seconds');
      var minutes = makeGetter('minutes');
      var hours = makeGetter('hours');
      var days = makeGetter('days');
      var months = makeGetter('months');
      var years = makeGetter('years');
  
      function weeks() {
        return absFloor(this.days() / 7);
      }
  
      var round = Math.round;
      var thresholds = {
        ss: 44,
        // a few seconds to seconds
        s: 45,
        // seconds to minute
        m: 45,
        // minutes to hour
        h: 22,
        // hours to day
        d: 26,
        // days to month
        M: 11 // months to year
  
      }; // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
  
      function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
      }
  
      function relativeTime$1(posNegDuration, withoutSuffix, locale) {
        var duration = createDuration(posNegDuration).abs();
        var seconds = round(duration.as('s'));
        var minutes = round(duration.as('m'));
        var hours = round(duration.as('h'));
        var days = round(duration.as('d'));
        var months = round(duration.as('M'));
        var years = round(duration.as('y'));
        var a = seconds <= thresholds.ss && ['s', seconds] || seconds < thresholds.s && ['ss', seconds] || minutes <= 1 && ['m'] || minutes < thresholds.m && ['mm', minutes] || hours <= 1 && ['h'] || hours < thresholds.h && ['hh', hours] || days <= 1 && ['d'] || days < thresholds.d && ['dd', days] || months <= 1 && ['M'] || months < thresholds.M && ['MM', months] || years <= 1 && ['y'] || ['yy', years];
        a[2] = withoutSuffix;
        a[3] = +posNegDuration > 0;
        a[4] = locale;
        return substituteTimeAgo.apply(null, a);
      } // This function allows you to set the rounding function for relative time strings
  
  
      function getSetRelativeTimeRounding(roundingFunction) {
        if (roundingFunction === undefined) {
          return round;
        }
  
        if (typeof roundingFunction === 'function') {
          round = roundingFunction;
          return true;
        }
  
        return false;
      } // This function allows you to set a threshold for relative time strings
  
  
      function getSetRelativeTimeThreshold(threshold, limit) {
        if (thresholds[threshold] === undefined) {
          return false;
        }
  
        if (limit === undefined) {
          return thresholds[threshold];
        }
  
        thresholds[threshold] = limit;
  
        if (threshold === 's') {
          thresholds.ss = limit - 1;
        }
  
        return true;
      }
  
      function humanize(withSuffix) {
        if (!this.isValid()) {
          return this.localeData().invalidDate();
        }
  
        var locale = this.localeData();
        var output = relativeTime$1(this, !withSuffix, locale);
  
        if (withSuffix) {
          output = locale.pastFuture(+this, output);
        }
  
        return locale.postformat(output);
      }
  
      var abs$1 = Math.abs;
  
      function sign(x) {
        return (x > 0) - (x < 0) || +x;
      }
  
      function toISOString$1() {
        // for ISO strings we do not use the normal bubbling rules:
        //  * milliseconds bubble up until they become hours
        //  * days do not bubble at all
        //  * months bubble up until they become years
        // This is because there is no context-free conversion between hours and days
        // (think of clock changes)
        // and also not between days and months (28-31 days per month)
        if (!this.isValid()) {
          return this.localeData().invalidDate();
        }
  
        var seconds = abs$1(this._milliseconds) / 1000;
        var days = abs$1(this._days);
        var months = abs$1(this._months);
        var minutes, hours, years; // 3600 seconds -> 60 minutes -> 1 hour
  
        minutes = absFloor(seconds / 60);
        hours = absFloor(minutes / 60);
        seconds %= 60;
        minutes %= 60; // 12 months -> 1 year
  
        years = absFloor(months / 12);
        months %= 12; // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
  
        var Y = years;
        var M = months;
        var D = days;
        var h = hours;
        var m = minutes;
        var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
        var total = this.asSeconds();
  
        if (!total) {
          // this is the same as C#'s (Noda) and python (isodate)...
          // but not other JS (goog.date)
          return 'P0D';
        }
  
        var totalSign = total < 0 ? '-' : '';
        var ymSign = sign(this._months) !== sign(total) ? '-' : '';
        var daysSign = sign(this._days) !== sign(total) ? '-' : '';
        var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
        return totalSign + 'P' + (Y ? ymSign + Y + 'Y' : '') + (M ? ymSign + M + 'M' : '') + (D ? daysSign + D + 'D' : '') + (h || m || s ? 'T' : '') + (h ? hmsSign + h + 'H' : '') + (m ? hmsSign + m + 'M' : '') + (s ? hmsSign + s + 'S' : '');
      }
  
      var proto$2 = Duration.prototype;
      proto$2.isValid = isValid$1;
      proto$2.abs = abs;
      proto$2.add = add$1;
      proto$2.subtract = subtract$1;
      proto$2.as = as;
      proto$2.asMilliseconds = asMilliseconds;
      proto$2.asSeconds = asSeconds;
      proto$2.asMinutes = asMinutes;
      proto$2.asHours = asHours;
      proto$2.asDays = asDays;
      proto$2.asWeeks = asWeeks;
      proto$2.asMonths = asMonths;
      proto$2.asQuarters = asQuarters;
      proto$2.asYears = asYears;
      proto$2.valueOf = valueOf$1;
      proto$2._bubble = bubble;
      proto$2.clone = clone$1;
      proto$2.get = get$2;
      proto$2.milliseconds = milliseconds;
      proto$2.seconds = seconds;
      proto$2.minutes = minutes;
      proto$2.hours = hours;
      proto$2.days = days;
      proto$2.weeks = weeks;
      proto$2.months = months;
      proto$2.years = years;
      proto$2.humanize = humanize;
      proto$2.toISOString = toISOString$1;
      proto$2.toString = toISOString$1;
      proto$2.toJSON = toISOString$1;
      proto$2.locale = locale;
      proto$2.localeData = localeData;
      proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
      proto$2.lang = lang; // Side effect imports
      // FORMATTING
  
      addFormatToken('X', 0, 0, 'unix');
      addFormatToken('x', 0, 0, 'valueOf'); // PARSING
  
      addRegexToken('x', matchSigned);
      addRegexToken('X', matchTimestamp);
      addParseToken('X', function (input, array, config) {
        config._d = new Date(parseFloat(input, 10) * 1000);
      });
      addParseToken('x', function (input, array, config) {
        config._d = new Date(toInt(input));
      }); // Side effect imports
  
      hooks.version = '2.24.0';
      setHookCallback(createLocal);
      hooks.fn = proto;
      hooks.min = min;
      hooks.max = max;
      hooks.now = now;
      hooks.utc = createUTC;
      hooks.unix = createUnix;
      hooks.months = listMonths;
      hooks.isDate = isDate;
      hooks.locale = getSetGlobalLocale;
      hooks.invalid = createInvalid;
      hooks.duration = createDuration;
      hooks.isMoment = isMoment;
      hooks.weekdays = listWeekdays;
      hooks.parseZone = createInZone;
      hooks.localeData = getLocale;
      hooks.isDuration = isDuration;
      hooks.monthsShort = listMonthsShort;
      hooks.weekdaysMin = listWeekdaysMin;
      hooks.defineLocale = defineLocale;
      hooks.updateLocale = updateLocale;
      hooks.locales = listLocales;
      hooks.weekdaysShort = listWeekdaysShort;
      hooks.normalizeUnits = normalizeUnits;
      hooks.relativeTimeRounding = getSetRelativeTimeRounding;
      hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
      hooks.calendarFormat = getCalendarFormat;
      hooks.prototype = proto; // currently HTML5 input type only supports 24-hour formats
  
      hooks.HTML5_FMT = {
        DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',
        // <input type="datetime-local" />
        DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',
        // <input type="datetime-local" step="1" />
        DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',
        // <input type="datetime-local" step="0.001" />
        DATE: 'YYYY-MM-DD',
        // <input type="date" />
        TIME: 'HH:mm',
        // <input type="time" />
        TIME_SECONDS: 'HH:mm:ss',
        // <input type="time" step="1" />
        TIME_MS: 'HH:mm:ss.SSS',
        // <input type="time" step="0.001" />
        WEEK: 'GGGG-[W]WW',
        // <input type="week" />
        MONTH: 'YYYY-MM' // <input type="month" />
  
      };
      return hooks;
    });
  }); // Maps for number <-> hex string conversion
  
  var byteToHex$2 = [];
  
  for (var i$2 = 0; i$2 < 256; i$2++) {
    byteToHex$2[i$2] = (i$2 + 0x100).toString(16).substr(1);
  }
  /**
   * Generate 16 random bytes to be used as a base for UUID.
   *
   * @ignore
   */
  
  
  var random$1 = function () {
    if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
      // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
      // Moderately fast, high quality
      var _rnds8 = new Uint8Array(16);
  
      return function whatwgRNG() {
        crypto.getRandomValues(_rnds8);
        return _rnds8;
      };
    } // Math.random()-based (RNG)
    //
    // If all else fails, use Math.random().
    // It's fast, but is of unspecified quality.
  
  
    var _rnds = new Array(16);
  
    return function () {
      for (var i = 0, r; i < 16; i++) {
        if ((i & 0x03) === 0) {
          r = Math.random() * 0x100000000;
        }
  
        _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
      }
  
      return _rnds;
    }; //     uuid.js
    //
    //     Copyright (c) 2010-2012 Robert Kieffer
    //     MIT License - http://opensource.org/licenses/mit-license.php
    // Unique ID creation requires a high quality random # generator.  We feature
    // detect to determine the best RNG source, normalizing to a function that
    // returns 128-bits of randomness, since that's what's usually required
    // return require('./rng');
  }();
  
  var byteToHex$1$1 = [];
  
  for (var i$1$1 = 0; i$1$1 < 256; i$1$1++) {
    byteToHex$1$1[i$1$1] = (i$1$1 + 0x100).toString(16).substr(1);
  } // **`v1()` - Generate time-based UUID**
  //
  // Inspired by https://github.com/LiosK/UUID.js
  // and http://docs.python.org/library/uuid.html
  // random #'s we need to init node and clockseq
  
  
  var seedBytes$1 = random$1(); // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
  
  var defaultNodeId$1 = [seedBytes$1[0] | 0x01, seedBytes$1[1], seedBytes$1[2], seedBytes$1[3], seedBytes$1[4], seedBytes$1[5]]; // Per 4.2.2, randomize (14 bit) clockseq
  
  var defaultClockseq$1 = (seedBytes$1[6] << 8 | seedBytes$1[7]) & 0x3fff; // Previous uuid creation time
  // for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
  // code from http://momentjs.com/
  
  
  var ASPDateRegex = /^\/?Date\((-?\d+)/i; // Hex color
  /**
   * Hue, Saturation, Value.
   */
  
  /**
   * Test whether given object is a number
   *
   * @param value - Input value of unknown type.
   *
   * @returns True if number, false otherwise.
   */
  
  function isNumber(value) {
    return value instanceof Number || typeof value === 'number';
  }
  /**
   * Test whether given object is a string
   *
   * @param value - Input value of unknown type.
   *
   * @returns True if string, false otherwise.
   */
  
  
  function isString(value) {
    return value instanceof String || typeof value === 'string';
  }
  /**
   * Test whether given object is a Moment date.
   * @TODO: This is basically a workaround, if Moment was imported property it wouldn't necessary as moment.isMoment is a TS type guard.
   *
   * @param value - Input value of unknown type.
   *
   * @returns True if Moment instance, false otherwise.
   */
  
  
  function isMoment(value) {
    return moment.isMoment(value);
  }
  /**
   * Copy property from b to a if property present in a.
   * If property in b explicitly set to null, delete it if `allowDeletion` set.
   *
   * Internal helper routine, should not be exported. Not added to `exports` for that reason.
   *
   * @param a - Target object.
   * @param b - Source object.
   * @param prop - Name of property to copy from b to a.
   * @param allowDeletion  if true, delete property in a if explicitly set to null in b
   */
  
  
  function copyOrDelete(a, b, prop, allowDeletion) {
    var doDeletion = false;
  
    if (allowDeletion === true) {
      doDeletion = b[prop] === null && a[prop] !== undefined;
    }
  
    if (doDeletion) {
      delete a[prop];
    } else {
      a[prop] = b[prop]; // Remember, this is a reference copy!
    }
  }
  /**
   * Deep extend an object a with the properties of object b
   *
   * @param a - Target object.
   * @param b - Source object.
   * @param protoExtend - If true, the prototype values will also be extended
   * (ie. the options objects that inherit from others will also get the inherited options).
   * @param allowDeletion - If true, the values of fields that are null will be deleted.
   *
   * @returns Argument a.
   */
  
  
  function deepExtend(a, b) {
    var protoExtend = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
    var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
  
    for (var prop in b) {
      if (Object.prototype.hasOwnProperty.call(b, prop) || protoExtend === true) {
        if (b[prop] && b[prop].constructor === Object) {
          if (a[prop] === undefined) {
            a[prop] = {};
          }
  
          if (a[prop].constructor === Object) {
            deepExtend(a[prop], b[prop], protoExtend); // NOTE: allowDeletion not propagated!
          } else {
            copyOrDelete(a, b, prop, allowDeletion);
          }
        } else if (Array.isArray(b[prop])) {
          a[prop] = [];
  
          for (var i = 0; i < b[prop].length; i++) {
            a[prop].push(b[prop][i]);
          }
        } else {
          copyOrDelete(a, b, prop, allowDeletion);
        }
      }
    }
  
    return a;
  }
  /**
   * Convert an object into another type
   *
   * @param object - Value of unknown type.
   * @param type - Name of the desired type.
   *
   * @returns Object in the desired type.
   * @throws Error
   */
  
  
  function convert(object, type) {
    var match;
  
    if (object === undefined) {
      return undefined;
    }
  
    if (object === null) {
      return null;
    }
  
    if (!type) {
      return object;
    }
  
    if (!(typeof type === 'string') && !(type instanceof String)) {
      throw new Error('Type must be a string');
    } //noinspection FallthroughInSwitchStatementJS
  
  
    switch (type) {
      case 'boolean':
      case 'Boolean':
        return Boolean(object);
  
      case 'number':
      case 'Number':
        if (isString(object) && !isNaN(Date.parse(object))) {
          return moment(object).valueOf();
        } else {
          // @TODO: I don't think that Number and String constructors are a good idea.
          // This could also fail if the object doesn't have valueOf method or if it's redefined.
          // For example: Object.create(null) or { valueOf: 7 }.
          return Number(object.valueOf());
        }
  
      case 'string':
      case 'String':
        return String(object);
  
      case 'Date':
        if (isNumber(object)) {
          return new Date(object);
        }
  
        if (object instanceof Date) {
          return new Date(object.valueOf());
        } else if (isMoment(object)) {
          return new Date(object.valueOf());
        }
  
        if (isString(object)) {
          match = ASPDateRegex.exec(object);
  
          if (match) {
            // object is an ASP date
            return new Date(Number(match[1])); // parse number
          } else {
            return moment(new Date(object)).toDate(); // parse string
          }
        } else {
          throw new Error('Cannot convert object of type ' + getType(object) + ' to type Date');
        }
  
      case 'Moment':
        if (isNumber(object)) {
          return moment(object);
        }
  
        if (object instanceof Date) {
          return moment(object.valueOf());
        } else if (isMoment(object)) {
          return moment(object);
        }
  
        if (isString(object)) {
          match = ASPDateRegex.exec(object);
  
          if (match) {
            // object is an ASP date
            return moment(Number(match[1])); // parse number
          } else {
            return moment(object); // parse string
          }
        } else {
          throw new Error('Cannot convert object of type ' + getType(object) + ' to type Date');
        }
  
      case 'ISODate':
        if (isNumber(object)) {
          return new Date(object);
        } else if (object instanceof Date) {
          return object.toISOString();
        } else if (isMoment(object)) {
          return object.toDate().toISOString();
        } else if (isString(object)) {
          match = ASPDateRegex.exec(object);
  
          if (match) {
            // object is an ASP date
            return new Date(Number(match[1])).toISOString(); // parse number
          } else {
            return moment(object).format(); // ISO 8601
          }
        } else {
          throw new Error('Cannot convert object of type ' + getType(object) + ' to type ISODate');
        }
  
      case 'ASPDate':
        if (isNumber(object)) {
          return '/Date(' + object + ')/';
        } else if (object instanceof Date) {
          return '/Date(' + object.valueOf() + ')/';
        } else if (isString(object)) {
          match = ASPDateRegex.exec(object);
  
          var _value;
  
          if (match) {
            // object is an ASP date
            _value = new Date(Number(match[1])).valueOf(); // parse number
          } else {
            _value = new Date(object).valueOf(); // parse string
          }
  
          return '/Date(' + _value + ')/';
        } else {
          throw new Error('Cannot convert object of type ' + getType(object) + ' to type ASPDate');
        }
  
      default:
        var never = type;
        throw new Error("Unknown type ".concat(never));
    }
  }
  /**
   * Get the type of an object, for example exports.getType([]) returns 'Array'
   *
   * @param object - Input value of unknown type.
   *
   * @returns Detected type.
   */
  
  
  function getType(object) {
    var type = _typeof(object);
  
    if (type === 'object') {
      if (object === null) {
        return 'null';
      }
  
      if (object instanceof Boolean) {
        return 'Boolean';
      }
  
      if (object instanceof Number) {
        return 'Number';
      }
  
      if (object instanceof String) {
        return 'String';
      }
  
      if (Array.isArray(object)) {
        return 'Array';
      }
  
      if (object instanceof Date) {
        return 'Date';
      }
  
      return 'Object';
    }
  
    if (type === 'number') {
      return 'Number';
    }
  
    if (type === 'boolean') {
      return 'Boolean';
    }
  
    if (type === 'string') {
      return 'String';
    }
  
    if (type === undefined) {
      return 'undefined';
    }
  
    return type;
  }
  
  /**
   * Determine whether a value can be used as an id.
   *
   * @param value - Input value of unknown type.
   *
   * @returns True if the value is valid id, false otherwise.
   */
  function isId(value) {
    return typeof value === "string" || typeof value === "number";
  }
  
  /* eslint @typescript-eslint/member-ordering: ["error", { "classes": ["field", "constructor", "method"] }] */
  
  /**
   * A queue.
   *
   * @typeParam T - The type of method names to be replaced by queued versions.
   */
  var Queue =
  /*#__PURE__*/
  function () {
    /**
     * Construct a new Queue.
     *
     * @param options - Queue configuration.
     */
    function Queue(options) {
      classCallCheck(this, Queue);
  
      this._queue = [];
      this._timeout = null;
      this._extended = null; // options
  
      this.delay = null;
      this.max = Infinity;
      this.setOptions(options);
    }
    /**
     * Update the configuration of the queue.
     *
     * @param options - Queue configuration.
     */
  
  
    createClass(Queue, [{
      key: "setOptions",
      value: function setOptions(options) {
        if (options && typeof options.delay !== "undefined") {
          this.delay = options.delay;
        }
  
        if (options && typeof options.max !== "undefined") {
          this.max = options.max;
        }
  
        this._flushIfNeeded();
      }
      /**
       * Extend an object with queuing functionality.
       * The object will be extended with a function flush, and the methods provided in options.replace will be replaced with queued ones.
       *
       * @param object - The object to be extended.
       * @param options - Additional options.
       *
       * @returns The created queue.
       */
  
    }, {
      key: "destroy",
  
      /**
       * Destroy the queue. The queue will first flush all queued actions, and in case it has extended an object, will restore the original object.
       */
      value: function destroy() {
        this.flush();
  
        if (this._extended) {
          var object = this._extended.object;
          var methods = this._extended.methods;
  
          for (var i = 0; i < methods.length; i++) {
            var method = methods[i];
  
            if (method.original) {
              // @TODO: better solution?
              object[method.name] = method.original;
            } else {
              // @TODO: better solution?
              delete object[method.name];
            }
          }
  
          this._extended = null;
        }
      }
      /**
       * Replace a method on an object with a queued version.
       *
       * @param object - Object having the method.
       * @param method - The method name.
       */
  
    }, {
      key: "replace",
      value: function replace(object, method) {
        /* eslint-disable-next-line @typescript-eslint/no-this-alias */
        var me = this;
        var original = object[method];
  
        if (!original) {
          throw new Error("Method " + method + " undefined");
        }
  
        object[method] = function () {
          for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
            args[_key] = arguments[_key];
          }
  
          // add this call to the queue
          me.queue({
            args: args,
            fn: original,
            context: this
          });
        };
      }
      /**
       * Queue a call.
       *
       * @param entry - The function or entry to be queued.
       */
  
    }, {
      key: "queue",
      value: function queue(entry) {
        if (typeof entry === "function") {
          this._queue.push({
            fn: entry
          });
        } else {
          this._queue.push(entry);
        }
  
        this._flushIfNeeded();
      }
      /**
       * Check whether the queue needs to be flushed.
       */
  
    }, {
      key: "_flushIfNeeded",
      value: function _flushIfNeeded() {
        var _this = this;
  
        // flush when the maximum is exceeded.
        if (this._queue.length > this.max) {
          this.flush();
        } // flush after a period of inactivity when a delay is configured
  
  
        if (this._timeout != null) {
          clearTimeout(this._timeout);
          this._timeout = null;
        }
  
        if (this.queue.length > 0 && typeof this.delay === "number") {
          this._timeout = setTimeout(function () {
            _this.flush();
          }, this.delay);
        }
      }
      /**
       * Flush all queued calls
       */
  
    }, {
      key: "flush",
      value: function flush() {
        this._queue.splice(0).forEach(function (entry) {
          entry.fn.apply(entry.context || entry.fn, entry.args || []);
        });
      }
    }], [{
      key: "extend",
      value: function extend(object, options) {
        var queue = new Queue(options);
  
        if (object.flush !== undefined) {
          throw new Error("Target object already has a property flush");
        }
  
        object.flush = function () {
          queue.flush();
        };
  
        var methods = [{
          name: "flush",
          original: undefined
        }];
  
        if (options && options.replace) {
          for (var i = 0; i < options.replace.length; i++) {
            var name = options.replace[i];
            methods.push({
              name: name,
              // @TODO: better solution?
              original: object[name]
            }); // @TODO: better solution?
  
            queue.replace(object, name);
          }
        }
  
        queue._extended = {
          object: object,
          methods: methods
        };
        return queue;
      }
    }]);
  
    return Queue;
  }();
  
  /* eslint-disable @typescript-eslint/member-ordering */
  
  /**
   * [[DataSet]] code that can be reused in [[DataView]] or other similar implementations of [[DataInterface]].
   *
   * @typeParam Item - Item type that may or may not have an id.
   * @typeParam IdProp - Name of the property that contains the id.
   */
  var DataSetPart =
  /*#__PURE__*/
  function () {
    function DataSetPart() {
      classCallCheck(this, DataSetPart);
  
      this._subscribers = {
        "*": [],
        add: [],
        remove: [],
        update: []
      };
      /**
       * @deprecated Use on instead (PS: DataView.subscribe === DataView.on).
       */
  
      this.subscribe = DataSetPart.prototype.on;
      /**
       * @deprecated Use off instead (PS: DataView.unsubscribe === DataView.off).
       */
  
      this.unsubscribe = DataSetPart.prototype.off;
    }
    /**
     * Trigger an event
     *
     * @param event - Event name.
     * @param payload - Event payload.
     * @param senderId - Id of the sender.
     */
  
  
    createClass(DataSetPart, [{
      key: "_trigger",
      value: function _trigger(event, payload, senderId) {
        if (event === "*") {
          throw new Error("Cannot trigger event *");
        }
  
        [].concat(toConsumableArray(this._subscribers[event]), toConsumableArray(this._subscribers["*"])).forEach(function (subscriber) {
          subscriber(event, payload, senderId != null ? senderId : null);
        });
      }
      /**
       * Subscribe to an event, add an event listener.
       *
       * @remarks Non-function callbacks are ignored.
       *
       * @param event - Event name.
       * @param callback - Callback method.
       */
  
    }, {
      key: "on",
      value: function on(event, callback) {
        if (typeof callback === "function") {
          this._subscribers[event].push(callback);
        } // @TODO: Maybe throw for invalid callbacks?
  
      }
      /**
       * Unsubscribe from an event, remove an event listener.
       *
       * @remarks If the same callback was subscribed more than once **all** occurences will be removed.
       *
       * @param event - Event name.
       * @param callback - Callback method.
       */
  
    }, {
      key: "off",
      value: function off(event, callback) {
        this._subscribers[event] = this._subscribers[event].filter(function (subscriber) {
          return subscriber !== callback;
        });
      }
    }]);
  
    return DataSetPart;
  }();
  
  function _arrayWithHoles(arr) {
    if (Array.isArray(arr)) return arr;
  }
  
  var arrayWithHoles = _arrayWithHoles;
  
  function _iterableToArrayLimit(arr, i) {
    var _arr = [];
    var _n = true;
    var _d = false;
    var _e = undefined;
  
    try {
      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);
  
        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"] != null) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }
  
    return _arr;
  }
  
  var iterableToArrayLimit = _iterableToArrayLimit;
  
  function _nonIterableRest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance");
  }
  
  var nonIterableRest = _nonIterableRest;
  
  function _slicedToArray(arr, i) {
    return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest();
  }
  
  var slicedToArray = _slicedToArray;
  
  /**
   * Data stream
   *
   * @remarks
   * [[DataStream]] offers an always up to date stream of items from a [[DataSet]] or [[DataView]].
   * That means that the stream is evaluated at the time of iteration, conversion to another data type or when [[cache]] is called, not when the [[DataStream]] was created.
   * Multiple invocations of for example [[toItemArray]] may yield different results (if the data source like for example [[DataSet]] gets modified).
   *
   * @typeparam Item - The item type this stream is going to work with.
   */
  var DataStream =
  /*#__PURE__*/
  function () {
    /**
     * Create a new data stream.
     *
     * @param _pairs - The id, item pairs.
     */
    function DataStream(_pairs) {
      classCallCheck(this, DataStream);
  
      this._pairs = _pairs;
    }
    /**
     * Return an iterable of key, value pairs for every entry in the stream.
     */
  
  
    createClass(DataStream, [{
      key: Symbol.iterator,
      value:
      /*#__PURE__*/
      regenerator.mark(function value() {
        var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step$value, id, item;
  
        return regenerator.wrap(function value$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                _iteratorNormalCompletion = true;
                _didIteratorError = false;
                _iteratorError = undefined;
                _context.prev = 3;
                _iterator = this._pairs[Symbol.iterator]();
  
              case 5:
                if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
                  _context.next = 12;
                  break;
                }
  
                _step$value = slicedToArray(_step.value, 2), id = _step$value[0], item = _step$value[1];
                _context.next = 9;
                return [id, item];
  
              case 9:
                _iteratorNormalCompletion = true;
                _context.next = 5;
                break;
  
              case 12:
                _context.next = 18;
                break;
  
              case 14:
                _context.prev = 14;
                _context.t0 = _context["catch"](3);
                _didIteratorError = true;
                _iteratorError = _context.t0;
  
              case 18:
                _context.prev = 18;
                _context.prev = 19;
  
                if (!_iteratorNormalCompletion && _iterator.return != null) {
                  _iterator.return();
                }
  
              case 21:
                _context.prev = 21;
  
                if (!_didIteratorError) {
                  _context.next = 24;
                  break;
                }
  
                throw _iteratorError;
  
              case 24:
                return _context.finish(21);
  
              case 25:
                return _context.finish(18);
  
              case 26:
              case "end":
                return _context.stop();
            }
          }
        }, value, this, [[3, 14, 18, 26], [19,, 21, 25]]);
      })
      /**
       * Return an iterable of key, value pairs for every entry in the stream.
       */
  
    }, {
      key: "entries",
      value:
      /*#__PURE__*/
      regenerator.mark(function entries() {
        var _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, _step2$value, id, item;
  
        return regenerator.wrap(function entries$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                _iteratorNormalCompletion2 = true;
                _didIteratorError2 = false;
                _iteratorError2 = undefined;
                _context2.prev = 3;
                _iterator2 = this._pairs[Symbol.iterator]();
  
              case 5:
                if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
                  _context2.next = 12;
                  break;
                }
  
                _step2$value = slicedToArray(_step2.value, 2), id = _step2$value[0], item = _step2$value[1];
                _context2.next = 9;
                return [id, item];
  
              case 9:
                _iteratorNormalCompletion2 = true;
                _context2.next = 5;
                break;
  
              case 12:
                _context2.next = 18;
                break;
  
              case 14:
                _context2.prev = 14;
                _context2.t0 = _context2["catch"](3);
                _didIteratorError2 = true;
                _iteratorError2 = _context2.t0;
  
              case 18:
                _context2.prev = 18;
                _context2.prev = 19;
  
                if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
                  _iterator2.return();
                }
  
              case 21:
                _context2.prev = 21;
  
                if (!_didIteratorError2) {
                  _context2.next = 24;
                  break;
                }
  
                throw _iteratorError2;
  
              case 24:
                return _context2.finish(21);
  
              case 25:
                return _context2.finish(18);
  
              case 26:
              case "end":
                return _context2.stop();
            }
          }
        }, entries, this, [[3, 14, 18, 26], [19,, 21, 25]]);
      })
      /**
       * Return an iterable of keys in the stream.
       */
  
    }, {
      key: "keys",
      value:
      /*#__PURE__*/
      regenerator.mark(function keys() {
        var _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, _step3$value, id;
  
        return regenerator.wrap(function keys$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                _iteratorNormalCompletion3 = true;
                _didIteratorError3 = false;
                _iteratorError3 = undefined;
                _context3.prev = 3;
                _iterator3 = this._pairs[Symbol.iterator]();
  
              case 5:
                if (_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done) {
                  _context3.next = 12;
                  break;
                }
  
                _step3$value = slicedToArray(_step3.value, 1), id = _step3$value[0];
                _context3.next = 9;
                return id;
  
              case 9:
                _iteratorNormalCompletion3 = true;
                _context3.next = 5;
                break;
  
              case 12:
                _context3.next = 18;
                break;
  
              case 14:
                _context3.prev = 14;
                _context3.t0 = _context3["catch"](3);
                _didIteratorError3 = true;
                _iteratorError3 = _context3.t0;
  
              case 18:
                _context3.prev = 18;
                _context3.prev = 19;
  
                if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
                  _iterator3.return();
                }
  
              case 21:
                _context3.prev = 21;
  
                if (!_didIteratorError3) {
                  _context3.next = 24;
                  break;
                }
  
                throw _iteratorError3;
  
              case 24:
                return _context3.finish(21);
  
              case 25:
                return _context3.finish(18);
  
              case 26:
              case "end":
                return _context3.stop();
            }
          }
        }, keys, this, [[3, 14, 18, 26], [19,, 21, 25]]);
      })
      /**
       * Return an iterable of values in the stream.
       */
  
    }, {
      key: "values",
      value:
      /*#__PURE__*/
      regenerator.mark(function values() {
        var _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, _step4$value, item;
  
        return regenerator.wrap(function values$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                _iteratorNormalCompletion4 = true;
                _didIteratorError4 = false;
                _iteratorError4 = undefined;
                _context4.prev = 3;
                _iterator4 = this._pairs[Symbol.iterator]();
  
              case 5:
                if (_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done) {
                  _context4.next = 12;
                  break;
                }
  
                _step4$value = slicedToArray(_step4.value, 2), item = _step4$value[1];
                _context4.next = 9;
                return item;
  
              case 9:
                _iteratorNormalCompletion4 = true;
                _context4.next = 5;
                break;
  
              case 12:
                _context4.next = 18;
                break;
  
              case 14:
                _context4.prev = 14;
                _context4.t0 = _context4["catch"](3);
                _didIteratorError4 = true;
                _iteratorError4 = _context4.t0;
  
              case 18:
                _context4.prev = 18;
                _context4.prev = 19;
  
                if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
                  _iterator4.return();
                }
  
              case 21:
                _context4.prev = 21;
  
                if (!_didIteratorError4) {
                  _context4.next = 24;
                  break;
                }
  
                throw _iteratorError4;
  
              case 24:
                return _context4.finish(21);
  
              case 25:
                return _context4.finish(18);
  
              case 26:
              case "end":
                return _context4.stop();
            }
          }
        }, values, this, [[3, 14, 18, 26], [19,, 21, 25]]);
      })
      /**
       * Return an array containing all the ids in this stream.
       *
       * @remarks
       * The array may contain duplicities.
       *
       * @returns The array with all ids from this stream.
       */
  
    }, {
      key: "toIdArray",
      value: function toIdArray() {
        return toConsumableArray(this._pairs).map(function (pair) {
          return pair[0];
        });
      }
      /**
       * Return an array containing all the items in this stream.
       *
       * @remarks
       * The array may contain duplicities.
       *
       * @returns The array with all items from this stream.
       */
  
    }, {
      key: "toItemArray",
      value: function toItemArray() {
        return toConsumableArray(this._pairs).map(function (pair) {
          return pair[1];
        });
      }
      /**
       * Return an array containing all the entries in this stream.
       *
       * @remarks
       * The array may contain duplicities.
       *
       * @returns The array with all entries from this stream.
       */
  
    }, {
      key: "toEntryArray",
      value: function toEntryArray() {
        return toConsumableArray(this._pairs);
      }
      /**
       * Return an object map containing all the items in this stream accessible by ids.
       *
       * @remarks
       * In case of duplicate ids (coerced to string so `7 == '7'`) the last encoutered appears in the returned object.
       *
       * @returns The object map of all id → item pairs from this stream.
       */
  
    }, {
      key: "toObjectMap",
      value: function toObjectMap() {
        var map = Object.create(null);
        var _iteratorNormalCompletion5 = true;
        var _didIteratorError5 = false;
        var _iteratorError5 = undefined;
  
        try {
          for (var _iterator5 = this._pairs[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
            var _step5$value = slicedToArray(_step5.value, 2),
                id = _step5$value[0],
                item = _step5$value[1];
  
            map[id] = item;
          }
        } catch (err) {
          _didIteratorError5 = true;
          _iteratorError5 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
              _iterator5.return();
            }
          } finally {
            if (_didIteratorError5) {
              throw _iteratorError5;
            }
          }
        }
  
        return map;
      }
      /**
       * Return a map containing all the items in this stream accessible by ids.
       *
       * @returns The map of all id → item pairs from this stream.
       */
  
    }, {
      key: "toMap",
      value: function toMap() {
        return new Map(this._pairs);
      }
      /**
       * Return a set containing all the (unique) ids in this stream.
       *
       * @returns The set of all ids from this stream.
       */
  
    }, {
      key: "toIdSet",
      value: function toIdSet() {
        return new Set(this.toIdArray());
      }
      /**
       * Return a set containing all the (unique) items in this stream.
       *
       * @returns The set of all items from this stream.
       */
  
    }, {
      key: "toItemSet",
      value: function toItemSet() {
        return new Set(this.toItemArray());
      }
      /**
       * Cache the items from this stream.
       *
       * @remarks
       * This method allows for items to be fetched immediatelly and used (possibly multiple times) later.
       * It can also be used to optimize performance as [[DataStream]] would otherwise reevaluate everything upon each iteration.
       *
       * ## Example
       * ```javascript
       * const ds = new DataSet([…])
       *
       * const cachedStream = ds.stream()
       *   .filter(…)
       *   .sort(…)
       *   .map(…)
       *   .cached(…) // Data are fetched, processed and cached here.
       *
       * ds.clear()
       * chachedStream // Still has all the items.
       * ```
       *
       * @returns A new [[DataStream]] with cached items (detached from the original [[DataSet]]).
       */
  
    }, {
      key: "cache",
      value: function cache() {
        return new DataStream(toConsumableArray(this._pairs));
      }
      /**
       * Get the distinct values of given property.
       *
       * @param callback - The function that picks and possibly converts the property.
       *
       * @typeparam T - The type of the distinct value.
       *
       * @returns A set of all distinct properties.
       */
  
    }, {
      key: "distinct",
      value: function distinct(callback) {
        var set = new Set();
        var _iteratorNormalCompletion6 = true;
        var _didIteratorError6 = false;
        var _iteratorError6 = undefined;
  
        try {
          for (var _iterator6 = this._pairs[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
            var _step6$value = slicedToArray(_step6.value, 2),
                id = _step6$value[0],
                item = _step6$value[1];
  
            set.add(callback(item, id));
          }
        } catch (err) {
          _didIteratorError6 = true;
          _iteratorError6 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
              _iterator6.return();
            }
          } finally {
            if (_didIteratorError6) {
              throw _iteratorError6;
            }
          }
        }
  
        return set;
      }
      /**
       * Filter the items of the stream.
       *
       * @param callback - The function that decides whether an item will be included.
       *
       * @returns A new data stream with the filtered items.
       */
  
    }, {
      key: "filter",
      value: function filter(callback) {
        var pairs = this._pairs;
        return new DataStream(defineProperty({}, Symbol.iterator,
        /*#__PURE__*/
        regenerator.mark(function _callee() {
          var _iteratorNormalCompletion7, _didIteratorError7, _iteratorError7, _iterator7, _step7, _step7$value, id, item;
  
          return regenerator.wrap(function _callee$(_context5) {
            while (1) {
              switch (_context5.prev = _context5.next) {
                case 0:
                  _iteratorNormalCompletion7 = true;
                  _didIteratorError7 = false;
                  _iteratorError7 = undefined;
                  _context5.prev = 3;
                  _iterator7 = pairs[Symbol.iterator]();
  
                case 5:
                  if (_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done) {
                    _context5.next = 13;
                    break;
                  }
  
                  _step7$value = slicedToArray(_step7.value, 2), id = _step7$value[0], item = _step7$value[1];
  
                  if (!callback(item, id)) {
                    _context5.next = 10;
                    break;
                  }
  
                  _context5.next = 10;
                  return [id, item];
  
                case 10:
                  _iteratorNormalCompletion7 = true;
                  _context5.next = 5;
                  break;
  
                case 13:
                  _context5.next = 19;
                  break;
  
                case 15:
                  _context5.prev = 15;
                  _context5.t0 = _context5["catch"](3);
                  _didIteratorError7 = true;
                  _iteratorError7 = _context5.t0;
  
                case 19:
                  _context5.prev = 19;
                  _context5.prev = 20;
  
                  if (!_iteratorNormalCompletion7 && _iterator7.return != null) {
                    _iterator7.return();
                  }
  
                case 22:
                  _context5.prev = 22;
  
                  if (!_didIteratorError7) {
                    _context5.next = 25;
                    break;
                  }
  
                  throw _iteratorError7;
  
                case 25:
                  return _context5.finish(22);
  
                case 26:
                  return _context5.finish(19);
  
                case 27:
                case "end":
                  return _context5.stop();
              }
            }
          }, _callee, null, [[3, 15, 19, 27], [20,, 22, 26]]);
        })));
      }
      /**
       * Execute a callback for each item of the stream.
       *
       * @param callback - The function that will be invoked for each item.
       */
  
    }, {
      key: "forEach",
      value: function forEach(callback) {
        var _iteratorNormalCompletion8 = true;
        var _didIteratorError8 = false;
        var _iteratorError8 = undefined;
  
        try {
          for (var _iterator8 = this._pairs[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
            var _step8$value = slicedToArray(_step8.value, 2),
                id = _step8$value[0],
                item = _step8$value[1];
  
            callback(item, id);
          }
        } catch (err) {
          _didIteratorError8 = true;
          _iteratorError8 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion8 && _iterator8.return != null) {
              _iterator8.return();
            }
          } finally {
            if (_didIteratorError8) {
              throw _iteratorError8;
            }
          }
        }
      }
      /**
       * Map the items into a different type.
       *
       * @param callback - The function that does the conversion.
       *
       * @typeparam Mapped - The type of the item after mapping.
       *
       * @returns A new data stream with the mapped items.
       */
  
    }, {
      key: "map",
      value: function map(callback) {
        var pairs = this._pairs;
        return new DataStream(defineProperty({}, Symbol.iterator,
        /*#__PURE__*/
        regenerator.mark(function _callee2() {
          var _iteratorNormalCompletion9, _didIteratorError9, _iteratorError9, _iterator9, _step9, _step9$value, id, item;
  
          return regenerator.wrap(function _callee2$(_context6) {
            while (1) {
              switch (_context6.prev = _context6.next) {
                case 0:
                  _iteratorNormalCompletion9 = true;
                  _didIteratorError9 = false;
                  _iteratorError9 = undefined;
                  _context6.prev = 3;
                  _iterator9 = pairs[Symbol.iterator]();
  
                case 5:
                  if (_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done) {
                    _context6.next = 12;
                    break;
                  }
  
                  _step9$value = slicedToArray(_step9.value, 2), id = _step9$value[0], item = _step9$value[1];
                  _context6.next = 9;
                  return [id, callback(item, id)];
  
                case 9:
                  _iteratorNormalCompletion9 = true;
                  _context6.next = 5;
                  break;
  
                case 12:
                  _context6.next = 18;
                  break;
  
                case 14:
                  _context6.prev = 14;
                  _context6.t0 = _context6["catch"](3);
                  _didIteratorError9 = true;
                  _iteratorError9 = _context6.t0;
  
                case 18:
                  _context6.prev = 18;
                  _context6.prev = 19;
  
                  if (!_iteratorNormalCompletion9 && _iterator9.return != null) {
                    _iterator9.return();
                  }
  
                case 21:
                  _context6.prev = 21;
  
                  if (!_didIteratorError9) {
                    _context6.next = 24;
                    break;
                  }
  
                  throw _iteratorError9;
  
                case 24:
                  return _context6.finish(21);
  
                case 25:
                  return _context6.finish(18);
  
                case 26:
                case "end":
                  return _context6.stop();
              }
            }
          }, _callee2, null, [[3, 14, 18, 26], [19,, 21, 25]]);
        })));
      }
      /**
       * Get the item with the maximum value of given property.
       *
       * @param callback - The function that picks and possibly converts the property.
       *
       * @returns The item with the maximum if found otherwise null.
       */
  
    }, {
      key: "max",
      value: function max(callback) {
        var iter = this._pairs[Symbol.iterator]();
  
        var curr = iter.next();
  
        if (curr.done) {
          return null;
        }
  
        var maxItem = curr.value[1];
        var maxValue = callback(curr.value[1], curr.value[0]);
  
        while (!(curr = iter.next()).done) {
          var _curr$value = slicedToArray(curr.value, 2),
              id = _curr$value[0],
              item = _curr$value[1];
  
          var _value = callback(item, id);
  
          if (_value > maxValue) {
            maxValue = _value;
            maxItem = item;
          }
        }
  
        return maxItem;
      }
      /**
       * Get the item with the minimum value of given property.
       *
       * @param callback - The function that picks and possibly converts the property.
       *
       * @returns The item with the minimum if found otherwise null.
       */
  
    }, {
      key: "min",
      value: function min(callback) {
        var iter = this._pairs[Symbol.iterator]();
  
        var curr = iter.next();
  
        if (curr.done) {
          return null;
        }
  
        var minItem = curr.value[1];
        var minValue = callback(curr.value[1], curr.value[0]);
  
        while (!(curr = iter.next()).done) {
          var _curr$value2 = slicedToArray(curr.value, 2),
              id = _curr$value2[0],
              item = _curr$value2[1];
  
          var _value2 = callback(item, id);
  
          if (_value2 < minValue) {
            minValue = _value2;
            minItem = item;
          }
        }
  
        return minItem;
      }
      /**
       * Reduce the items into a single value.
       *
       * @param callback - The function that does the reduction.
       * @param accumulator - The initial value of the accumulator.
       *
       * @typeparam T - The type of the accumulated value.
       *
       * @returns The reduced value.
       */
  
    }, {
      key: "reduce",
      value: function reduce(callback, accumulator) {
        var _iteratorNormalCompletion10 = true;
        var _didIteratorError10 = false;
        var _iteratorError10 = undefined;
  
        try {
          for (var _iterator10 = this._pairs[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
            var _step10$value = slicedToArray(_step10.value, 2),
                id = _step10$value[0],
                item = _step10$value[1];
  
            accumulator = callback(accumulator, item, id);
          }
        } catch (err) {
          _didIteratorError10 = true;
          _iteratorError10 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
              _iterator10.return();
            }
          } finally {
            if (_didIteratorError10) {
              throw _iteratorError10;
            }
          }
        }
  
        return accumulator;
      }
      /**
       * Sort the items.
       *
       * @param callback - Item comparator.
       *
       * @returns A new stream with sorted items.
       */
  
    }, {
      key: "sort",
      value: function sort(callback) {
        var _this = this;
  
        return new DataStream(defineProperty({}, Symbol.iterator, function () {
          return toConsumableArray(_this._pairs).sort(function (_ref3, _ref4) {
            var _ref5 = slicedToArray(_ref3, 2),
                idA = _ref5[0],
                itemA = _ref5[1];
  
            var _ref6 = slicedToArray(_ref4, 2),
                idB = _ref6[0],
                itemB = _ref6[1];
  
            return callback(itemA, itemB, idA, idB);
          })[Symbol.iterator]();
        }));
      }
    }]);
  
    return DataStream;
  }();
  
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; }
  
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
  /**
   * # DataSet
   *
   * Vis.js comes with a flexible DataSet, which can be used to hold and manipulate unstructured data and listen for changes in the data. The DataSet is key/value based. Data items can be added, updated and removed from the DataSet, and one can subscribe to changes in the DataSet. The data in the DataSet can be filtered and ordered, and fields (like dates) can be converted to a specific type. Data can be normalized when appending it to the DataSet as well.
   *
   * ## Example
   *
   * The following example shows how to use a DataSet.
   *
   * ```javascript
   * // create a DataSet
   * var options = {};
   * var data = new vis.DataSet(options);
   *
   * // add items
   * // note that the data items can contain different properties and data formats
   * data.add([
   *   {id: 1, text: 'item 1', date: new Date(2013, 6, 20), group: 1, first: true},
   *   {id: 2, text: 'item 2', date: '2013-06-23', group: 2},
   *   {id: 3, text: 'item 3', date: '2013-06-25', group: 2},
   *   {id: 4, text: 'item 4'}
   * ]);
   *
   * // subscribe to any change in the DataSet
   * data.on('*', function (event, properties, senderId) {
   *   console.log('event', event, properties);
   * });
   *
   * // update an existing item
   * data.update({id: 2, group: 1});
   *
   * // remove an item
   * data.remove(4);
   *
   * // get all ids
   * var ids = data.getIds();
   * console.log('ids', ids);
   *
   * // get a specific item
   * var item1 = data.get(1);
   * console.log('item1', item1);
   *
   * // retrieve a filtered subset of the data
   * var items = data.get({
   *   filter: function (item) {
   *     return item.group == 1;
   *   }
   * });
   * console.log('filtered items', items);
   *
   * // retrieve formatted items
   * var items = data.get({
   *   fields: ['id', 'date'],
   *   type: {
   *     date: 'ISODate'
   *   }
   * });
   * console.log('formatted items', items);
   * ```
   *
   * @typeParam Item - Item type that may or may not have an id.
   * @typeParam IdProp - Name of the property that contains the id.
   */
  
  var DataSet =
  /*#__PURE__*/
  function (_DataSetPart) {
    inherits(DataSet, _DataSetPart);
  
    /**
     * Construct a new DataSet.
     *
     * @param data - Initial data or options.
     * @param options - Options (type error if data is also options).
     */
    function DataSet(data, options) {
      var _this;
  
      classCallCheck(this, DataSet);
  
      _this = possibleConstructorReturn(this, getPrototypeOf(DataSet).call(this)); // correctly read optional arguments
  
      if (data && !Array.isArray(data)) {
        options = data;
        data = [];
      }
  
      _this._options = options || {};
      _this._data = new Map(); // map with data indexed by id
  
      _this.length = 0; // number of items in the DataSet
  
      _this._idProp = _this._options.fieldId || "id"; // name of the field containing id
  
      _this._type = {}; // internal field types (NOTE: this can differ from this._options.type)
      // all variants of a Date are internally stored as Date, so we can convert
      // from everything to everything (also from ISODate to Number for example)
  
      if (_this._options.type) {
        var fields = Object.keys(_this._options.type);
  
        for (var i = 0, len = fields.length; i < len; i++) {
          var field = fields[i];
          var value = _this._options.type[field];
  
          if (value == "Date" || value == "ISODate" || value == "ASPDate") {
            _this._type[field] = "Date";
          } else {
            _this._type[field] = value;
          }
        }
      } // add initial data when provided
  
  
      if (data && data.length) {
        _this.add(data);
      }
  
      _this.setOptions(options);
  
      return _this;
    }
    /**
     * Set new options.
     *
     * @param options - The new options.
     */
  
  
    createClass(DataSet, [{
      key: "setOptions",
      value: function setOptions(options) {
        if (options && options.queue !== undefined) {
          if (options.queue === false) {
            // delete queue if loaded
            if (this._queue) {
              this._queue.destroy();
  
              delete this._queue;
            }
          } else {
            // create queue and update its options
            if (!this._queue) {
              this._queue = Queue.extend(this, {
                replace: ["add", "update", "remove"]
              });
            }
  
            if (options.queue && _typeof_1(options.queue) === "object") {
              this._queue.setOptions(options.queue);
            }
          }
        }
      }
      /**
       * Add a data item or an array with items.
       *
       * After the items are added to the DataSet, the DataSet will trigger an event `add`. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
       *
       * ## Example
       *
       * ```javascript
       * // create a DataSet
       * const data = new vis.DataSet()
       *
       * // add items
       * const ids = data.add([
       *   { id: 1, text: 'item 1' },
       *   { id: 2, text: 'item 2' },
       *   { text: 'item without an id' }
       * ])
       *
       * console.log(ids) // [1, 2, '<UUIDv4>']
       * ```
       *
       * @param data - Items to be added (ids will be generated if missing).
       * @param senderId - Sender id.
       *
       * @returns addedIds - Array with the ids (generated if not present) of the added items.
       *
       * @throws When an item with the same id as any of the added items already exists.
       */
  
    }, {
      key: "add",
      value: function add(data, senderId) {
        var _this2 = this;
  
        var addedIds = [];
        var id;
  
        if (Array.isArray(data)) {
          // Array
          var idsToAdd = data.map(function (d) {
            return d[_this2._idProp];
          });
  
          if (idsToAdd.some(function (id) {
            return _this2._data.has(id);
          })) {
            throw new Error("A duplicate id was found in the parameter array.");
          }
  
          for (var i = 0, len = data.length; i < len; i++) {
            id = this._addItem(data[i]);
            addedIds.push(id);
          }
        } else if (data && _typeof_1(data) === "object") {
          // Single item
          id = this._addItem(data);
          addedIds.push(id);
        } else {
          throw new Error("Unknown dataType");
        }
  
        if (addedIds.length) {
          this._trigger("add", {
            items: addedIds
          }, senderId);
        }
  
        return addedIds;
      }
      /**
       * Update existing items. When an item does not exist, it will be created.
       *
       * @remarks
       * The provided properties will be merged in the existing item. When an item does not exist, it will be created.
       *
       * After the items are updated, the DataSet will trigger an event `add` for the added items, and an event `update`. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
       *
       * ## Example
       *
       * ```javascript
       * // create a DataSet
       * const data = new vis.DataSet([
       *   { id: 1, text: 'item 1' },
       *   { id: 2, text: 'item 2' },
       *   { id: 3, text: 'item 3' }
       * ])
       *
       * // update items
       * const ids = data.update([
       *   { id: 2, text: 'item 2 (updated)' },
       *   { id: 4, text: 'item 4 (new)' }
       * ])
       *
       * console.log(ids) // [2, 4]
       * ```
       *
       * ## Warning for TypeScript users
       * This method may introduce partial items into the data set. Use add or updateOnly instead for better type safety.
       *
       * @param data - Items to be updated (if the id is already present) or added (if the id is missing).
       * @param senderId - Sender id.
       *
       * @returns updatedIds - The ids of the added (these may be newly generated if there was no id in the item from the data) or updated items.
       *
       * @throws When the supplied data is neither an item nor an array of items.
       */
  
    }, {
      key: "update",
      value: function update(data, senderId) {
        var _this3 = this;
  
        var addedIds = [];
        var updatedIds = [];
        var oldData = [];
        var updatedData = [];
        var idProp = this._idProp;
  
        var addOrUpdate = function addOrUpdate(item) {
          var origId = item[idProp];
  
          if (origId != null && _this3._data.has(origId)) {
            var fullItem = item; // it has an id, therefore it is a fullitem
  
            var oldItem = Object.assign({}, _this3._data.get(origId)); // update item
  
            var id = _this3._updateItem(fullItem);
  
            updatedIds.push(id);
            updatedData.push(fullItem);
            oldData.push(oldItem);
          } else {
            // add new item
            var _id = _this3._addItem(item);
  
            addedIds.push(_id);
          }
        };
  
        if (Array.isArray(data)) {
          // Array
          for (var i = 0, len = data.length; i < len; i++) {
            if (data[i] && _typeof_1(data[i]) === "object") {
              addOrUpdate(data[i]);
            } else {
              console.warn("Ignoring input item, which is not an object at index " + i);
            }
          }
        } else if (data && _typeof_1(data) === "object") {
          // Single item
          addOrUpdate(data);
        } else {
          throw new Error("Unknown dataType");
        }
  
        if (addedIds.length) {
          this._trigger("add", {
            items: addedIds
          }, senderId);
        }
  
        if (updatedIds.length) {
          var props = {
            items: updatedIds,
            oldData: oldData,
            data: updatedData
          }; // TODO: remove deprecated property 'data' some day
          //Object.defineProperty(props, 'data', {
          //  'get': (function() {
          //    console.warn('Property data is deprecated. Use DataSet.get(ids) to retrieve the new data, use the oldData property on this object to get the old data');
          //    return updatedData;
          //  }).bind(this)
          //});
  
          this._trigger("update", props, senderId);
        }
  
        return addedIds.concat(updatedIds);
      }
      /**
       * Update existing items. When an item does not exist, an error will be thrown.
       *
       * @remarks
       * The provided properties will be deeply merged into the existing item.
       * When an item does not exist (id not present in the data set or absent), an error will be thrown and nothing will be changed.
       *
       * After the items are updated, the DataSet will trigger an event `update`.
       * When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
       *
       * ## Example
       *
       * ```javascript
       * // create a DataSet
       * const data = new vis.DataSet([
       *   { id: 1, text: 'item 1' },
       *   { id: 2, text: 'item 2' },
       *   { id: 3, text: 'item 3' },
       * ])
       *
       * // update items
       * const ids = data.update([
       *   { id: 2, text: 'item 2 (updated)' }, // works
       *   // { id: 4, text: 'item 4 (new)' }, // would throw
       *   // { text: 'item 4 (new)' }, // would also throw
       * ])
       *
       * console.log(ids) // [2]
       * ```
       *
       * @param data - Updates (the id and optionally other props) to the items in this data set.
       * @param senderId - Sender id.
       *
       * @returns updatedIds - The ids of the updated items.
       *
       * @throws When the supplied data is neither an item nor an array of items, when the ids are missing.
       */
  
    }, {
      key: "updateOnly",
      value: function updateOnly(data, senderId) {
        var _this4 = this;
  
        if (!Array.isArray(data)) {
          data = [data];
        }
  
        var updateEventData = data.map(function (update) {
          var oldData = _this4._data.get(update[_this4._idProp]);
  
          if (oldData == null) {
            throw new Error("Updating non-existent items is not allowed.");
          }
  
          return {
            oldData: oldData,
            update: update
          };
        }).map(function (_ref) {
          var oldData = _ref.oldData,
              update = _ref.update;
          var id = oldData[_this4._idProp];
          var updatedData = deepExtend(deepExtend({}, oldData), update);
  
          _this4._data.set(id, updatedData);
  
          return {
            id: id,
            oldData: oldData,
            updatedData: updatedData
          };
        });
  
        if (updateEventData.length) {
          var props = {
            items: updateEventData.map(function (value) {
              return value.id;
            }),
            oldData: updateEventData.map(function (value) {
              return value.oldData;
            }),
            data: updateEventData.map(function (value) {
              return value.updatedData;
            })
          }; // TODO: remove deprecated property 'data' some day
          //Object.defineProperty(props, 'data', {
          //  'get': (function() {
          //    console.warn('Property data is deprecated. Use DataSet.get(ids) to retrieve the new data, use the oldData property on this object to get the old data');
          //    return updatedData;
          //  }).bind(this)
          //});
  
          this._trigger("update", props, senderId);
  
          return props.items;
        } else {
          return [];
        }
      }
      /** @inheritdoc */
  
    }, {
      key: "get",
      value: function get(first, second) {
        // @TODO: Woudn't it be better to split this into multiple methods?
        // parse the arguments
        var id = undefined;
        var ids = undefined;
        var options = undefined;
  
        if (isId(first)) {
          // get(id [, options])
          id = first;
          options = second;
        } else if (Array.isArray(first)) {
          // get(ids [, options])
          ids = first;
          options = second;
        } else {
          // get([, options])
          options = first;
        } // determine the return type
  
  
        var returnType = options && options.returnType === "Object" ? "Object" : "Array"; // @TODO: WTF is this? Or am I missing something?
        // var returnType
        // if (options && options.returnType) {
        //   var allowedValues = ['Array', 'Object']
        //   returnType =
        //     allowedValues.indexOf(options.returnType) == -1
        //       ? 'Array'
        //       : options.returnType
        // } else {
        //   returnType = 'Array'
        // }
        // build options
  
        var type = options && options.type || this._options.type;
        var filter = options && options.filter;
        var items = [];
        var item = null;
        var itemIds = null;
        var itemId = null; // convert items
  
        if (id != null) {
          // return a single item
          item = this._getItem(id, type);
  
          if (item && filter && !filter(item)) {
            item = null;
          }
        } else if (ids != null) {
          // return a subset of items
          for (var i = 0, len = ids.length; i < len; i++) {
            item = this._getItem(ids[i], type);
  
            if (item != null && (!filter || filter(item))) {
              items.push(item);
            }
          }
        } else {
          // return all items
          itemIds = toConsumableArray(this._data.keys());
  
          for (var _i = 0, _len = itemIds.length; _i < _len; _i++) {
            itemId = itemIds[_i];
            item = this._getItem(itemId, type);
  
            if (item != null && (!filter || filter(item))) {
              items.push(item);
            }
          }
        } // order the results
  
  
        if (options && options.order && id == undefined) {
          this._sort(items, options.order);
        } // filter fields of the items
  
  
        if (options && options.fields) {
          var fields = options.fields;
  
          if (id != undefined && item != null) {
            item = this._filterFields(item, fields);
          } else {
            for (var _i2 = 0, _len2 = items.length; _i2 < _len2; _i2++) {
              items[_i2] = this._filterFields(items[_i2], fields);
            }
          }
        } // return the results
  
  
        if (returnType == "Object") {
          var result = {};
  
          for (var _i3 = 0, _len3 = items.length; _i3 < _len3; _i3++) {
            var resultant = items[_i3]; // @TODO: Shoudn't this be this._fieldId?
            // result[resultant.id] = resultant
  
            var _id2 = resultant[this._idProp];
            result[_id2] = resultant;
          }
  
          return result;
        } else {
          if (id != null) {
            // a single item
            return item;
          } else {
            // just return our array
            return items;
          }
        }
      }
      /** @inheritdoc */
  
    }, {
      key: "getIds",
      value: function getIds(options) {
        var data = this._data;
        var filter = options && options.filter;
        var order = options && options.order;
        var type = options && options.type || this._options.type;
  
        var itemIds = toConsumableArray(data.keys());
  
        var ids = [];
        var item;
        var items;
  
        if (filter) {
          // get filtered items
          if (order) {
            // create ordered list
            items = [];
  
            for (var i = 0, len = itemIds.length; i < len; i++) {
              var id = itemIds[i];
              item = this._getItem(id, type);
  
              if (filter(item)) {
                items.push(item);
              }
            }
  
            this._sort(items, order);
  
            for (var _i4 = 0, _len4 = items.length; _i4 < _len4; _i4++) {
              ids.push(items[_i4][this._idProp]);
            }
          } else {
            // create unordered list
            for (var _i5 = 0, _len5 = itemIds.length; _i5 < _len5; _i5++) {
              var _id3 = itemIds[_i5];
              item = this._getItem(_id3, type);
  
              if (filter(item)) {
                ids.push(item[this._idProp]);
              }
            }
          }
        } else {
          // get all items
          if (order) {
            // create an ordered list
            items = [];
  
            for (var _i6 = 0, _len6 = itemIds.length; _i6 < _len6; _i6++) {
              var _id4 = itemIds[_i6];
              items.push(data.get(_id4));
            }
  
            this._sort(items, order);
  
            for (var _i7 = 0, _len7 = items.length; _i7 < _len7; _i7++) {
              ids.push(items[_i7][this._idProp]);
            }
          } else {
            // create unordered list
            for (var _i8 = 0, _len8 = itemIds.length; _i8 < _len8; _i8++) {
              var _id5 = itemIds[_i8];
              item = data.get(_id5);
              ids.push(item[this._idProp]);
            }
          }
        }
  
        return ids;
      }
      /** @inheritdoc */
  
    }, {
      key: "getDataSet",
      value: function getDataSet() {
        return this;
      }
      /** @inheritdoc */
  
    }, {
      key: "forEach",
      value: function forEach(callback, options) {
        var filter = options && options.filter;
        var type = options && options.type || this._options.type;
        var data = this._data;
  
        var itemIds = toConsumableArray(data.keys());
  
        if (options && options.order) {
          // execute forEach on ordered list
          var items = this.get(options);
  
          for (var i = 0, len = items.length; i < len; i++) {
            var item = items[i];
            var id = item[this._idProp];
            callback(item, id);
          }
        } else {
          // unordered
          for (var _i9 = 0, _len9 = itemIds.length; _i9 < _len9; _i9++) {
            var _id6 = itemIds[_i9];
  
            var _item = this._getItem(_id6, type);
  
            if (!filter || filter(_item)) {
              callback(_item, _id6);
            }
          }
        }
      }
      /** @inheritdoc */
  
    }, {
      key: "map",
      value: function map(callback, options) {
        var filter = options && options.filter;
        var type = options && options.type || this._options.type;
        var mappedItems = [];
        var data = this._data;
  
        var itemIds = toConsumableArray(data.keys()); // convert and filter items
  
  
        for (var i = 0, len = itemIds.length; i < len; i++) {
          var id = itemIds[i];
  
          var item = this._getItem(id, type);
  
          if (!filter || filter(item)) {
            mappedItems.push(callback(item, id));
          }
        } // order items
  
  
        if (options && options.order) {
          this._sort(mappedItems, options.order);
        }
  
        return mappedItems;
      }
      /**
       * Filter the fields of an item.
       *
       * @param item - The item whose fields should be filtered.
       * @param fields - The names of the fields that will be kept.
       *
       * @typeParam K - Field name type.
       *
       * @returns The item without any additional fields.
       */
  
    }, {
      key: "_filterFields",
      value: function _filterFields(item, fields) {
        if (!item) {
          // item is null
          return item;
        }
  
        return (Array.isArray(fields) ? // Use the supplied array
        fields : // Use the keys of the supplied object
        Object.keys(fields)).reduce(function (filteredItem, field) {
          filteredItem[field] = item[field];
          return filteredItem;
        }, {});
      }
      /**
       * Sort the provided array with items.
       *
       * @param items - Items to be sorted in place.
       * @param order - A field name or custom sort function.
       *
       * @typeParam T - The type of the items in the items array.
       */
  
    }, {
      key: "_sort",
      value: function _sort(items, order) {
        if (typeof order === "string") {
          // order by provided field name
          var name = order; // field name
  
          items.sort(function (a, b) {
            // @TODO: How to treat missing properties?
            var av = a[name];
            var bv = b[name];
            return av > bv ? 1 : av < bv ? -1 : 0;
          });
        } else if (typeof order === "function") {
          // order by sort function
          items.sort(order);
        } else {
          // TODO: extend order by an Object {field:string, direction:string}
          //       where direction can be 'asc' or 'desc'
          throw new TypeError("Order must be a function or a string");
        }
      }
      /**
       * Remove an item or multiple items by “reference” (only the id is used) or by id.
       *
       * The method ignores removal of non-existing items, and returns an array containing the ids of the items which are actually removed from the DataSet.
       *
       * After the items are removed, the DataSet will trigger an event `remove` for the removed items. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
       *
       * ## Example
       * ```javascript
       * // create a DataSet
       * const data = new vis.DataSet([
       *   { id: 1, text: 'item 1' },
       *   { id: 2, text: 'item 2' },
       *   { id: 3, text: 'item 3' }
       * ])
       *
       * // remove items
       * const ids = data.remove([2, { id: 3 }, 4])
       *
       * console.log(ids) // [2, 3]
       * ```
       *
       * @param id - One or more items or ids of items to be removed.
       * @param senderId - Sender id.
       *
       * @returns The ids of the removed items.
       */
  
    }, {
      key: "remove",
      value: function remove(id, senderId) {
        var removedIds = [];
        var removedItems = []; // force everything to be an array for simplicity
  
        var ids = Array.isArray(id) ? id : [id];
  
        for (var i = 0, len = ids.length; i < len; i++) {
          var item = this._remove(ids[i]);
  
          if (item) {
            var itemId = item[this._idProp];
  
            if (itemId != null) {
              removedIds.push(itemId);
              removedItems.push(item);
            }
          }
        }
  
        if (removedIds.length) {
          this._trigger("remove", {
            items: removedIds,
            oldData: removedItems
          }, senderId);
        }
  
        return removedIds;
      }
      /**
       * Remove an item by its id or reference.
       *
       * @param id - Id of an item or the item itself.
       *
       * @returns The removed item if removed, null otherwise.
       */
  
    }, {
      key: "_remove",
      value: function _remove(id) {
        // @TODO: It origianlly returned the item although the docs say id.
        // The code expects the item, so probably an error in the docs.
        var ident; // confirm the id to use based on the args type
  
        if (isId(id)) {
          ident = id;
        } else if (id && _typeof_1(id) === "object") {
          ident = id[this._idProp]; // look for the identifier field using ._idProp
        } // do the removing if the item is found
  
  
        if (ident != null && this._data.has(ident)) {
          var item = this._data.get(ident) || null;
  
          this._data.delete(ident);
  
          --this.length;
          return item;
        }
  
        return null;
      }
      /**
       * Clear the entire data set.
       *
       * After the items are removed, the [[DataSet]] will trigger an event `remove` for all removed items. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
       *
       * @param senderId - Sender id.
       *
       * @returns removedIds - The ids of all removed items.
       */
  
    }, {
      key: "clear",
      value: function clear(senderId) {
        var ids = toConsumableArray(this._data.keys());
  
        var items = [];
  
        for (var i = 0, len = ids.length; i < len; i++) {
          items.push(this._data.get(ids[i]));
        }
  
        this._data.clear();
  
        this.length = 0;
  
        this._trigger("remove", {
          items: ids,
          oldData: items
        }, senderId);
  
        return ids;
      }
      /**
       * Find the item with maximum value of a specified field.
       *
       * @param field - Name of the property that should be searched for max value.
       *
       * @returns Item containing max value, or null if no items.
       */
  
    }, {
      key: "max",
      value: function max(field) {
        var max = null;
        var maxField = null;
        var _iteratorNormalCompletion = true;
        var _didIteratorError = false;
        var _iteratorError = undefined;
  
        try {
          for (var _iterator = this._data.values()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
            var item = _step.value;
            var itemField = item[field];
  
            if (typeof itemField === "number" && (maxField == null || itemField > maxField)) {
              max = item;
              maxField = itemField;
            }
          }
        } catch (err) {
          _didIteratorError = true;
          _iteratorError = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion && _iterator.return != null) {
              _iterator.return();
            }
          } finally {
            if (_didIteratorError) {
              throw _iteratorError;
            }
          }
        }
  
        return max || null;
      }
      /**
       * Find the item with minimum value of a specified field.
       *
       * @param field - Name of the property that should be searched for min value.
       *
       * @returns Item containing min value, or null if no items.
       */
  
    }, {
      key: "min",
      value: function min(field) {
        var min = null;
        var minField = null;
        var _iteratorNormalCompletion2 = true;
        var _didIteratorError2 = false;
        var _iteratorError2 = undefined;
  
        try {
          for (var _iterator2 = this._data.values()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
            var item = _step2.value;
            var itemField = item[field];
  
            if (typeof itemField === "number" && (minField == null || itemField < minField)) {
              min = item;
              minField = itemField;
            }
          }
        } catch (err) {
          _didIteratorError2 = true;
          _iteratorError2 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
              _iterator2.return();
            }
          } finally {
            if (_didIteratorError2) {
              throw _iteratorError2;
            }
          }
        }
  
        return min || null;
      }
      /**
       * Find all distinct values of a specified field
       *
       * @param prop - The property name whose distinct values should be returned.
       *
       * @returns Unordered array containing all distinct values. Items without specified property are ignored.
       */
  
    }, {
      key: "distinct",
      value: function distinct(prop) {
        var data = this._data;
  
        var itemIds = toConsumableArray(data.keys());
  
        var values = [];
        var fieldType = this._options.type && this._options.type[prop] || null;
        var count = 0;
  
        for (var i = 0, len = itemIds.length; i < len; i++) {
          var id = itemIds[i];
          var item = data.get(id);
          var value = item[prop];
          var exists = false;
  
          for (var j = 0; j < count; j++) {
            if (values[j] == value) {
              exists = true;
              break;
            }
          }
  
          if (!exists && value !== undefined) {
            values[count] = value;
            count++;
          }
        }
  
        if (fieldType) {
          for (var _i10 = 0, _len10 = values.length; _i10 < _len10; _i10++) {
            values[_i10] = convert(values[_i10], fieldType);
          }
        }
  
        return values;
      }
      /**
       * Add a single item. Will fail when an item with the same id already exists.
       *
       * @param item - A new item to be added.
       *
       * @returns Added item's id. An id is generated when it is not present in the item.
       */
  
    }, {
      key: "_addItem",
      value: function _addItem(item) {
        var id = item[this._idProp];
  
        if (id != null) {
          // check whether this id is already taken
          if (this._data.has(id)) {
            // item already exists
            throw new Error("Cannot add item: item with id " + id + " already exists");
          }
        } else {
          // generate an id
          id = uuid4();
          item[this._idProp] = id;
        }
  
        var d = {};
        var fields = Object.keys(item);
  
        for (var i = 0, len = fields.length; i < len; i++) {
          var field = fields[i];
          var fieldType = this._type[field]; // type may be undefined
  
          d[field] = convert(item[field], fieldType);
        }
  
        this._data.set(id, d);
  
        ++this.length;
        return id;
      }
      /**
       * Get an item. Fields can be converted to a specific type
       *
       * @param id - Id of the requested item.
       * @param types - Property name to type name object map of type converstions.
       *
       * @returns The item, optionally after type conversion.
       */
  
    }, {
      key: "_getItem",
      value: function _getItem(id, types) {
        // @TODO: I have no idea how to type this.
        // get the item from the dataset
        var raw = this._data.get(id);
  
        if (!raw) {
          return null;
        } // convert the items field types
  
  
        var converted;
        var fields = Object.keys(raw);
  
        if (types) {
          converted = {};
  
          for (var i = 0, len = fields.length; i < len; i++) {
            var field = fields[i];
            var value = raw[field];
            converted[field] = convert(value, types[field]);
          }
        } else {
          // no field types specified, no converting needed
          converted = _objectSpread({}, raw);
        }
  
        if (converted[this._idProp] == null) {
          converted[this._idProp] = raw.id;
        }
  
        return converted;
      }
      /**
       * Update a single item: merge with existing item.
       * Will fail when the item has no id, or when there does not exist an item with the same id.
       *
       * @param item - The new item
       *
       * @returns The id of the updated item.
       */
  
    }, {
      key: "_updateItem",
      value: function _updateItem(item) {
        var id = item[this._idProp];
  
        if (id == null) {
          throw new Error("Cannot update item: item has no id (item: " + JSON.stringify(item) + ")");
        }
  
        var d = this._data.get(id);
  
        if (!d) {
          // item doesn't exist
          throw new Error("Cannot update item: no item with id " + id + " found");
        } // merge with current item
  
  
        var fields = Object.keys(item);
  
        for (var i = 0, len = fields.length; i < len; i++) {
          var field = fields[i];
          var fieldType = this._type[field]; // type may be undefined
  
          d[field] = convert(item[field], fieldType);
        }
  
        return id;
      }
      /** @inheritdoc */
  
    }, {
      key: "stream",
      value: function stream(ids) {
        if (ids) {
          var data = this._data;
          return new DataStream(defineProperty({}, Symbol.iterator,
          /*#__PURE__*/
          regenerator.mark(function _callee() {
            var _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, id, item;
  
            return regenerator.wrap(function _callee$(_context) {
              while (1) {
                switch (_context.prev = _context.next) {
                  case 0:
                    _iteratorNormalCompletion3 = true;
                    _didIteratorError3 = false;
                    _iteratorError3 = undefined;
                    _context.prev = 3;
                    _iterator3 = ids[Symbol.iterator]();
  
                  case 5:
                    if (_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done) {
                      _context.next = 14;
                      break;
                    }
  
                    id = _step3.value;
                    item = data.get(id);
  
                    if (!(item != null)) {
                      _context.next = 11;
                      break;
                    }
  
                    _context.next = 11;
                    return [id, item];
  
                  case 11:
                    _iteratorNormalCompletion3 = true;
                    _context.next = 5;
                    break;
  
                  case 14:
                    _context.next = 20;
                    break;
  
                  case 16:
                    _context.prev = 16;
                    _context.t0 = _context["catch"](3);
                    _didIteratorError3 = true;
                    _iteratorError3 = _context.t0;
  
                  case 20:
                    _context.prev = 20;
                    _context.prev = 21;
  
                    if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
                      _iterator3.return();
                    }
  
                  case 23:
                    _context.prev = 23;
  
                    if (!_didIteratorError3) {
                      _context.next = 26;
                      break;
                    }
  
                    throw _iteratorError3;
  
                  case 26:
                    return _context.finish(23);
  
                  case 27:
                    return _context.finish(20);
  
                  case 28:
                  case "end":
                    return _context.stop();
                }
              }
            }, _callee, null, [[3, 16, 20, 28], [21,, 23, 27]]);
          })));
        } else {
          return new DataStream(defineProperty({}, Symbol.iterator, this._data.entries.bind(this._data)));
        }
      }
    }]);
  
    return DataSet;
  }(DataSetPart);
  
  /**
   * DataView
   *
   * A DataView offers a filtered and/or formatted view on a DataSet. One can subscribe to changes in a DataView, and easily get filtered or formatted data without having to specify filters and field types all the time.
   *
   * ## Example
   * ```javascript
   * // create a DataSet
   * var data = new vis.DataSet();
   * data.add([
   *   {id: 1, text: 'item 1', date: new Date(2013, 6, 20), group: 1, first: true},
   *   {id: 2, text: 'item 2', date: '2013-06-23', group: 2},
   *   {id: 3, text: 'item 3', date: '2013-06-25', group: 2},
   *   {id: 4, text: 'item 4'}
   * ]);
   *
   * // create a DataView
   * // the view will only contain items having a property group with value 1,
   * // and will only output fields id, text, and date.
   * var view = new vis.DataView(data, {
   *   filter: function (item) {
   *     return (item.group == 1);
   *   },
   *   fields: ['id', 'text', 'date']
   * });
   *
   * // subscribe to any change in the DataView
   * view.on('*', function (event, properties, senderId) {
   *   console.log('event', event, properties);
   * });
   *
   * // update an item in the data set
   * data.update({id: 2, group: 1});
   *
   * // get all ids in the view
   * var ids = view.getIds();
   * console.log('ids', ids); // will output [1, 2]
   *
   * // get all items in the view
   * var items = view.get();
   * ```
   *
   * @typeParam Item - Item type that may or may not have an id.
   * @typeParam IdProp - Name of the property that contains the id.
   */
  
  var DataView =
  /*#__PURE__*/
  function (_DataSetPart) {
    inherits(DataView, _DataSetPart);
  
    /**
     * Create a DataView.
     *
     * @param data - The instance containing data (directly or indirectly).
     * @param options - Options to configure this data view.
     */
    function DataView(data, options) {
      var _this;
  
      classCallCheck(this, DataView);
  
      _this = possibleConstructorReturn(this, getPrototypeOf(DataView).call(this));
      /** @inheritdoc */
  
      _this.length = 0;
      _this._ids = new Set(); // ids of the items currently in memory (just contains a boolean true)
  
      _this._options = options || {};
      _this._listener = _this._onEvent.bind(assertThisInitialized(_this));
  
      _this.setData(data);
  
      return _this;
    } // TODO: implement a function .config() to dynamically update things like configured filter
    // and trigger changes accordingly
  
    /**
     * Set a data source for the view.
     *
     * @param data - The instance containing data (directly or indirectly).
     */
  
  
    createClass(DataView, [{
      key: "setData",
      value: function setData(data) {
        if (this._data) {
          // unsubscribe from current dataset
          if (this._data.off) {
            this._data.off("*", this._listener);
          } // trigger a remove of all items in memory
  
  
          var ids = this._data.getIds({
            filter: this._options.filter
          });
  
          var items = this._data.get(ids);
  
          this._ids.clear();
  
          this.length = 0;
  
          this._trigger("remove", {
            items: ids,
            oldData: items
          });
        }
  
        if (data != null) {
          this._data = data; // trigger an add of all added items
  
          var _ids = this._data.getIds({
            filter: this._options.filter
          });
  
          for (var i = 0, len = _ids.length; i < len; i++) {
            var id = _ids[i];
  
            this._ids.add(id);
          }
  
          this.length = _ids.length;
  
          this._trigger("add", {
            items: _ids
          });
        } else {
          this._data = new DataSet();
        } // subscribe to new dataset
  
  
        if (this._data.on) {
          this._data.on("*", this._listener);
        }
      }
      /**
       * Refresh the DataView.
       * Useful when the DataView has a filter function containing a variable parameter.
       */
  
    }, {
      key: "refresh",
      value: function refresh() {
        var ids = this._data.getIds({
          filter: this._options.filter
        });
  
        var oldIds = toConsumableArray(this._ids);
  
        var newIds = {};
        var addedIds = [];
        var removedIds = [];
        var removedItems = []; // check for additions
  
        for (var i = 0, len = ids.length; i < len; i++) {
          var id = ids[i];
          newIds[id] = true;
  
          if (!this._ids.has(id)) {
            addedIds.push(id);
  
            this._ids.add(id);
          }
        } // check for removals
  
  
        for (var _i = 0, _len = oldIds.length; _i < _len; _i++) {
          var _id = oldIds[_i];
  
          var item = this._data.get(_id);
  
          if (item == null) {
            // @TODO: Investigate.
            // Doesn't happen during tests or examples.
            // Is it really impossible or could it eventually happen?
            // How to handle it if it does? The types guarantee non-nullable items.
            console.error("If you see this, report it please.");
          } else if (!newIds[_id]) {
            removedIds.push(_id);
            removedItems.push(item);
  
            this._ids.delete(_id);
          }
        }
  
        this.length += addedIds.length - removedIds.length; // trigger events
  
        if (addedIds.length) {
          this._trigger("add", {
            items: addedIds
          });
        }
  
        if (removedIds.length) {
          this._trigger("remove", {
            items: removedIds,
            oldData: removedItems
          });
        }
      }
      /** @inheritdoc */
  
    }, {
      key: "get",
      value: function get(first, second) {
        if (this._data == null) {
          return null;
        } // parse the arguments
  
  
        var ids = null;
        var options;
  
        if (isId(first) || Array.isArray(first)) {
          ids = first;
          options = second;
        } else {
          options = first;
        } // extend the options with the default options and provided options
  
  
        var viewOptions = Object.assign({}, this._options, options); // create a combined filter method when needed
  
        var thisFilter = this._options.filter;
        var optionsFilter = options && options.filter;
  
        if (thisFilter && optionsFilter) {
          viewOptions.filter = function (item) {
            return thisFilter(item) && optionsFilter(item);
          };
        }
  
        if (ids == null) {
          return this._data.get(viewOptions);
        } else {
          return this._data.get(ids, viewOptions);
        }
      }
      /** @inheritdoc */
  
    }, {
      key: "getIds",
      value: function getIds(options) {
        if (this._data.length) {
          var defaultFilter = this._options.filter;
          var optionsFilter = options != null ? options.filter : null;
          var filter;
  
          if (optionsFilter) {
            if (defaultFilter) {
              filter = function filter(item) {
                return defaultFilter(item) && optionsFilter(item);
              };
            } else {
              filter = optionsFilter;
            }
          } else {
            filter = defaultFilter;
          }
  
          return this._data.getIds({
            filter: filter,
            order: options && options.order
          });
        } else {
          return [];
        }
      }
      /** @inheritdoc */
  
    }, {
      key: "forEach",
      value: function forEach(callback, options) {
        if (this._data) {
          var defaultFilter = this._options.filter;
          var optionsFilter = options && options.filter;
          var filter;
  
          if (optionsFilter) {
            if (defaultFilter) {
              filter = function filter(item) {
                return defaultFilter(item) && optionsFilter(item);
              };
            } else {
              filter = optionsFilter;
            }
          } else {
            filter = defaultFilter;
          }
  
          this._data.forEach(callback, {
            filter: filter,
            order: options && options.order
          });
        }
      }
      /** @inheritdoc */
  
    }, {
      key: "map",
      value: function map(callback, options) {
        if (this._data) {
          var defaultFilter = this._options.filter;
          var optionsFilter = options && options.filter;
          var filter;
  
          if (optionsFilter) {
            if (defaultFilter) {
              filter = function filter(item) {
                return defaultFilter(item) && optionsFilter(item);
              };
            } else {
              filter = optionsFilter;
            }
          } else {
            filter = defaultFilter;
          }
  
          return this._data.map(callback, {
            filter: filter,
            order: options && options.order
          });
        } else {
          return [];
        }
      }
      /** @inheritdoc */
  
    }, {
      key: "getDataSet",
      value: function getDataSet() {
        return this._data.getDataSet();
      }
      /** @inheritdoc */
  
    }, {
      key: "stream",
      value: function stream(ids) {
        return this._data.stream(ids || defineProperty({}, Symbol.iterator, this._ids.keys.bind(this._ids)));
      }
      /**
       * Event listener. Will propagate all events from the connected data set to the subscribers of the DataView, but will filter the items and only trigger when there are changes in the filtered data set.
       *
       * @param event - The name of the event.
       * @param params - Parameters of the event.
       * @param senderId - Id supplied by the sender.
       */
  
    }, {
      key: "_onEvent",
      value: function _onEvent(event, params, senderId) {
        if (!params || !params.items || !this._data) {
          return;
        }
  
        var ids = params.items;
        var addedIds = [];
        var updatedIds = [];
        var removedIds = [];
        var oldItems = [];
        var updatedItems = [];
        var removedItems = [];
  
        switch (event) {
          case "add":
            // filter the ids of the added items
            for (var i = 0, len = ids.length; i < len; i++) {
              var id = ids[i];
              var item = this.get(id);
  
              if (item) {
                this._ids.add(id);
  
                addedIds.push(id);
              }
            }
  
            break;
  
          case "update":
            // determine the event from the views viewpoint: an updated
            // item can be added, updated, or removed from this view.
            for (var _i2 = 0, _len2 = ids.length; _i2 < _len2; _i2++) {
              var _id2 = ids[_i2];
  
              var _item = this.get(_id2);
  
              if (_item) {
                if (this._ids.has(_id2)) {
                  updatedIds.push(_id2);
                  updatedItems.push(params.data[_i2]);
                  oldItems.push(params.oldData[_i2]);
                } else {
                  this._ids.add(_id2);
  
                  addedIds.push(_id2);
                }
              } else {
                if (this._ids.has(_id2)) {
                  this._ids.delete(_id2);
  
                  removedIds.push(_id2);
                  removedItems.push(params.oldData[_i2]);
                }
              }
            }
  
            break;
  
          case "remove":
            // filter the ids of the removed items
            for (var _i3 = 0, _len3 = ids.length; _i3 < _len3; _i3++) {
              var _id3 = ids[_i3];
  
              if (this._ids.has(_id3)) {
                this._ids.delete(_id3);
  
                removedIds.push(_id3);
                removedItems.push(params.oldData[_i3]);
              }
            }
  
            break;
        }
  
        this.length += addedIds.length - removedIds.length;
  
        if (addedIds.length) {
          this._trigger("add", {
            items: addedIds
          }, senderId);
        }
  
        if (updatedIds.length) {
          this._trigger("update", {
            items: updatedIds,
            oldData: oldItems,
            data: updatedItems
          }, senderId);
        }
  
        if (removedIds.length) {
          this._trigger("remove", {
            items: removedIds,
            oldData: removedItems
          }, senderId);
        }
      }
    }]);
  
    return DataView;
  }(DataSetPart);
  
  var index = {
    DataSet: DataSet,
    DataView: DataView,
    Queue: Queue
  };
  
  export default index;
  export { DataSet, DataStream, DataView, Queue };
  