diff options
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/anonymous.test.ts | 32 | ||||
-rw-r--r-- | src/utils/anonymous.ts | 1 | ||||
-rw-r--r-- | src/utils/datetime.ts | 18 | ||||
-rw-r--r-- | src/utils/iterator.ts | 27 |
4 files changed, 78 insertions, 0 deletions
diff --git a/src/utils/anonymous.test.ts b/src/utils/anonymous.test.ts index 2da613f..45896bf 100644 --- a/src/utils/anonymous.test.ts +++ b/src/utils/anonymous.test.ts @@ -9,6 +9,7 @@ import { identity, instanciate, pass, + transform, } from "./anonymous.ts"; import { assertSpyCalls, spy } from "@std/testing/mock"; import { FALSE, TRUE } from "../../tests/fixtures/test_data.ts"; @@ -128,3 +129,34 @@ describe("extremeBy", () => { assertEquals(extremeBy(data, "min"), Infinity); }); }); + +describe("transform", () => { + it("applies the function to the input", () => { + const result = transform(5, (x) => x * 2); + assertEquals(result, 10); + }); + + it("works with strings", () => { + const result = transform("hello", (x) => x.toUpperCase()); + assertEquals(result, "HELLO"); + }); + + it("works with objects", () => { + const input = { a: 1, b: 2 }; + const result = transform(input, ({ a, b }) => a + b); + assertEquals(result, 3); + }); + + it("returns the correct type", () => { + const TRUE = true; + const FALSE = false; + const result = transform(TRUE, (x) => !x); + assertEquals(result, FALSE); + }); + + it("works with identity function", () => { + const input = [1, 2, 3]; + const result = transform(input, identity); + assertEquals(result, input); + }); +}); diff --git a/src/utils/anonymous.ts b/src/utils/anonymous.ts index ddd28bd..58e5a0a 100644 --- a/src/utils/anonymous.ts +++ b/src/utils/anonymous.ts @@ -23,3 +23,4 @@ export const pass = <T>(fn: (x: T) => void): (x: T) => T => (x: T): T => { export const equal = <T>(x: T): (y: T) => boolean => (y: T): boolean => x === y; export const extremeBy = (arr: number[], mode: "max" | "min"): number => Math[mode](...arr); +export const transform = <T, U>(x: T, y: (x: T) => U): U => y(x); diff --git a/src/utils/datetime.ts b/src/utils/datetime.ts index c32fde0..be2ce08 100644 --- a/src/utils/datetime.ts +++ b/src/utils/datetime.ts @@ -1,3 +1,5 @@ +import { createRanges } from "./iterator.ts"; + export function toIso8601Full(date: Date): string { const yearN = date.getFullYear(); const isNegativeYear = yearN <= 0; @@ -66,3 +68,19 @@ export function getRelativeTimeUnit( if (Math.abs(minutes) >= 1) return [Math.round(minutes), "minute"]; return [Math.round(seconds), "second"]; } + +export function listDates(dates: Date[], { date, locale, list }: { + date: Intl.DateTimeFormatOptions; + locale: Intl.LocalesArgument; + list: Intl.ListFormatOptions; +}): string { + const formatter = new Intl.DateTimeFormat(locale, date); + return new Intl.ListFormat(locale, list).format(dates.map(formatter.format)); +} + +export function listYearsWithRanges(years: number[], { locale, list }: { + locale: Intl.LocalesArgument; + list: Intl.ListFormatOptions; +}): string { + return new Intl.ListFormat(locale, list).format(createRanges(years)); +} diff --git a/src/utils/iterator.ts b/src/utils/iterator.ts index fa58fc9..43437b6 100644 --- a/src/utils/iterator.ts +++ b/src/utils/iterator.ts @@ -50,3 +50,30 @@ export async function findMapAsync<T, R>( return await tryNext(0); } + +export function createRanges(nums: Iterable<number>): string[] { + const ns = new Set(nums).values().toArray().sort(( + a, + b, + ) => a - b); + + const result = []; + let start = ns[0]; + let end = ns[0]; + + for (let i = 1; i <= ns.length; i++) { + if (ns[i] === end + 1) { + end = ns[i]; + } else { + if (start === end) { + result.push(`${start}`); + } else { + result.push(`${start}-${end}`); + } + start = ns[i]; + end = ns[i]; + } + } + + return result; +} |