diff --git a/projects/cdk/date-time/test/time.spec.ts b/projects/cdk/date-time/test/time.spec.ts index b3fb25fcca5f..2adf472894c1 100644 --- a/projects/cdk/date-time/test/time.spec.ts +++ b/projects/cdk/date-time/test/time.spec.ts @@ -359,7 +359,28 @@ describe('TuiTime', () => { ms: -1000 * 60 * 60 - 1000 * 60 - 1000 - 10, }); - expect(increasedTime.toString()).toBe('03:23:55.990'); + expect(increasedTime.toString()).toBe('03:22:54.990'); + }); + + it('seconds are increased if milliseconds reach 1000', () => { + const time = new TuiTime(15, 0, 0, 999); + const increasedTime = time.shift({ms: 1}); + + expect(increasedTime.toString()).toBe('15:00:01'); + }); + + it('minutes are increased if seconds reach 60', () => { + const time = new TuiTime(15, 0, 59); + const increasedTime = time.shift({seconds: 1}); + + expect(increasedTime.toString()).toBe('15:01'); + }); + + it('hours are increased if minutes reach 60', () => { + const time = new TuiTime(15, 59); + const increasedTime = time.shift({minutes: 1}); + + expect(increasedTime.toString()).toBe('16:00'); }); }); diff --git a/projects/cdk/date-time/time.ts b/projects/cdk/date-time/time.ts index d1257674baf2..9d9406bbe638 100644 --- a/projects/cdk/date-time/time.ts +++ b/projects/cdk/date-time/time.ts @@ -8,6 +8,7 @@ import { MILLISECONDS_IN_DAY, MILLISECONDS_IN_HOUR, MILLISECONDS_IN_MINUTE, + MILLISECONDS_IN_SECOND, MINUTES_IN_HOUR, SECONDS_IN_MINUTE, } from './date-time'; @@ -162,27 +163,22 @@ export class TuiTime implements TuiTimeLike { * Shifts time by hours and minutes */ public shift({hours = 0, minutes = 0, seconds = 0, ms = 0}: TuiTimeLike): TuiTime { - const newMs = (1000 + this.ms + (ms % 1000)) % 1000; + const totalMs = + this.toAbsoluteMilliseconds() + + hours * MILLISECONDS_IN_HOUR + + minutes * MILLISECONDS_IN_MINUTE + + seconds * MILLISECONDS_IN_SECOND + + ms; + const totalSeconds = Math.floor(totalMs / MILLISECONDS_IN_SECOND); + const totalMinutes = Math.floor(totalSeconds / SECONDS_IN_MINUTE); + const totalHours = Math.floor(totalMinutes / MINUTES_IN_HOUR); - const secondsInMs = ms < 0 ? Math.ceil(ms / 1000) : Math.floor(ms / 1000); - const secondsToAdd = secondsInMs + seconds; - const newSeconds = (60 + this.seconds + (secondsToAdd % 60)) % 60; - - const minutesInSeconds = - secondsToAdd < 0 - ? Math.ceil(secondsToAdd / 60) - : Math.floor(secondsToAdd / 60); - const minutesToAdd = minutesInSeconds + minutes; - const newMinutes = (60 + this.minutes + (minutesToAdd % 60)) % 60; - - const hoursInMinutes = - minutesToAdd < 0 - ? Math.ceil(minutesToAdd / 60) - : Math.floor(minutesToAdd / 60); - const hoursToAdd = hoursInMinutes + hours; - const newHours = (24 + this.hours + (hoursToAdd % 24)) % 24; - - return new TuiTime(newHours, newMinutes, newSeconds, newMs); + return new TuiTime( + this.normalizeToRange(totalHours, HOURS_IN_DAY), + this.normalizeToRange(totalMinutes, MINUTES_IN_HOUR), + this.normalizeToRange(totalSeconds, SECONDS_IN_MINUTE), + this.normalizeToRange(totalMs, MILLISECONDS_IN_SECOND), + ); } /** @@ -241,4 +237,8 @@ export class TuiTime implements TuiTimeLike { return {meridiem, hours: hours % 12}; } + + private normalizeToRange(value: number, modulus: number): number { + return ((value % modulus) + modulus) % modulus; + } }