Skip to content

Instantly share code, notes, and snippets.

@Shoghy
Last active March 25, 2025 21:49
Show Gist options
  • Select an option

  • Save Shoghy/93ced9fdef636169d194abc4e1121dc1 to your computer and use it in GitHub Desktop.

Select an option

Save Shoghy/93ced9fdef636169d194abc4e1121dc1 to your computer and use it in GitHub Desktop.
export interface TimeSpanProps {
ms?: number;
seconds?: number;
minutes?: number;
hours?: number;
days?: number;
}
export class TimeSpan {
private readonly _ms: number;
public static readonly MsPerSecond = 1000;
public static readonly MsPerMinute = 60_000;
public static readonly MsPerHour = 3_600_000;
public static readonly MsPerDay = 86_400_000;
get Ms(): number {
return this._ms % 1000;
}
get TotalMs(): number {
return this._ms;
}
get Seconds(): number {
return Math.floor(this._ms / TimeSpan.MsPerSecond) % 60;
}
get TotalSeconds(): number {
return this._ms / TimeSpan.MsPerSecond;
}
get Minutes(): number {
return Math.floor(this._ms / TimeSpan.MsPerMinute) % 60;
}
get TotalMinutes(): number {
return this._ms / TimeSpan.MsPerMinute;
}
get Hours(): number {
return Math.floor(this._ms / TimeSpan.MsPerHour) % 24;
}
get TotalHours(): number {
return this._ms / TimeSpan.MsPerHour;
}
get Days(): number {
return Math.floor(this._ms / TimeSpan.MsPerDay);
}
get TotalDays(): number {
return this._ms / TimeSpan.MsPerDay;
}
constructor(time: TimeSpanProps) {
let ms = 0;
if (time.ms !== undefined) {
ms += time.ms;
}
if (time.seconds !== undefined) {
ms += time.seconds * TimeSpan.MsPerSecond;
}
if (time.minutes !== undefined) {
ms += time.minutes * TimeSpan.MsPerMinute;
}
if (time.hours !== undefined) {
ms += time.hours * TimeSpan.MsPerHour;
}
if (time.days !== undefined) {
ms += time.days * TimeSpan.MsPerDay;
}
this._ms = Math.floor(ms);
}
static FromMs(ms: number): TimeSpan {
return new TimeSpan({ ms });
}
static FromSeconds(seconds: number): TimeSpan {
return new TimeSpan({ seconds });
}
static FromMinutes(minutes: number): TimeSpan {
return new TimeSpan({ minutes });
}
static FromHours(hours: number): TimeSpan {
return new TimeSpan({ hours });
}
static FromDays(days: number): TimeSpan {
return new TimeSpan({ days });
}
static FromDates(from: Date, to: Date): TimeSpan {
const ms = to.valueOf() - from.valueOf();
return new TimeSpan({ ms });
}
static TimeSinceDate(date: Date): TimeSpan {
const now = Date.now();
return new TimeSpan({ ms: now - date.valueOf() });
}
AddMs(ms: number): TimeSpan {
return new TimeSpan({ ms: this._ms + ms });
}
SubtractMs(ms: number): TimeSpan {
return new TimeSpan({ ms: this._ms - ms });
}
AddSeconds(seconds: number): TimeSpan {
return new TimeSpan({ ms: this._ms, seconds });
}
SubtractSeconds(seconds: number): TimeSpan {
return new TimeSpan({ ms: this._ms, seconds: -seconds });
}
AddMinutes(minutes: number): TimeSpan {
return new TimeSpan({ ms: this._ms, minutes });
}
SubtractMinutes(minutes: number): TimeSpan {
return new TimeSpan({ ms: this._ms, minutes: -minutes });
}
AddHours(hours: number): TimeSpan {
return new TimeSpan({ ms: this._ms, hours });
}
SubtractHours(hours: number): TimeSpan {
return new TimeSpan({ ms: this._ms, hours: -hours });
}
AddDays(days: number): TimeSpan {
return new TimeSpan({ ms: this._ms, days });
}
SubtractDays(days: number): TimeSpan {
return new TimeSpan({ ms: this._ms, days: -days });
}
AddTimeSpan(timeSpan: TimeSpan): TimeSpan {
return new TimeSpan({
ms: this._ms + timeSpan._ms,
});
}
SubtractTimeSpan(timeSpan: TimeSpan): TimeSpan {
return new TimeSpan({
ms: this._ms - timeSpan._ms,
});
}
/**
* @returns new Date(Date.now() + TotalMs)
*/
ToDate(): Date {
return new Date(Date.now() + this._ms);
}
Compare(timeSpan: TimeSpan): -1 | 0 | 1 {
if (this._ms > timeSpan._ms) return 1;
if (this._ms < timeSpan._ms) return -1;
return 0;
}
Duration(): TimeSpan {
return new TimeSpan({ ms: Math.abs(this._ms) });
}
Equals(timeSpan: TimeSpan): boolean {
return this._ms === timeSpan._ms;
}
Negate(): TimeSpan {
return new TimeSpan({ ms: -this._ms });
}
Multiply(factor: number): TimeSpan {
return new TimeSpan({ ms: this._ms * factor });
}
Divide(divisor: number): TimeSpan {
return new TimeSpan({ ms: this._ms / divisor });
}
GreaterThan(timeSpan: TimeSpan): boolean {
return this._ms > timeSpan._ms;
}
GreaterOrEqualTo(timeSpan: TimeSpan): boolean {
return this._ms >= timeSpan._ms;
}
LessThan(timeSpan: TimeSpan): boolean {
return this._ms < timeSpan._ms;
}
LessOrEqualTo(timeSpan: TimeSpan): boolean {
return this._ms <= timeSpan._ms;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment