Skip to content

Commit

Permalink
fix(cdk): TuiTime.shift doesn't shift higher order units
Browse files Browse the repository at this point in the history
  • Loading branch information
reverie3 authored and splincode committed Jan 9, 2025
1 parent c7f5c8c commit 06a0577
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 22 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 @@ -330,7 +330,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
42 changes: 21 additions & 21 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 @@ -138,27 +139,22 @@ export class TuiTime implements TuiTimeLike {
* Shifts time by hours and minutes
*/
shift({hours = 0, minutes = 0, seconds = 0, ms = 0}: TuiTimeLike): TuiTime {
const newMs = (1000 + this.ms + (ms % 1000)) % 1000;

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);
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);

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 @@ -204,4 +200,8 @@ export class TuiTime implements TuiTimeLike {
private formatTime(time: number, digits: number = 2): string {
return String(time).padStart(digits, '0');
}

private normalizeToRange(value: number, modulus: number): number {
return ((value % modulus) + modulus) % modulus;
}
}

0 comments on commit 06a0577

Please sign in to comment.