std/ulid/decode_time.ts

54 lines
1.6 KiB
TypeScript
Raw Normal View History

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// Copyright 2023 Yoshiya Hinosawa. All rights reserved. MIT license.
// Copyright 2017 Alizain Feerasta. All rights reserved. MIT license.
// This module is browser compatible.
import {
ENCODING,
ENCODING_LEN,
TIME_LEN,
TIME_MAX,
ULID_LEN,
} from "./_util.ts";
/**
* Extracts the number of milliseconds since the Unix epoch that had passed when
* the ULID was generated. If the ULID is malformed, an error will be thrown.
*
* @example Decode the time from a ULID
* ```ts
* import { decodeTime, ulid } from "@std/ulid";
* import { assertEquals } from "@std/assert";
*
* const timestamp = 150_000;
* const ulidString = ulid(timestamp);
*
* assertEquals(decodeTime(ulidString), timestamp);
* ```
*
* @param ulid The ULID to extract the timestamp from.
* @returns The number of milliseconds since the Unix epoch that had passed when the ULID was generated.
*/
export function decodeTime(ulid: string): number {
if (ulid.length !== ULID_LEN) {
throw new Error(`ULID must be exactly ${ULID_LEN} characters long`);
}
const time = ulid
.substring(0, TIME_LEN)
.split("")
.reverse()
.reduce((carry, char, index) => {
const encodingIndex = ENCODING.indexOf(char);
if (encodingIndex === -1) {
throw new Error(`Invalid ULID character found: ${char}`);
}
return (carry += encodingIndex * Math.pow(ENCODING_LEN, index));
}, 0);
if (time > TIME_MAX) {
throw new RangeError(
`ULID timestamp component exceeds maximum value of ${TIME_MAX}`,
);
}
return time;
}