Skip to content

Commit

Permalink
fix(cdk): TuiTime.shift doesn't shift higher order units (#10065)
Browse files Browse the repository at this point in the history
  • Loading branch information
reverie3 authored Dec 26, 2024
1 parent 14426cd commit 5939585
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 21 deletions.
23 changes: 22 additions & 1 deletion projects/cdk/date-time/test/time.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
});

Expand Down
40 changes: 20 additions & 20 deletions projects/cdk/date-time/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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),
);
}

/**
Expand Down Expand Up @@ -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;
}
}

0 comments on commit 5939585

Please sign in to comment.