Path: blob/main/components/gitpod-protocol/src/util/timeutil.ts
2500 views
/**1* Copyright (c) 2020 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import parseDuration from "parse-duration";78/**9* Returns the <code>day</code>th of the next month from <code>formDate</code>.10* If the next month does not have a <code>day</code>th, the last day of that11* month is taken.12* The time is copied from <code>fromDate</code>.13*14* @param fromDate15* @param day16*/17export function oneMonthLater(fromDate: string, day?: number): string {18const later = new Date(fromDate);19day = day || later.getDate();20const fromMonth = later.getMonth();21later.setDate(day);22later.setMonth(later.getMonth() + 1);23if (later.getMonth() - fromMonth > 1) {24later.setDate(0);25}26return later.toISOString();27}28export const yearsLater = (fromDate: string, years: number): string =>29liftDate1(fromDate, (d) => {30d.setUTCFullYear(d.getUTCFullYear() + years);31return d.toISOString();32});3334export const addMillis = (d1: string, millis: number) =>35liftDate1(d1, (d1) => new Date(d1.getTime() + millis).toISOString());36export const durationInHours = (d1: string, d2: string) =>37liftDate(d1, d2, (d1, d2) => millisecondsToHours(d1.getTime() - d2.getTime()));38export const durationInMillis = (d1: string, d2: string) => liftDate(d1, d2, (d1, d2) => d1.getTime() - d2.getTime());39export const isDateGreaterOrEqual = (d1: string, d2: string): boolean =>40liftDate(d1, d2, (d1, d2) => d1.getTime() >= d2.getTime());41export const isDateSmallerOrEqual = (d1: string, d2: string | undefined) => !d2 || d1 <= d2;42export const isDateSmaller = (d1: string, d2: string | undefined) => !d2 || d1 < d2;43export const oldest = (d1: string, d2: string): string => (d1 > d2 ? d1 : d2);44export const earliest = (d1: string, d2: string): string => (d1 < d2 ? d1 : d2);45export const orderAsc = (d1: string, d2: string): number => liftDate(d1, d2, (d1, d2) => d1.getTime() - d2.getTime());46export const liftDate1 = <T>(d1: string, f: (d1: Date) => T): T => f(new Date(d1));47export const liftDate = <T>(d1: string, d2: string, f: (d1: Date, d2: Date) => T): T => f(new Date(d1), new Date(d2));4849export function daysBefore(date: string, days: number): string {50const result = new Date(date);51result.setDate(result.getDate() - days);52return result.toISOString();53}5455export function hoursBefore(date: string, hours: number): string {56const result = new Date(date);57result.setHours(result.getHours() - hours);58return result.toISOString();59}6061export function hoursLater(date: string, hours: number): string {62const result = new Date(date);63result.setHours(result.getHours() + hours);64return result.toISOString();65}6667export function secondsBefore(date: string, seconds: number): string {68return new Date(new Date(date).getTime() - seconds * 1000).toISOString();69}7071export function rightAfter(date: string): string {72return new Date(new Date(date).getTime() + 1).toISOString();73}7475export function rightBefore(date: string): string {76return new Date(new Date(date).getTime() - 1).toISOString();77}7879export function durationLongerThanSeconds(time: number, durationSeconds: number, now: number = Date.now()): boolean {80return (now - time) / 1000 > durationSeconds;81}8283export function millisecondsToHours(milliseconds: number): number {84return milliseconds / 1000 / 60 / 60;85}8687export function hoursToMilliseconds(hours: number): number {88return hours * 60 * 60 * 1000;89}9091export function goDurationToHumanReadable(goDuration: string): string {92const durationMs = parseGoDurationToMs(goDuration);9394let remainingMs = durationMs;95const hours = Math.floor(remainingMs / (60 * 60 * 1000));96remainingMs = remainingMs - hours * 60 * 60 * 1000;9798const minutes = Math.floor(remainingMs / (60 * 1000));99remainingMs = remainingMs - minutes * 60 * 1000;100101const seconds = Math.floor(remainingMs / 1000);102remainingMs = remainingMs - seconds * 1000;103104const segments: string[] = [];105if (hours) {106segments.push(`${hours} hour${hours === 1 ? "" : "s"}`);107}108if (minutes) {109segments.push(`${minutes} minute${minutes === 1 ? "" : "s"}`);110}111if (seconds) {112segments.push(`${seconds} second${seconds === 1 ? "" : "s"}`);113}114115return segments.join(" ");116}117118export function parseGoDurationToMs(goDuration: string): number {119// Handle empty or whitespace-only strings as 0 duration120if (!goDuration || goDuration.trim() === "") {121return 0;122}123124const result = parseDuration(goDuration);125if (result === null || result === undefined) {126throw new Error(`Invalid Go duration format: ${goDuration}`);127}128return result;129}130131132