summaryrefslogtreecommitdiff
path: root/std/datetime
diff options
context:
space:
mode:
authorCasper Beyer <caspervonb@pm.me>2021-02-02 19:05:46 +0800
committerGitHub <noreply@github.com>2021-02-02 12:05:46 +0100
commit6abf126c2a7a451cded8c6b5e6ddf1b69c84055d (patch)
treefd94c013a19fcb38954844085821ec1601c20e18 /std/datetime
parenta2b5d44f1aa9d64f448a2a3cc2001272e2f60b98 (diff)
chore: remove std directory (#9361)
This removes the std folder from the tree. Various parts of the tests are pretty tightly dependent on std (47 direct imports and 75 indirect imports, not counting the cli tests that use them as fixtures) so I've added std as a submodule for now.
Diffstat (limited to 'std/datetime')
-rw-r--r--std/datetime/README.md188
-rw-r--r--std/datetime/formatter.ts594
-rw-r--r--std/datetime/mod.ts249
-rw-r--r--std/datetime/test.ts393
-rw-r--r--std/datetime/tokenizer.ts76
5 files changed, 0 insertions, 1500 deletions
diff --git a/std/datetime/README.md b/std/datetime/README.md
deleted file mode 100644
index b168cd08b..000000000
--- a/std/datetime/README.md
+++ /dev/null
@@ -1,188 +0,0 @@
-# datetime
-
-Simple helper to help parse date strings into `Date`, with additional functions.
-
-## Usage
-
-The following symbols from
-[unicode LDML](http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)
-are supported:
-
-- `yyyy` - numeric year.
-- `yy` - 2-digit year.
-- `M` - numeric month.
-- `MM` - 2-digit month.
-- `d` - numeric day.
-- `dd` - 2-digit day.
-
-- `H` - numeric hour (0-23 hours).
-- `HH` - 2-digit hour (00-23 hours).
-- `h` - numeric hour (1-12 hours).
-- `hh` - 2-digit hour (01-12 hours).
-- `m` - numeric minute.
-- `mm` - 2-digit minute.
-- `s` - numeric second.
-- `ss` - 2-digit second.
-- `S` - 1-digit fractionalSecond.
-- `SS` - 2-digit fractionalSecond.
-- `SSS` - 3-digit fractionalSecond.
-
-- `a` - dayPeriod, either `AM` or `PM`.
-
-- `'foo'` - quoted literal.
-- `./-` - unquoted literal.
-
-## Methods
-
-### parse
-
-Takes an input `string` and a `formatString` to parse to a `date`.
-
-```ts
-import { parse } from 'https://deno.land/std@$STD_VERSION/datetime/mod.ts'
-
-parse("20-01-2019", "dd-MM-yyyy") // output : new Date(2019, 0, 20)
-parse("2019-01-20", "yyyy-MM-dd") // output : new Date(2019, 0, 20)
-parse("20.01.2019", "dd.MM.yyyy") // output : new Date(2019, 0, 20)
-parse("01-20-2019 16:34", "MM-dd-yyyy HH:mm") // output : new Date(2019, 0, 20, 16, 34)
-parse("01-20-2019 04:34 PM", "MM-dd-yyyy hh:mm a") // output : new Date(2019, 0, 20, 16, 34)
-parse("16:34 01-20-2019", "HH:mm MM-dd-yyyy") // output : new Date(2019, 0, 20, 16, 34)
-parse("01-20-2019 16:34:23.123", "MM-dd-yyyy HH:mm:ss.SSS") // output : new Date(2019, 0, 20, 16, 34, 23, 123)
-...
-```
-
-### format
-
-Takes an input `date` and a `formatString` to format to a `string`.
-
-```ts
-import { format } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-format(new Date(2019, 0, 20), "dd-MM-yyyy"); // output : "20-01-2019"
-format(new Date(2019, 0, 20), "yyyy-MM-dd"); // output : "2019-01-20"
-format(new Date(2019, 0, 20), "dd.MM.yyyy"); // output : "2019-01-20"
-format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy HH:mm"); // output : "01-20-2019 16:34"
-format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy hh:mm a"); // output : "01-20-2019 04:34 PM"
-format(new Date(2019, 0, 20, 16, 34), "HH:mm MM-dd-yyyy"); // output : "16:34 01-20-2019"
-format(new Date(2019, 0, 20, 16, 34, 23, 123), "MM-dd-yyyy HH:mm:ss.SSS"); // output : "01-20-2019 16:34:23.123"
-format(new Date(2019, 0, 20), "'today:' yyyy-MM-dd"); // output : "today: 2019-01-20"
-```
-
-### dayOfYear
-
-Returns the number of the day in the year.
-
-```ts
-import { dayOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-dayOfYear(new Date("2019-03-11T03:24:00")); // output: 70
-```
-
-### weekOfYear
-
-Returns the ISO week number of the provided date (1-53).
-
-```ts
-import { weekOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-weekOfYear(new Date("2020-12-28T03:24:00")); // Returns 53
-```
-
-### toIMF
-
-Formats the given date to IMF date time format. (Reference:
-https://tools.ietf.org/html/rfc7231#section-7.1.1.1 )
-
-```js
-import { toIMF } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-toIMF(new Date(0)); // => returns "Thu, 01 Jan 1970 00:00:00 GMT"
-```
-
-### isLeap
-
-Returns true if the given date or year (in number) is a leap year. Returns false
-otherwise.
-
-```js
-import { isLeap } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-isLeap(new Date("1970-01-01")); // => returns false
-isLeap(new Date("1972-01-01")); // => returns true
-isLeap(new Date("2000-01-01")); // => returns true
-isLeap(new Date("2100-01-01")); // => returns false
-isLeap(1972); // => returns true
-```
-
-### difference
-
-Returns the difference of the 2 given dates in the given units. If the units are
-omitted, it returns the difference in the all available units.
-
-Available units: "milliseconds", "seconds", "minutes", "hours", "days", "weeks",
-"months", "quarters", "years"
-
-```js
-import { difference } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-const date0 = new Date("2018-05-14");
-const date1 = new Date("2020-05-13");
-
-difference(date0, date1, { units: ["days", "months", "years"] });
-// => returns { days: 730, months: 23, years: 1 }
-
-difference(date0, date1);
-// => returns {
-// milliseconds: 63072000000,
-// seconds: 63072000,
-// minutes: 1051200,
-// hours: 17520,
-// days: 730,
-// weeks: 104,
-// months: 23,
-// quarters: 5,
-// years: 1
-// }
-```
-
-## Constants
-
-### SECOND
-
-```
-import { SECOND } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-console.log(SECOND); // => 1000
-```
-
-### MINUTE
-
-```
-import { MINUTE } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-console.log(MINUTE); // => 60000 (60 * 1000)
-```
-
-### HOUR
-
-```
-import { HOUR } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-console.log(HOUR); // => 3600000 (60 * 60 * 1000)
-```
-
-### DAY
-
-```
-import { DAY } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-console.log(DAY); // => 86400000 (24 * 60 * 60 * 1000)
-```
-
-### WEEK
-
-```
-import { WEEK } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
-
-console.log(WEEK); // => 604800000 (7 * 24 * 60 * 60 * 1000)
-```
diff --git a/std/datetime/formatter.ts b/std/datetime/formatter.ts
deleted file mode 100644
index 788de6d00..000000000
--- a/std/datetime/formatter.ts
+++ /dev/null
@@ -1,594 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import {
- CallbackResult,
- ReceiverResult,
- Rule,
- TestFunction,
- TestResult,
- Tokenizer,
-} from "./tokenizer.ts";
-
-function digits(value: string | number, count = 2): string {
- return String(value).padStart(count, "0");
-}
-
-// as declared as in namespace Intl
-type DateTimeFormatPartTypes =
- | "day"
- | "dayPeriod"
- // | "era"
- | "hour"
- | "literal"
- | "minute"
- | "month"
- | "second"
- | "timeZoneName"
- // | "weekday"
- | "year"
- | "fractionalSecond";
-
-interface DateTimeFormatPart {
- type: DateTimeFormatPartTypes;
- value: string;
-}
-
-type TimeZone = "UTC";
-
-interface Options {
- timeZone?: TimeZone;
-}
-
-function createLiteralTestFunction(value: string): TestFunction {
- return (string: string): TestResult => {
- return string.startsWith(value)
- ? { value, length: value.length }
- : undefined;
- };
-}
-
-function createMatchTestFunction(match: RegExp): TestFunction {
- return (string: string): TestResult => {
- const result = match.exec(string);
- if (result) return { value: result, length: result[0].length };
- };
-}
-
-// according to unicode symbols (http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)
-const defaultRules = [
- {
- test: createLiteralTestFunction("yyyy"),
- fn: (): CallbackResult => ({ type: "year", value: "numeric" }),
- },
- {
- test: createLiteralTestFunction("yy"),
- fn: (): CallbackResult => ({ type: "year", value: "2-digit" }),
- },
-
- {
- test: createLiteralTestFunction("MM"),
- fn: (): CallbackResult => ({ type: "month", value: "2-digit" }),
- },
- {
- test: createLiteralTestFunction("M"),
- fn: (): CallbackResult => ({ type: "month", value: "numeric" }),
- },
- {
- test: createLiteralTestFunction("dd"),
- fn: (): CallbackResult => ({ type: "day", value: "2-digit" }),
- },
- {
- test: createLiteralTestFunction("d"),
- fn: (): CallbackResult => ({ type: "day", value: "numeric" }),
- },
-
- {
- test: createLiteralTestFunction("HH"),
- fn: (): CallbackResult => ({ type: "hour", value: "2-digit" }),
- },
- {
- test: createLiteralTestFunction("H"),
- fn: (): CallbackResult => ({ type: "hour", value: "numeric" }),
- },
- {
- test: createLiteralTestFunction("hh"),
- fn: (): CallbackResult => ({
- type: "hour",
- value: "2-digit",
- hour12: true,
- }),
- },
- {
- test: createLiteralTestFunction("h"),
- fn: (): CallbackResult => ({
- type: "hour",
- value: "numeric",
- hour12: true,
- }),
- },
- {
- test: createLiteralTestFunction("mm"),
- fn: (): CallbackResult => ({ type: "minute", value: "2-digit" }),
- },
- {
- test: createLiteralTestFunction("m"),
- fn: (): CallbackResult => ({ type: "minute", value: "numeric" }),
- },
- {
- test: createLiteralTestFunction("ss"),
- fn: (): CallbackResult => ({ type: "second", value: "2-digit" }),
- },
- {
- test: createLiteralTestFunction("s"),
- fn: (): CallbackResult => ({ type: "second", value: "numeric" }),
- },
- {
- test: createLiteralTestFunction("SSS"),
- fn: (): CallbackResult => ({ type: "fractionalSecond", value: 3 }),
- },
- {
- test: createLiteralTestFunction("SS"),
- fn: (): CallbackResult => ({ type: "fractionalSecond", value: 2 }),
- },
- {
- test: createLiteralTestFunction("S"),
- fn: (): CallbackResult => ({ type: "fractionalSecond", value: 1 }),
- },
-
- {
- test: createLiteralTestFunction("a"),
- fn: (value: unknown): CallbackResult => ({
- type: "dayPeriod",
- value: value as string,
- }),
- },
-
- // quoted literal
- {
- test: createMatchTestFunction(/^(')(?<value>\\.|[^\']*)\1/),
- fn: (match: unknown): CallbackResult => ({
- type: "literal",
- value: (match as RegExpExecArray).groups!.value as string,
- }),
- },
- // literal
- {
- test: createMatchTestFunction(/^.+?\s*/),
- fn: (match: unknown): CallbackResult => ({
- type: "literal",
- value: (match as RegExpExecArray)[0],
- }),
- },
-];
-
-type FormatPart = {
- type: DateTimeFormatPartTypes;
- value: string | number;
- hour12?: boolean;
-};
-type Format = FormatPart[];
-
-export class DateTimeFormatter {
- #format: Format;
-
- constructor(formatString: string, rules: Rule[] = defaultRules) {
- const tokenizer = new Tokenizer(rules);
- this.#format = tokenizer.tokenize(
- formatString,
- ({ type, value, hour12 }) => {
- const result = {
- type,
- value,
- } as unknown as ReceiverResult;
- if (hour12) result.hour12 = hour12 as boolean;
- return result;
- },
- ) as Format;
- }
-
- format(date: Date, options: Options = {}): string {
- let string = "";
-
- const utc = options.timeZone === "UTC";
-
- for (const token of this.#format) {
- const type = token.type;
-
- switch (type) {
- case "year": {
- const value = utc ? date.getUTCFullYear() : date.getFullYear();
- switch (token.value) {
- case "numeric": {
- string += value;
- break;
- }
- case "2-digit": {
- string += digits(value, 2).slice(-2);
- break;
- }
- default:
- throw Error(
- `FormatterError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "month": {
- const value = (utc ? date.getUTCMonth() : date.getMonth()) + 1;
- switch (token.value) {
- case "numeric": {
- string += value;
- break;
- }
- case "2-digit": {
- string += digits(value, 2);
- break;
- }
- default:
- throw Error(
- `FormatterError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "day": {
- const value = utc ? date.getUTCDate() : date.getDate();
- switch (token.value) {
- case "numeric": {
- string += value;
- break;
- }
- case "2-digit": {
- string += digits(value, 2);
- break;
- }
- default:
- throw Error(
- `FormatterError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "hour": {
- let value = utc ? date.getUTCHours() : date.getHours();
- value -= token.hour12 && date.getHours() > 12 ? 12 : 0;
- switch (token.value) {
- case "numeric": {
- string += value;
- break;
- }
- case "2-digit": {
- string += digits(value, 2);
- break;
- }
- default:
- throw Error(
- `FormatterError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "minute": {
- const value = utc ? date.getUTCMinutes() : date.getMinutes();
- switch (token.value) {
- case "numeric": {
- string += value;
- break;
- }
- case "2-digit": {
- string += digits(value, 2);
- break;
- }
- default:
- throw Error(
- `FormatterError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "second": {
- const value = utc ? date.getUTCSeconds() : date.getSeconds();
- switch (token.value) {
- case "numeric": {
- string += value;
- break;
- }
- case "2-digit": {
- string += digits(value, 2);
- break;
- }
- default:
- throw Error(
- `FormatterError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "fractionalSecond": {
- const value = utc
- ? date.getUTCMilliseconds()
- : date.getMilliseconds();
- string += digits(value, Number(token.value));
- break;
- }
- // FIXME(bartlomieju)
- case "timeZoneName": {
- // string += utc ? "Z" : token.value
- break;
- }
- case "dayPeriod": {
- string += token.value ? (date.getHours() >= 12 ? "PM" : "AM") : "";
- break;
- }
- case "literal": {
- string += token.value;
- break;
- }
-
- default:
- throw Error(`FormatterError: { ${token.type} ${token.value} }`);
- }
- }
-
- return string;
- }
-
- parseToParts(string: string): DateTimeFormatPart[] {
- const parts: DateTimeFormatPart[] = [];
-
- for (const token of this.#format) {
- const type = token.type;
-
- let value = "";
- switch (token.type) {
- case "year": {
- switch (token.value) {
- case "numeric": {
- value = /^\d{1,4}/.exec(string)?.[0] as string;
- break;
- }
- case "2-digit": {
- value = /^\d{1,2}/.exec(string)?.[0] as string;
- break;
- }
- }
- break;
- }
- case "month": {
- switch (token.value) {
- case "numeric": {
- value = /^\d{1,2}/.exec(string)?.[0] as string;
- break;
- }
- case "2-digit": {
- value = /^\d{2}/.exec(string)?.[0] as string;
- break;
- }
- case "narrow": {
- value = /^[a-zA-Z]+/.exec(string)?.[0] as string;
- break;
- }
- case "short": {
- value = /^[a-zA-Z]+/.exec(string)?.[0] as string;
- break;
- }
- case "long": {
- value = /^[a-zA-Z]+/.exec(string)?.[0] as string;
- break;
- }
- default:
- throw Error(
- `ParserError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "day": {
- switch (token.value) {
- case "numeric": {
- value = /^\d{1,2}/.exec(string)?.[0] as string;
- break;
- }
- case "2-digit": {
- value = /^\d{2}/.exec(string)?.[0] as string;
- break;
- }
- default:
- throw Error(
- `ParserError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "hour": {
- switch (token.value) {
- case "numeric": {
- value = /^\d{1,2}/.exec(string)?.[0] as string;
- if (token.hour12 && parseInt(value) > 12) {
- console.error(
- `Trying to parse hour greater than 12. Use 'H' instead of 'h'.`,
- );
- }
- break;
- }
- case "2-digit": {
- value = /^\d{2}/.exec(string)?.[0] as string;
- if (token.hour12 && parseInt(value) > 12) {
- console.error(
- `Trying to parse hour greater than 12. Use 'HH' instead of 'hh'.`,
- );
- }
- break;
- }
- default:
- throw Error(
- `ParserError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "minute": {
- switch (token.value) {
- case "numeric": {
- value = /^\d{1,2}/.exec(string)?.[0] as string;
- break;
- }
- case "2-digit": {
- value = /^\d{2}/.exec(string)?.[0] as string;
- break;
- }
- default:
- throw Error(
- `ParserError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "second": {
- switch (token.value) {
- case "numeric": {
- value = /^\d{1,2}/.exec(string)?.[0] as string;
- break;
- }
- case "2-digit": {
- value = /^\d{2}/.exec(string)?.[0] as string;
- break;
- }
- default:
- throw Error(
- `ParserError: value "${token.value}" is not supported`,
- );
- }
- break;
- }
- case "fractionalSecond": {
- value = new RegExp(`^\\d{${token.value}}`).exec(string)
- ?.[0] as string;
- break;
- }
- case "timeZoneName": {
- value = token.value as string;
- break;
- }
- case "dayPeriod": {
- value = /^(A|P)M/.exec(string)?.[0] as string;
- break;
- }
- case "literal": {
- if (!string.startsWith(token.value as string)) {
- throw Error(
- `Literal "${token.value}" not found "${string.slice(0, 25)}"`,
- );
- }
- value = token.value as string;
- break;
- }
-
- default:
- throw Error(`${token.type} ${token.value}`);
- }
-
- if (!value) {
- throw Error(
- `value not valid for token { ${type} ${value} } ${
- string.slice(
- 0,
- 25,
- )
- }`,
- );
- }
- parts.push({ type, value });
-
- string = string.slice(value.length);
- }
-
- if (string.length) {
- throw Error(
- `datetime string was not fully parsed! ${string.slice(0, 25)}`,
- );
- }
-
- return parts;
- }
-
- /** sort & filter dateTimeFormatPart */
- sortDateTimeFormatPart(parts: DateTimeFormatPart[]): DateTimeFormatPart[] {
- let result: DateTimeFormatPart[] = [];
- const typeArray = [
- "year",
- "month",
- "day",
- "hour",
- "minute",
- "second",
- "fractionalSecond",
- ];
- for (const type of typeArray) {
- const current = parts.findIndex((el) => el.type === type);
- if (current !== -1) {
- result = result.concat(parts.splice(current, 1));
- }
- }
- result = result.concat(parts);
- return result;
- }
-
- partsToDate(parts: DateTimeFormatPart[]): Date {
- const date = new Date();
- const utc = parts.find(
- (part) => part.type === "timeZoneName" && part.value === "UTC",
- );
-
- utc ? date.setUTCHours(0, 0, 0, 0) : date.setHours(0, 0, 0, 0);
- for (const part of parts) {
- switch (part.type) {
- case "year": {
- const value = Number(part.value.padStart(4, "20"));
- utc ? date.setUTCFullYear(value) : date.setFullYear(value);
- break;
- }
- case "month": {
- const value = Number(part.value) - 1;
- utc ? date.setUTCMonth(value) : date.setMonth(value);
- break;
- }
- case "day": {
- const value = Number(part.value);
- utc ? date.setUTCDate(value) : date.setDate(value);
- break;
- }
- case "hour": {
- let value = Number(part.value);
- const dayPeriod = parts.find(
- (part: DateTimeFormatPart) => part.type === "dayPeriod",
- );
- if (dayPeriod?.value === "PM") value += 12;
- utc ? date.setUTCHours(value) : date.setHours(value);
- break;
- }
- case "minute": {
- const value = Number(part.value);
- utc ? date.setUTCMinutes(value) : date.setMinutes(value);
- break;
- }
- case "second": {
- const value = Number(part.value);
- utc ? date.setUTCSeconds(value) : date.setSeconds(value);
- break;
- }
- case "fractionalSecond": {
- const value = Number(part.value);
- utc ? date.setUTCMilliseconds(value) : date.setMilliseconds(value);
- break;
- }
- }
- }
- return date;
- }
-
- parse(string: string): Date {
- const parts = this.parseToParts(string);
- const sortParts = this.sortDateTimeFormatPart(parts);
- return this.partsToDate(sortParts);
- }
-}
diff --git a/std/datetime/mod.ts b/std/datetime/mod.ts
deleted file mode 100644
index 8a3ec7c4f..000000000
--- a/std/datetime/mod.ts
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-import { DateTimeFormatter } from "./formatter.ts";
-
-export const SECOND = 1e3;
-export const MINUTE = SECOND * 60;
-export const HOUR = MINUTE * 60;
-export const DAY = HOUR * 24;
-export const WEEK = DAY * 7;
-const DAYS_PER_WEEK = 7;
-
-enum Day {
- Sun,
- Mon,
- Tue,
- Wed,
- Thu,
- Fri,
- Sat,
-}
-
-/**
- * Parse date from string using format string
- * @param dateString Date string
- * @param format Format string
- * @return Parsed date
- */
-export function parse(dateString: string, formatString: string): Date {
- const formatter = new DateTimeFormatter(formatString);
- const parts = formatter.parseToParts(dateString);
- const sortParts = formatter.sortDateTimeFormatPart(parts);
- return formatter.partsToDate(sortParts);
-}
-
-/**
- * Format date using format string
- * @param date Date
- * @param format Format string
- * @return formatted date string
- */
-export function format(date: Date, formatString: string): string {
- const formatter = new DateTimeFormatter(formatString);
- return formatter.format(date);
-}
-
-/**
- * Get number of the day in the year
- * @return Number of the day in year
- */
-export function dayOfYear(date: Date): number {
- // Values from 0 to 99 map to the years 1900 to 1999. All other values are the actual year. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date)
- // Using setFullYear as a workaround
-
- const yearStart = new Date(date);
-
- yearStart.setUTCFullYear(date.getUTCFullYear(), 0, 0);
- const diff = date.getTime() -
- yearStart.getTime() +
- (yearStart.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000;
-
- return Math.floor(diff / DAY);
-}
-/**
- * Get number of the week in the year (ISO-8601)
- * @return Number of the week in year
- */
-export function weekOfYear(date: Date): number {
- const workingDate = new Date(
- Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()),
- );
-
- const day = workingDate.getUTCDay();
-
- const nearestThursday = workingDate.getUTCDate() +
- Day.Thu -
- (day === Day.Sun ? DAYS_PER_WEEK : day);
-
- workingDate.setUTCDate(nearestThursday);
-
- // Get first day of year
- const yearStart = new Date(Date.UTC(workingDate.getUTCFullYear(), 0, 1));
-
- // return the calculated full weeks to nearest Thursday
- return Math.ceil((workingDate.getTime() - yearStart.getTime() + DAY) / WEEK);
-}
-
-/**
- * Parse a date to return a IMF formatted string date
- * RFC: https://tools.ietf.org/html/rfc7231#section-7.1.1.1
- * IMF is the time format to use when generating times in HTTP
- * headers. The time being formatted must be in UTC for Format to
- * generate the correct format.
- * @param date Date to parse
- * @return IMF date formatted string
- */
-export function toIMF(date: Date): string {
- function dtPad(v: string, lPad = 2): string {
- return v.padStart(lPad, "0");
- }
- const d = dtPad(date.getUTCDate().toString());
- const h = dtPad(date.getUTCHours().toString());
- const min = dtPad(date.getUTCMinutes().toString());
- const s = dtPad(date.getUTCSeconds().toString());
- const y = date.getUTCFullYear();
- const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
- const months = [
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov",
- "Dec",
- ];
- return `${days[date.getUTCDay()]}, ${d} ${
- months[date.getUTCMonth()]
- } ${y} ${h}:${min}:${s} GMT`;
-}
-
-/**
- * Check given year is a leap year or not.
- * based on : https://docs.microsoft.com/en-us/office/troubleshoot/excel/determine-a-leap-year
- * @param year year in number or Date format
- */
-export function isLeap(year: Date | number): boolean {
- const yearNumber = year instanceof Date ? year.getFullYear() : year;
- return (
- (yearNumber % 4 === 0 && yearNumber % 100 !== 0) || yearNumber % 400 === 0
- );
-}
-
-export type Unit =
- | "milliseconds"
- | "seconds"
- | "minutes"
- | "hours"
- | "days"
- | "weeks"
- | "months"
- | "quarters"
- | "years";
-
-export type DifferenceFormat = Partial<Record<Unit, number>>;
-
-export type DifferenceOptions = {
- units?: Unit[];
-};
-
-/**
- * Calculate difference between two dates.
- * @param from Year to calculate difference
- * @param to Year to calculate difference with
- * @param options Options for determining how to respond
- *
- * example :
- *
- * ```typescript
- * datetime.difference(new Date("2020/1/1"),new Date("2020/2/2"),{ units : ["days","months"] })
- * ```
- */
-export function difference(
- from: Date,
- to: Date,
- options?: DifferenceOptions,
-): DifferenceFormat {
- const uniqueUnits = options?.units ? [...new Set(options?.units)] : [
- "milliseconds",
- "seconds",
- "minutes",
- "hours",
- "days",
- "weeks",
- "months",
- "quarters",
- "years",
- ];
-
- const bigger = Math.max(from.getTime(), to.getTime());
- const smaller = Math.min(from.getTime(), to.getTime());
- const differenceInMs = bigger - smaller;
-
- const differences: DifferenceFormat = {};
-
- for (const uniqueUnit of uniqueUnits) {
- switch (uniqueUnit) {
- case "milliseconds":
- differences.milliseconds = differenceInMs;
- break;
- case "seconds":
- differences.seconds = Math.floor(differenceInMs / SECOND);
- break;
- case "minutes":
- differences.minutes = Math.floor(differenceInMs / MINUTE);
- break;
- case "hours":
- differences.hours = Math.floor(differenceInMs / HOUR);
- break;
- case "days":
- differences.days = Math.floor(differenceInMs / DAY);
- break;
- case "weeks":
- differences.weeks = Math.floor(differenceInMs / WEEK);
- break;
- case "months":
- differences.months = calculateMonthsDifference(bigger, smaller);
- break;
- case "quarters":
- differences.quarters = Math.floor(
- (typeof differences.months !== "undefined" &&
- differences.months / 4) ||
- calculateMonthsDifference(bigger, smaller) / 4,
- );
- break;
- case "years":
- differences.years = Math.floor(
- (typeof differences.months !== "undefined" &&
- differences.months / 12) ||
- calculateMonthsDifference(bigger, smaller) / 12,
- );
- break;
- }
- }
-
- return differences;
-}
-
-function calculateMonthsDifference(bigger: number, smaller: number): number {
- const biggerDate = new Date(bigger);
- const smallerDate = new Date(smaller);
- const yearsDiff = biggerDate.getFullYear() - smallerDate.getFullYear();
- const monthsDiff = biggerDate.getMonth() - smallerDate.getMonth();
- const calendarDifferences = Math.abs(yearsDiff * 12 + monthsDiff);
- const compareResult = biggerDate > smallerDate ? 1 : -1;
- biggerDate.setMonth(
- biggerDate.getMonth() - compareResult * calendarDifferences,
- );
- const isLastMonthNotFull = biggerDate > smallerDate
- ? 1
- : -1 === -compareResult
- ? 1
- : 0;
- const months = compareResult * (calendarDifferences - isLastMonthNotFull);
- return months === 0 ? 0 : months;
-}
diff --git a/std/datetime/test.ts b/std/datetime/test.ts
deleted file mode 100644
index b2614bc00..000000000
--- a/std/datetime/test.ts
+++ /dev/null
@@ -1,393 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import { assert, assertEquals, assertThrows } from "../testing/asserts.ts";
-import * as datetime from "./mod.ts";
-
-Deno.test({
- name: "[std/datetime] parse",
- fn: () => {
- assertEquals(
- datetime.parse("01-03-2019 16:30", "MM-dd-yyyy HH:mm"),
- new Date(2019, 0, 3, 16, 30),
- );
- assertEquals(
- datetime.parse("01.03.2019 16:30", "MM.dd.yyyy HH:mm"),
- new Date(2019, 0, 3, 16, 30),
- );
- assertEquals(
- datetime.parse("01.03.2019 16:30", "MM.dd.yyyy HH:mm"),
- new Date(2019, 0, 3, 16, 30),
- );
- assertEquals(
- datetime.parse("03-01-2019 16:31", "dd-MM-yyyy HH:mm"),
- new Date(2019, 0, 3, 16, 31),
- );
- assertEquals(
- datetime.parse("2019-01-03 16:32", "yyyy-MM-dd HH:mm"),
- new Date(2019, 0, 3, 16, 32),
- );
- assertEquals(
- datetime.parse("16:33 01-03-2019", "HH:mm MM-dd-yyyy"),
- new Date(2019, 0, 3, 16, 33),
- );
- assertEquals(
- datetime.parse("01-03-2019 16:33:23.123", "MM-dd-yyyy HH:mm:ss.SSS"),
- new Date(2019, 0, 3, 16, 33, 23, 123),
- );
- assertEquals(
- datetime.parse("01-03-2019 09:33 PM", "MM-dd-yyyy HH:mm a"),
- new Date(2019, 0, 3, 21, 33),
- );
- assertEquals(
- datetime.parse("16:34 03-01-2019", "HH:mm dd-MM-yyyy"),
- new Date(2019, 0, 3, 16, 34),
- );
- assertEquals(
- datetime.parse("16:35 2019-01-03", "HH:mm yyyy-MM-dd"),
- new Date(2019, 0, 3, 16, 35),
- );
- assertEquals(
- datetime.parse("01-03-2019", "MM-dd-yyyy"),
- new Date(2019, 0, 3),
- );
- assertEquals(
- datetime.parse("03-01-2019", "dd-MM-yyyy"),
- new Date(2019, 0, 3),
- );
- assertEquals(
- datetime.parse("31-10-2019", "dd-MM-yyyy"),
- new Date(2019, 9, 31),
- );
- assertEquals(
- datetime.parse("2019-01-03", "yyyy-MM-dd"),
- new Date(2019, 0, 3),
- );
- },
-});
-
-Deno.test({
- name: "[std/datetime] invalidParseDateTimeFormatThrows",
- fn: () => {
- assertThrows((): void => {
- // deno-lint-ignore no-explicit-any
- (datetime as any).parse("2019-01-01 00:00", "x-y-z");
- }, Error);
- assertThrows((): void => {
- // deno-lint-ignore no-explicit-any
- (datetime as any).parse("2019-01-01", "x-y-z");
- }, Error);
- },
-});
-
-Deno.test({
- name: "[std/datetime] format",
- fn: () => {
- // 00 hours
- assertEquals(
- "01:00:00",
- datetime.format(new Date("2019-01-01T01:00:00"), "HH:mm:ss"),
- );
- assertEquals(
- "13:00:00",
- datetime.format(new Date("2019-01-01T13:00:00"), "HH:mm:ss"),
- );
-
- // 12 hours
- assertEquals(
- "01:00:00",
- datetime.format(new Date("2019-01-01T01:00:00"), "hh:mm:ss"),
- );
- assertEquals(
- "01:00:00",
- datetime.format(new Date("2019-01-01T13:00:00"), "hh:mm:ss"),
- );
-
- // milliseconds
- assertEquals(
- "13:00:00.000",
- datetime.format(new Date("2019-01-01T13:00:00"), "HH:mm:ss.SSS"),
- );
- assertEquals(
- "13:00:00.000",
- datetime.format(new Date("2019-01-01T13:00:00.000"), "HH:mm:ss.SSS"),
- );
- assertEquals(
- "13:00:00.123",
- datetime.format(new Date("2019-01-01T13:00:00.123"), "HH:mm:ss.SSS"),
- );
-
- // day period
- assertEquals(
- "01:00:00 AM",
- datetime.format(new Date("2019-01-01T01:00:00"), "HH:mm:ss a"),
- );
- assertEquals(
- "01:00:00 AM",
- datetime.format(new Date("2019-01-01T01:00:00"), "hh:mm:ss a"),
- );
- assertEquals(
- "01:00:00 PM",
- datetime.format(new Date("2019-01-01T13:00:00"), "hh:mm:ss a"),
- );
- assertEquals(
- "21:00:00 PM",
- datetime.format(new Date("2019-01-01T21:00:00"), "HH:mm:ss a"),
- );
- assertEquals(
- "09:00:00 PM",
- datetime.format(new Date("2019-01-01T21:00:00"), "hh:mm:ss a"),
- );
-
- // quoted literal
- assertEquals(
- datetime.format(new Date(2019, 0, 20), "'today:' yyyy-MM-dd"),
- "today: 2019-01-20",
- );
- },
-});
-
-Deno.test({
- name: "[std/datetime] dayOfYear",
- fn: () => {
- // from https://golang.org/src/time/time_test.go
- // Test YearDay in several different scenarios
- // and corner cases
- // Non-leap-year tests
- assertEquals(datetime.dayOfYear(new Date("2007-01-01T00:00:00.000Z")), 1);
- assertEquals(datetime.dayOfYear(new Date("2007-01-15T00:00:00.000Z")), 15);
- assertEquals(datetime.dayOfYear(new Date("2007-02-01T00:00:00.000Z")), 32);
- assertEquals(datetime.dayOfYear(new Date("2007-02-15T00:00:00.000Z")), 46);
- assertEquals(datetime.dayOfYear(new Date("2007-03-01T00:00:00.000Z")), 60);
- assertEquals(datetime.dayOfYear(new Date("2007-03-15T00:00:00.000Z")), 74);
- assertEquals(datetime.dayOfYear(new Date("2007-04-01T00:00:00.000Z")), 91);
- assertEquals(datetime.dayOfYear(new Date("2007-12-31T00:00:00.000Z")), 365);
-
- // Leap-year tests
- assertEquals(datetime.dayOfYear(new Date("2008-01-01T00:00:00.000Z")), 1);
- assertEquals(datetime.dayOfYear(new Date("2008-01-15T00:00:00.000Z")), 15);
- assertEquals(datetime.dayOfYear(new Date("2008-02-01T00:00:00.000Z")), 32);
- assertEquals(datetime.dayOfYear(new Date("2008-02-15T00:00:00.000Z")), 46);
- assertEquals(datetime.dayOfYear(new Date("2008-03-01T00:00:00.000Z")), 61);
- assertEquals(datetime.dayOfYear(new Date("2008-03-15T00:00:00.000Z")), 75);
- assertEquals(datetime.dayOfYear(new Date("2008-04-01T00:00:00.000Z")), 92);
- assertEquals(datetime.dayOfYear(new Date("2008-12-31T00:00:00.000Z")), 366);
-
- // Looks like leap-year (but isn't) tests
- assertEquals(datetime.dayOfYear(new Date("1900-01-01T00:00:00.000Z")), 1);
- assertEquals(datetime.dayOfYear(new Date("1900-01-15T00:00:00.000Z")), 15);
- assertEquals(datetime.dayOfYear(new Date("1900-02-01T00:00:00.000Z")), 32);
- assertEquals(datetime.dayOfYear(new Date("1900-02-15T00:00:00.000Z")), 46);
- assertEquals(datetime.dayOfYear(new Date("1900-03-01T00:00:00.000Z")), 60);
- assertEquals(datetime.dayOfYear(new Date("1900-03-15T00:00:00.000Z")), 74);
- assertEquals(datetime.dayOfYear(new Date("1900-04-01T00:00:00.000Z")), 91);
- assertEquals(datetime.dayOfYear(new Date("1900-12-31T00:00:00.000Z")), 365);
-
- // Year one tests (non-leap)
- assertEquals(datetime.dayOfYear(new Date("0001-01-01T00:00:00.000Z")), 1);
- assertEquals(datetime.dayOfYear(new Date("0001-01-15T00:00:00.000Z")), 15);
- assertEquals(datetime.dayOfYear(new Date("0001-02-01T00:00:00.000Z")), 32);
- assertEquals(datetime.dayOfYear(new Date("0001-02-15T00:00:00.000Z")), 46);
- assertEquals(datetime.dayOfYear(new Date("0001-03-01T00:00:00.000Z")), 60);
- assertEquals(datetime.dayOfYear(new Date("0001-03-15T00:00:00.000Z")), 74);
- assertEquals(datetime.dayOfYear(new Date("0001-04-01T00:00:00.000Z")), 91);
- assertEquals(datetime.dayOfYear(new Date("0001-12-31T00:00:00.000Z")), 365);
-
- // Year minus one tests (non-leap)
- assertEquals(
- datetime.dayOfYear(new Date("-000001-01-01T00:00:00.000Z")),
- 1,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000001-01-15T00:00:00.000Z")),
- 15,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000001-02-01T00:00:00.000Z")),
- 32,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000001-02-15T00:00:00.000Z")),
- 46,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000001-03-01T00:00:00.000Z")),
- 60,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000001-03-15T00:00:00.000Z")),
- 74,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000001-04-01T00:00:00.000Z")),
- 91,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000001-12-31T00:00:00.000Z")),
- 365,
- );
-
- // 400 BC tests (leap-year)
- assertEquals(
- datetime.dayOfYear(new Date("-000400-01-01T00:00:00.000Z")),
- 1,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000400-01-15T00:00:00.000Z")),
- 15,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000400-02-01T00:00:00.000Z")),
- 32,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000400-02-15T00:00:00.000Z")),
- 46,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000400-03-01T00:00:00.000Z")),
- 61,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000400-03-15T00:00:00.000Z")),
- 75,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000400-04-01T00:00:00.000Z")),
- 92,
- );
- assertEquals(
- datetime.dayOfYear(new Date("-000400-12-31T00:00:00.000Z")),
- 366,
- );
-
- // Special Cases
-
- // Gregorian calendar change (no effect)
- assertEquals(datetime.dayOfYear(new Date("1582-10-04T03:24:00.000Z")), 277);
- assertEquals(datetime.dayOfYear(new Date("1582-10-15T03:24:00.000Z")), 288);
- },
-});
-
-Deno.test({
- name: "[std/datetime] weekOfYear",
- fn: () => {
- assertEquals(datetime.weekOfYear(new Date("2020-01-05T03:00:00.000Z")), 1);
- assertEquals(datetime.weekOfYear(new Date("2020-06-28T03:00:00.000Z")), 26);
-
- // iso weeks year starting sunday
- assertEquals(datetime.weekOfYear(new Date(2012, 0, 1)), 52);
- assertEquals(datetime.weekOfYear(new Date(2012, 0, 2)), 1);
- assertEquals(datetime.weekOfYear(new Date(2012, 0, 8)), 1);
- assertEquals(datetime.weekOfYear(new Date(2012, 0, 9)), 2);
- assertEquals(datetime.weekOfYear(new Date(2012, 0, 15)), 2);
-
- // iso weeks year starting monday
- assertEquals(datetime.weekOfYear(new Date(2007, 0, 1)), 1);
- assertEquals(datetime.weekOfYear(new Date(2007, 0, 7)), 1);
- assertEquals(datetime.weekOfYear(new Date(2007, 0, 8)), 2);
- assertEquals(datetime.weekOfYear(new Date(2007, 0, 14)), 2);
- assertEquals(datetime.weekOfYear(new Date(2007, 0, 15)), 3);
-
- // iso weeks year starting tuesday
- assertEquals(datetime.weekOfYear(new Date(2007, 11, 31)), 1);
- assertEquals(datetime.weekOfYear(new Date(2008, 0, 1)), 1);
- assertEquals(datetime.weekOfYear(new Date(2008, 0, 6)), 1);
- assertEquals(datetime.weekOfYear(new Date(2008, 0, 7)), 2);
- assertEquals(datetime.weekOfYear(new Date(2008, 0, 13)), 2);
- assertEquals(datetime.weekOfYear(new Date(2008, 0, 14)), 3);
-
- // iso weeks year starting wednesday
- assertEquals(datetime.weekOfYear(new Date(2002, 11, 30)), 1);
- assertEquals(datetime.weekOfYear(new Date(2003, 0, 1)), 1);
- assertEquals(datetime.weekOfYear(new Date(2003, 0, 5)), 1);
- assertEquals(datetime.weekOfYear(new Date(2003, 0, 6)), 2);
- assertEquals(datetime.weekOfYear(new Date(2003, 0, 12)), 2);
- assertEquals(datetime.weekOfYear(new Date(2003, 0, 13)), 3);
-
- // iso weeks year starting thursday
- assertEquals(datetime.weekOfYear(new Date(2008, 11, 29)), 1);
- assertEquals(datetime.weekOfYear(new Date(2009, 0, 1)), 1);
- assertEquals(datetime.weekOfYear(new Date(2009, 0, 4)), 1);
- assertEquals(datetime.weekOfYear(new Date(2009, 0, 5)), 2);
- assertEquals(datetime.weekOfYear(new Date(2009, 0, 11)), 2);
- assertEquals(datetime.weekOfYear(new Date(2009, 0, 13)), 3);
-
- // iso weeks year starting friday
- assertEquals(datetime.weekOfYear(new Date(2009, 11, 28)), 53);
- assertEquals(datetime.weekOfYear(new Date(2010, 0, 1)), 53);
- assertEquals(datetime.weekOfYear(new Date(2010, 0, 3)), 53);
- assertEquals(datetime.weekOfYear(new Date(2010, 0, 4)), 1);
- assertEquals(datetime.weekOfYear(new Date(2010, 0, 10)), 1);
- assertEquals(datetime.weekOfYear(new Date(2010, 0, 11)), 2);
-
- // iso weeks year starting saturday
- assertEquals(datetime.weekOfYear(new Date(2010, 11, 27)), 52);
- assertEquals(datetime.weekOfYear(new Date(2011, 0, 1)), 52);
- assertEquals(datetime.weekOfYear(new Date(2011, 0, 2)), 52);
- assertEquals(datetime.weekOfYear(new Date(2011, 0, 3)), 1);
- assertEquals(datetime.weekOfYear(new Date(2011, 0, 9)), 1);
- assertEquals(datetime.weekOfYear(new Date(2011, 0, 10)), 2);
- },
-});
-
-Deno.test({
- name: "[std/datetime] to IMF",
- fn(): void {
- const actual = datetime.toIMF(new Date(Date.UTC(1994, 3, 5, 15, 32)));
- const expected = "Tue, 05 Apr 1994 15:32:00 GMT";
- assertEquals(actual, expected);
- },
-});
-
-Deno.test({
- name: "[std/datetime] to IMF 0",
- fn(): void {
- const actual = datetime.toIMF(new Date(0));
- const expected = "Thu, 01 Jan 1970 00:00:00 GMT";
- assertEquals(actual, expected);
- },
-});
-
-Deno.test({
- name: "[std/datetime] isLeap",
- fn(): void {
- assert(datetime.isLeap(1992));
- assert(datetime.isLeap(2000));
- assert(!datetime.isLeap(2003));
- assert(!datetime.isLeap(2007));
- },
-});
-
-Deno.test({
- name: "[std/datetime] difference",
- fn(): void {
- const denoInit = new Date("2018/5/14");
- const denoReleaseV1 = new Date("2020/5/13");
- let difference = datetime.difference(denoReleaseV1, denoInit, {
- units: ["days", "months", "years"],
- });
- assertEquals(difference.days, 730);
- assertEquals(difference.months, 23);
- assertEquals(difference.years, 1);
-
- const birth = new Date("1998/2/23 10:10:10");
- const old = new Date("1998/2/23 11:11:11");
- difference = datetime.difference(birth, old, {
- units: ["milliseconds", "minutes", "seconds", "hours"],
- });
- assertEquals(difference.milliseconds, 3661000);
- assertEquals(difference.seconds, 3661);
- assertEquals(difference.minutes, 61);
- assertEquals(difference.hours, 1);
- },
-});
-
-Deno.test({
- name: "[std/datetime] constants",
- fn(): void {
- assertEquals(datetime.SECOND, 1e3);
- assertEquals(datetime.MINUTE, datetime.SECOND * 60);
- assertEquals(datetime.HOUR, datetime.MINUTE * 60);
- assertEquals(datetime.DAY, datetime.HOUR * 24);
- assertEquals(datetime.WEEK, datetime.DAY * 7);
- },
-});
diff --git a/std/datetime/tokenizer.ts b/std/datetime/tokenizer.ts
deleted file mode 100644
index 9a9d0daa8..000000000
--- a/std/datetime/tokenizer.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-export type Token = {
- type: string;
- value: string | number;
- index: number;
- [key: string]: unknown;
-};
-
-export interface ReceiverResult {
- [name: string]: string | number | unknown;
-}
-export type CallbackResult = {
- type: string;
- value: string | number;
- [key: string]: unknown;
-};
-type CallbackFunction = (value: unknown) => CallbackResult;
-
-export type TestResult = { value: unknown; length: number } | undefined;
-export type TestFunction = (
- string: string,
-) => TestResult | undefined;
-
-export interface Rule {
- test: TestFunction;
- fn: CallbackFunction;
-}
-
-export class Tokenizer {
- rules: Rule[];
-
- constructor(rules: Rule[] = []) {
- this.rules = rules;
- }
-
- addRule(test: TestFunction, fn: CallbackFunction): Tokenizer {
- this.rules.push({ test, fn });
- return this;
- }
-
- tokenize(
- string: string,
- receiver = (token: Token): ReceiverResult => token,
- ): ReceiverResult[] {
- function* generator(rules: Rule[]): IterableIterator<ReceiverResult> {
- let index = 0;
- for (const rule of rules) {
- const result = rule.test(string);
- if (result) {
- const { value, length } = result;
- index += length;
- string = string.slice(length);
- const token = { ...rule.fn(value), index };
- yield receiver(token);
- yield* generator(rules);
- }
- }
- }
- const tokenGenerator = generator(this.rules);
-
- const tokens: ReceiverResult[] = [];
-
- for (const token of tokenGenerator) {
- tokens.push(token);
- }
-
- if (string.length) {
- throw new Error(
- `parser error: string not fully parsed! ${string.slice(0, 25)}`,
- );
- }
-
- return tokens;
- }
-}