function Clock(options) {
  options = options ?? Frozen.EMPTY_OBJECT;

  let currentTime = options.currentTime;
  let startTime = options.startTime;
  let stopTime = options.stopTime;

  if (!defined(currentTime)) {
    // if not specified, current time is the start time,
    // or if that is not specified, 1 day before the stop time,
    // or if that is not specified, then now.
    if (defined(startTime)) {
      currentTime = JulianDate.clone(startTime);
    } else if (defined(stopTime)) {
      currentTime = JulianDate.addDays(stopTime, -1.0, new JulianDate());
    } else {
      currentTime = JulianDate.now();
    }
  } else {
    currentTime = JulianDate.clone(currentTime);
  }

  if (!defined(startTime)) {
    // if not specified, start time is the current time
    // (as determined above)
    startTime = JulianDate.clone(currentTime);
  } else {
    startTime = JulianDate.clone(startTime);
  }

  if (!defined(stopTime)) {
    // if not specified, stop time is 1 day after the start time
    // (as determined above)
    stopTime = JulianDate.addDays(startTime, 1.0, new JulianDate());
  } else {
    stopTime = JulianDate.clone(stopTime);
  }

  //>>includeStart('debug', pragmas.debug);
  if (JulianDate.greaterThan(startTime, stopTime)) {
    throw new DeveloperError("startTime must come before stopTime.");
  }
  //>>includeEnd('debug');

  /**
   * The start time of the clock.
   * @type {JulianDate}
   */
  this.startTime = startTime;

  /**
   * The stop time of the clock.
   * @type {JulianDate}
   */
  this.stopTime = stopTime;

  /**
   * Determines how the clock should behave when
   * {@link Clock#startTime} or {@link Clock#stopTime}
   * is reached.
   * @type {ClockRange}
   * @default {@link ClockRange.UNBOUNDED}
   */
  this.clockRange = options.clockRange ?? ClockRange.UNBOUNDED;

  /**
   * Indicates whether {@link Clock#tick} can advance time.  This could be false if data is being buffered,
   * for example.  The clock will only advance time when both
   * {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.
   * @type {boolean}
   * @default true
   */
  this.canAnimate = options.canAnimate ?? true;

  /**
   * An {@link Event} that is fired whenever {@link Clock#tick} is called.
   * @type {Event}
   */
  this.onTick = new Event();
  /**
   * An {@link Event} that is fired whenever {@link Clock#stopTime} is reached.
   * @type {Event}
   */
  this.onStop = new Event();

  this._currentTime = undefined;
  this._multiplier = undefined;
  this._clockStep = undefined;
  this._shouldAnimate = undefined;
  this._lastSystemTime = getTimestamp();

  // set values using the property setters to
  // make values consistent.

  this.currentTime = currentTime;
  this.multiplier = options.multiplier ?? 1.0;
  this.shouldAnimate = options.shouldAnimate ?? false;
  this.clockStep = options.clockStep ?? ClockStep.SYSTEM_CLOCK_MULTIPLIER;
}
A simple clock for keeping track of simulated time.

@alias Clock
@constructor

@param {object} [options] Object with the following properties:
@param {JulianDate} [options.startTime] The start time of the clock.
@param {JulianDate} [options.stopTime] The stop time of the clock.
@param {JulianDate} [options.currentTime] The current time.
@param {number} [options.multiplier=1.0] Determines how much time advances when {@link Clock#tick} is called, negative values allow for advancing backwards.
@param {ClockStep} [options.clockStep=ClockStep.SYSTEM_CLOCK_MULTIPLIER] Determines if calls to {@link Clock#tick} are frame dependent or system clock dependent.
@param {ClockRange} [options.clockRange=ClockRange.UNBOUNDED] Determines how the clock should behave when {@link Clock#startTime} or {@link Clock#stopTime} is reached.
@param {boolean} [options.canAnimate=true] Indicates whether {@link Clock#tick} can advance time.  This could be false if data is being buffered, for example.  The clock will only tick when both {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.
@param {boolean} [options.shouldAnimate=false] Indicates whether {@link Clock#tick} should attempt to advance time.  The clock will only tick when both {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.

@exception {DeveloperError} startTime must come before stopTime.


@example
// Create a clock that loops on Christmas day 2013 and runs in real-time.
const clock = new Cesium.Clock({
   startTime : Cesium.JulianDate.fromIso8601("2013-12-25"),
   currentTime : Cesium.JulianDate.fromIso8601("2013-12-25"),
   stopTime : Cesium.JulianDate.fromIso8601("2013-12-26"),
   clockRange : Cesium.ClockRange.LOOP_STOP,
   clockStep : Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER
});

@see ClockStep
@see ClockRange
@see JulianDate