Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  timekeeper.js   Sprache: JAVA

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


"use strict";

/**
 * TimeKeeper keeps track of the time states. Given min, max, step, and
 * format (12/24hr), TimeKeeper will determine the ranges of possible
 * selections, and whether or not the current time state is out of range
 * or off step.
 *
 * @param {Object} props
 *        {
 *          {Date} min
 *          {Date} max
 *          {Number} step
 *          {String} format: Either "12" or "24"
 *        }
 */

function TimeKeeper(props) {
  this.props = props;
  this.state = { time: new Date(0), ranges: {} };
}

{
  const DAY_PERIOD_IN_HOURS = 12,
    SECOND_IN_MS = 1000,
    MINUTE_IN_MS = 60000,
    HOUR_IN_MS = 3600000,
    DAY_PERIOD_IN_MS = 43200000,
    DAY_IN_MS = 86400000,
    TIME_FORMAT_24 = "24";

  TimeKeeper.prototype = {
    /**
     * Getters for different time units.
     * @return {Number}
     */

    get hour() {
      return this.state.time.getUTCHours();
    },
    get minute() {
      return this.state.time.getUTCMinutes();
    },
    get second() {
      return this.state.time.getUTCSeconds();
    },
    get millisecond() {
      return this.state.time.getUTCMilliseconds();
    },
    get dayPeriod() {
      // 0 stands for AM and 12 for PM
      return this.state.time.getUTCHours() < DAY_PERIOD_IN_HOURS
        ? 0
        : DAY_PERIOD_IN_HOURS;
    },

    /**
     * Get the ranges of different time units.
     * @return {Object}
     *         {
     *           {Array<Number>} dayPeriod
     *           {Array<Number>} hours
     *           {Array<Number>} minutes
     *           {Array<Number>} seconds
     *           {Array<Number>} milliseconds
     *         }
     */

    get ranges() {
      return this.state.ranges;
    },

    /**
     * Set new time, check if the current state is valid, and set ranges.
     *
     * @param {Object} timeState: The new time
     *        {
     *          {Number} hour [optional]
     *          {Number} minute [optional]
     *          {Number} second [optional]
     *          {Number} millisecond [optional]
     *        }
     */

    setState(timeState) {
      const { min, max } = this.props;
      const { hour, minute, second, millisecond } = timeState;

      if (hour != undefined) {
        this.state.time.setUTCHours(hour);
      }
      if (minute != undefined) {
        this.state.time.setUTCMinutes(minute);
      }
      if (second != undefined) {
        this.state.time.setUTCSeconds(second);
      }
      if (millisecond != undefined) {
        this.state.time.setUTCMilliseconds(millisecond);
      }

      this.state.isOffStep = this._isOffStep(this.state.time);
      this.state.isOutOfRange = this.state.time < min || this.state.time > max;
      this.state.isInvalid = this.state.isOutOfRange || this.state.isOffStep;

      this._setRanges(this.dayPeriod, this.hour, this.minute, this.second);
    },

    /**
     * Set day-period (AM/PM)
     * @param {Number} dayPeriod: 0 as AM, 12 as PM
     */

    setDayPeriod(dayPeriod) {
      if (dayPeriod == this.dayPeriod) {
        return;
      }

      if (dayPeriod == 0) {
        this.setState({ hour: this.hour - DAY_PERIOD_IN_HOURS });
      } else {
        this.setState({ hour: this.hour + DAY_PERIOD_IN_HOURS });
      }
    },

    /**
     * Set hour in 24hr format (0 ~ 23)
     * @param {Number} hour
     */

    setHour(hour) {
      this.setState({ hour });
    },

    /**
     * Set minute (0 ~ 59)
     * @param {Number} minute
     */

    setMinute(minute) {
      this.setState({ minute });
    },

    /**
     * Set second (0 ~ 59)
     * @param {Number} second
     */

    setSecond(second) {
      this.setState({ second });
    },

    /**
     * Set millisecond (0 ~ 999)
     * @param {Number} millisecond
     */

    setMillisecond(millisecond) {
      this.setState({ millisecond });
    },

    /**
     * Calculate the range of possible choices for each time unit.
     * Reuse the old result if the input has not changed.
     *
     * @param {Number} dayPeriod
     * @param {Number} hour
     * @param {Number} minute
     * @param {Number} second
     */

    _setRanges(dayPeriod, hour, minute, second) {
      this.state.ranges.dayPeriod =
        this.state.ranges.dayPeriod || this._getDayPeriodRange();

      if (this.state.dayPeriod != dayPeriod) {
        this.state.ranges.hours = this._getHoursRange(dayPeriod);
      }

      if (this.state.hour != hour) {
        this.state.ranges.minutes = this._getMinutesRange(hour);
      }

      if (this.state.hour != hour || this.state.minute != minute) {
        this.state.ranges.seconds = this._getSecondsRange(hour, minute);
      }

      if (
        this.state.hour != hour ||
        this.state.minute != minute ||
        this.state.second != second
      ) {
        this.state.ranges.milliseconds = this._getMillisecondsRange(
          hour,
          minute,
          second
        );
      }

      // Save the time states for comparison.
      this.state.dayPeriod = dayPeriod;
      this.state.hour = hour;
      this.state.minute = minute;
      this.state.second = second;
    },

    /**
     * Get the AM/PM range. Return an empty array if in 24hr mode.
     *
     * @return {Array<Number>}
     */

    _getDayPeriodRange() {
      if (this.props.format == TIME_FORMAT_24) {
        return [];
      }

      const start = 0;
      const end = DAY_IN_MS - 1;
      const minStep = DAY_PERIOD_IN_MS;
      const formatter = time =>
        new Date(time).getUTCHours() < DAY_PERIOD_IN_HOURS
          ? 0
          : DAY_PERIOD_IN_HOURS;

      return this._getSteps(start, end, minStep, formatter);
    },

    /**
     * Get the hours range.
     *
     * @param  {Number} dayPeriod
     * @return {Array<Number>}
     */

    _getHoursRange(dayPeriod) {
      const { format } = this.props;
      const start = format == "24" ? 0 : dayPeriod * HOUR_IN_MS;
      const end = format == "24" ? DAY_IN_MS - 1 : start + DAY_PERIOD_IN_MS - 1;
      const minStep = HOUR_IN_MS;
      const formatter = time => new Date(time).getUTCHours();

      return this._getSteps(start, end, minStep, formatter);
    },

    /**
     * Get the minutes range
     *
     * @param  {Number} hour
     * @return {Array<Number>}
     */

    _getMinutesRange(hour) {
      const start = hour * HOUR_IN_MS;
      const end = start + HOUR_IN_MS - 1;
      const minStep = MINUTE_IN_MS;
      const formatter = time => new Date(time).getUTCMinutes();

      return this._getSteps(start, end, minStep, formatter);
    },

    /**
     * Get the seconds range
     *
     * @param  {Number} hour
     * @param  {Number} minute
     * @return {Array<Number>}
     */

    _getSecondsRange(hour, minute) {
      const start = hour * HOUR_IN_MS + minute * MINUTE_IN_MS;
      const end = start + MINUTE_IN_MS - 1;
      const minStep = SECOND_IN_MS;
      const formatter = time => new Date(time).getUTCSeconds();

      return this._getSteps(start, end, minStep, formatter);
    },

    /**
     * Get the milliseconds range
     * @param  {Number} hour
     * @param  {Number} minute
     * @param  {Number} second
     * @return {Array<Number>}
     */

    _getMillisecondsRange(hour, minute, second) {
      const start =
        hour * HOUR_IN_MS + minute * MINUTE_IN_MS + second * SECOND_IN_MS;
      const end = start + SECOND_IN_MS - 1;
      const minStep = 1;
      const formatter = time => new Date(time).getUTCMilliseconds();

      return this._getSteps(start, end, minStep, formatter);
    },

    /**
     * Calculate the range of possible steps.
     *
     * @param  {Number} startValue: Start time in ms
     * @param  {Number} endValue: End time in ms
     * @param  {Number} minStep: Smallest step in ms for the time unit
     * @param  {Function} formatter: Outputs time in a particular format
     * @return {Array<Object>}
     *         {
     *           {Number} value
     *           {Boolean} enabled
     *         }
     */

    _getSteps(startValue, endValue, minStep, formatter) {
      const { min, max, step } = this.props;
      // The timeStep should be big enough so that there won't be
      // duplications. Ex: minimum step for minute should be 60000ms,
      // if smaller than that, next step might return the same minute.
      const timeStep = Math.max(minStep, step);

      // Make sure the starting point and end point is not off step
      let time =
        min.valueOf() +
        Math.ceil((startValue - min.valueOf()) / timeStep) * timeStep;
      let maxValue =
        min.valueOf() +
        Math.floor((max.valueOf() - min.valueOf()) / step) * step;
      let steps = [];

      // Increment by timeStep until reaching the end of the range.
      while (time <= endValue) {
        steps.push({
          value: formatter(time),
          // Check if the value is within the min and max. If it's out of range,
          // also check for the case when minStep is too large, and has stepped out
          // of range when it should be enabled.
          enabled:
            (time >= min.valueOf() && time <= max.valueOf()) ||
            (time > maxValue &&
              startValue <= maxValue &&
              endValue >= maxValue &&
              formatter(time) == formatter(maxValue)),
        });
        time += timeStep;
      }

      return steps;
    },

    /**
     * A generic function for stepping up or down from a value of a range.
     * It stops at the upper and lower limits.
     *
     * @param  {Number} current: The current value
     * @param  {Number} offset: The offset relative to current value
     * @param  {Array<Object>} range: List of possible steps
     * @return {Number} The new value
     */

    _step(current, offset, range) {
      const index = range.findIndex(step => step.value == current);
      const newIndex =
        offset > 0
          ? Math.min(index + offset, range.length - 1)
          : Math.max(index + offset, 0);
      return range[newIndex].value;
    },

    /**
     * Step up or down AM/PM
     *
     * @param  {Number} offset
     */

    stepDayPeriodBy(offset) {
      const current = this.dayPeriod;
      const dayPeriod = this._step(
        current,
        offset,
        this.state.ranges.dayPeriod
      );

      if (current != dayPeriod) {
        this.hour < DAY_PERIOD_IN_HOURS
          ? this.setState({ hour: this.hour + DAY_PERIOD_IN_HOURS })
          : this.setState({ hour: this.hour - DAY_PERIOD_IN_HOURS });
      }
    },

    /**
     * Step up or down hours
     *
     * @param  {Number} offset
     */

    stepHourBy(offset) {
      const current = this.hour;
      const hour = this._step(current, offset, this.state.ranges.hours);

      if (current != hour) {
        this.setState({ hour });
      }
    },

    /**
     * Step up or down minutes
     *
     * @param  {Number} offset
     */

    stepMinuteBy(offset) {
      const current = this.minute;
      const minute = this._step(current, offset, this.state.ranges.minutes);

      if (current != minute) {
        this.setState({ minute });
      }
    },

    /**
     * Step up or down seconds
     *
     * @param  {Number} offset
     */

    stepSecondBy(offset) {
      const current = this.second;
      const second = this._step(current, offset, this.state.ranges.seconds);

      if (current != second) {
        this.setState({ second });
      }
    },

    /**
     * Step up or down milliseconds
     *
     * @param  {Number} offset
     */

    stepMillisecondBy(offset) {
      const current = this.milliseconds;
      const millisecond = this._step(
        current,
        offset,
        this.state.ranges.millisecond
      );

      if (current != millisecond) {
        this.setState({ millisecond });
      }
    },

    /**
     * Checks if the time state is off step.
     *
     * @param  {Date} time
     * @return {Boolean}
     */

    _isOffStep(time) {
      const { min, step } = this.props;

      return (time.valueOf() - min.valueOf()) % step != 0;
    },
  };
}

Messung V0.5
C=93 H=99 G=95

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge