Work with a time span in Javascript

后端 未结 7 762
感动是毒
感动是毒 2020-11-30 05:53

Using Date.js already, but can also use another library if necessary.

Not sure what is the best way to work with time deltas. Specifically, I want to display the tim

7条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-11-30 06:23

    Here a .NET C# similar implementation of a timespan class that supports days, hours, minutes and seconds. This implementation also supports negative timespans.

    const MILLIS_PER_SECOND = 1000;
    const MILLIS_PER_MINUTE = MILLIS_PER_SECOND * 60;   //     60,000
    const MILLIS_PER_HOUR = MILLIS_PER_MINUTE * 60;     //  3,600,000
    const MILLIS_PER_DAY = MILLIS_PER_HOUR * 24;        // 86,400,000
    
    export class TimeSpan {
        private _millis: number;
    
        private static interval(value: number, scale: number): TimeSpan {
            if (Number.isNaN(value)) {
                throw new Error("value can't be NaN");
            }
    
            const tmp = value * scale;
            const millis = TimeSpan.round(tmp + (value >= 0 ? 0.5 : -0.5));
            if ((millis > TimeSpan.maxValue.totalMilliseconds) || (millis < TimeSpan.minValue.totalMilliseconds)) {
                throw new TimeSpanOverflowError("TimeSpanTooLong");
            }
    
            return new TimeSpan(millis);
        }
    
        private static round(n: number): number {
            if (n < 0) {
                return Math.ceil(n);
            } else if (n > 0) {
                return Math.floor(n);
            }
    
            return 0;
        }
    
        private static timeToMilliseconds(hour: number, minute: number, second: number): number {
            const totalSeconds = (hour * 3600) + (minute * 60) + second;
            if (totalSeconds > TimeSpan.maxValue.totalSeconds || totalSeconds < TimeSpan.minValue.totalSeconds) {
                throw new TimeSpanOverflowError("TimeSpanTooLong");
            }
    
            return totalSeconds * MILLIS_PER_SECOND;
        }
    
        public static get zero(): TimeSpan {
            return new TimeSpan(0);
        }
    
        public static get maxValue(): TimeSpan {
            return new TimeSpan(Number.MAX_SAFE_INTEGER);
        }
    
        public static get minValue(): TimeSpan {
            return new TimeSpan(Number.MIN_SAFE_INTEGER);
        }
    
        public static fromDays(value: number): TimeSpan {
            return TimeSpan.interval(value, MILLIS_PER_DAY);
        }
    
        public static fromHours(value: number): TimeSpan {
            return TimeSpan.interval(value, MILLIS_PER_HOUR);
        }
    
        public static fromMilliseconds(value: number): TimeSpan {
            return TimeSpan.interval(value, 1);
        }
    
        public static fromMinutes(value: number): TimeSpan {
            return TimeSpan.interval(value, MILLIS_PER_MINUTE);
        }
    
        public static fromSeconds(value: number): TimeSpan {
            return TimeSpan.interval(value, MILLIS_PER_SECOND);
        }
    
        public static fromTime(hours: number, minutes: number, seconds: number): TimeSpan;
        public static fromTime(days: number, hours: number, minutes: number, seconds: number, milliseconds: number): TimeSpan;
        public static fromTime(daysOrHours: number, hoursOrMinutes: number, minutesOrSeconds: number, seconds?: number, milliseconds?: number): TimeSpan {
            if (milliseconds != undefined) {
                return this.fromTimeStartingFromDays(daysOrHours, hoursOrMinutes, minutesOrSeconds, seconds, milliseconds);
            } else {
                return this.fromTimeStartingFromHours(daysOrHours, hoursOrMinutes, minutesOrSeconds);
            }
        }
    
        private static fromTimeStartingFromHours(hours: number, minutes: number, seconds: number): TimeSpan {
            const millis = TimeSpan.timeToMilliseconds(hours, minutes, seconds);
            return new TimeSpan(millis);
        }
    
        private static fromTimeStartingFromDays(days: number, hours: number, minutes: number, seconds: number, milliseconds: number): TimeSpan {
            const totalMilliSeconds = (days * MILLIS_PER_DAY) +
                (hours * MILLIS_PER_HOUR) +
                (minutes * MILLIS_PER_MINUTE) +
                (seconds * MILLIS_PER_SECOND) +
                milliseconds;
    
            if (totalMilliSeconds > TimeSpan.maxValue.totalMilliseconds || totalMilliSeconds < TimeSpan.minValue.totalMilliseconds) {
                throw new TimeSpanOverflowError("TimeSpanTooLong");
            }
            return new TimeSpan(totalMilliSeconds);
        }
    
        constructor(millis: number) {
            this._millis = millis;
        }
    
        public get days(): number {
            return TimeSpan.round(this._millis / MILLIS_PER_DAY);
        }
    
        public get hours(): number {
            return TimeSpan.round((this._millis / MILLIS_PER_HOUR) % 24);
        }
    
        public get minutes(): number {
            return TimeSpan.round((this._millis / MILLIS_PER_MINUTE) % 60);
        }
    
        public get seconds(): number {
            return TimeSpan.round((this._millis / MILLIS_PER_SECOND) % 60);
        }
    
        public get milliseconds(): number {
            return TimeSpan.round(this._millis % 1000);
        }
    
        public get totalDays(): number {
            return this._millis / MILLIS_PER_DAY;
        }
    
        public get totalHours(): number {
            return this._millis / MILLIS_PER_HOUR;
        }
    
        public get totalMinutes(): number {
            return this._millis / MILLIS_PER_MINUTE;
        }
    
        public get totalSeconds(): number {
            return this._millis / MILLIS_PER_SECOND;
        }
    
        public get totalMilliseconds(): number {
            return this._millis;
        }
    
        public add(ts: TimeSpan): TimeSpan {
            const result = this._millis + ts.totalMilliseconds;
            return new TimeSpan(result);
        }
    
        public subtract(ts: TimeSpan): TimeSpan {
            const result = this._millis - ts.totalMilliseconds;
            return new TimeSpan(result);
        }
    }
    

    How to use

    Create a new TimeSpan object

    From zero
    
        const ts = TimeSpan.zero;
    
    
    From milliseconds
    
        const milliseconds = 10000; // 1 second
    
        // by using the constructor
        const ts1 = new TimeSpan(milliseconds);
    
        // or as an alternative you can use the static factory method
        const ts2 = TimeSpan.fromMilliseconds(milliseconds);
    
    
    From seconds
    
        const seconds = 86400; // 1 day
        const ts = TimeSpan.fromSeconds(seconds);
    
    
    From minutes
    
        const minutes = 1440; // 1 day
        const ts = TimeSpan.fromMinutes(minutes);
    
    
    From hours
    
        const hours = 24; // 1 day
        const ts = TimeSpan.fromHours(hours);
    
    
    From days
    
        const days = 1; // 1 day
        const ts = TimeSpan.fromDays(days);
    
    
    From time with given hours, minutes and seconds
    
        const hours = 1;
        const minutes = 1;
        const seconds = 1;
        const ts = TimeSpan.fromTime(hours, minutes, seconds);
    
    
    From time2 with given days, hours, minutes, seconds and milliseconds
    
        const days = 1;
        const hours = 1;
        const minutes = 1;
        const seconds = 1;
        const milliseconds = 1;
        const ts = TimeSpan.fromTime(days, hours, minutes, seconds, milliseconds);
    
    
    From maximal safe integer
    
        const ts = TimeSpan.maxValue;
    
    
    From minimal safe integer
    
        const ts = TimeSpan.minValue;
    
    
    From minimal safe integer
    
        const ts = TimeSpan.minValue;
    
    
    Add
    
        const ts1 = TimeSpan.fromDays(1);
        const ts2 = TimeSpan.fromHours(1);
        const ts = ts1.add(ts2);
    
        console.log(ts.days);               // 1
        console.log(ts.hours);              // 1
        console.log(ts.minutes);            // 0
        console.log(ts.seconds);            // 0
        console.log(ts.milliseconds);           // 0
    
    
    Subtract
    
        const ts1 = TimeSpan.fromDays(1);
        const ts2 = TimeSpan.fromHours(1);
        const ts = ts1.subtract(ts2);
    
        console.log(ts.days);               // 0
        console.log(ts.hours);              // 23
        console.log(ts.minutes);            // 0
        console.log(ts.seconds);            // 0
        console.log(ts.milliseconds);           // 0
    
    
    Getting the intervals
    
        const days = 1;
        const hours = 1;
        const minutes = 1;
        const seconds = 1;
        const milliseconds = 1;
        const ts = TimeSpan.fromTime2(days, hours, minutes, seconds, milliseconds);
    
        console.log(ts.days);               // 1
        console.log(ts.hours);              // 1
        console.log(ts.minutes);            // 1
        console.log(ts.seconds);            // 1
        console.log(ts.milliseconds);           // 1
    
        console.log(ts.totalDays)           // 1.0423726967592593;
        console.log(ts.totalHours)          // 25.016944722222224;
        console.log(ts.totalMinutes)            // 1501.0166833333333;
        console.log(ts.totalSeconds)            // 90061.001;
        console.log(ts.totalMilliseconds);      // 90061001;
    
    

    See also here: https://github.com/erdas/timespan

提交回复
热议问题