112 lines
5.4 KiB
TypeScript
112 lines
5.4 KiB
TypeScript
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
|
|
import { test, expect } from "@perspective-dev/test";
|
|
import perspective from "../perspective_client";
|
|
|
|
const JAN_1_2024_UTC = 1704067200000;
|
|
|
|
test.describe("Date timezone invariance", function () {
|
|
let SAVED_TZ: string | undefined;
|
|
|
|
test.beforeEach(() => {
|
|
SAVED_TZ = process.env.TZ;
|
|
process.env.TZ = "Europe/Amsterdam";
|
|
});
|
|
|
|
test.afterEach(() => {
|
|
process.env.TZ = SAVED_TZ;
|
|
});
|
|
|
|
test("date strings serialize to UTC midnight epoch ms", async function () {
|
|
const table = await perspective.table({ d: "date" });
|
|
await table.update({ d: ["2024-01-01"] });
|
|
const view = await table.view();
|
|
const cols = (await view.to_columns()) as { d: number[] };
|
|
expect(cols.d).toEqual([JAN_1_2024_UTC]);
|
|
await view.delete();
|
|
await table.delete();
|
|
});
|
|
|
|
test("date epoch ms input round-trips exactly", async function () {
|
|
const table = await perspective.table({ d: "date" });
|
|
await table.update({ d: [JAN_1_2024_UTC] });
|
|
const view = await table.view();
|
|
const cols = (await view.to_columns()) as { d: number[] };
|
|
expect(cols.d).toEqual([JAN_1_2024_UTC]);
|
|
await view.delete();
|
|
await table.delete();
|
|
});
|
|
|
|
test("formatted output prints the stored calendar day", async function () {
|
|
const table = await perspective.table({ d: "date" });
|
|
await table.update({ d: ["2024-01-01"] });
|
|
const view = await table.view();
|
|
expect(await view.to_columns_string({ formatted: true })).toEqual(
|
|
'{"d":["2024-01-01"]}',
|
|
);
|
|
expect(await view.to_csv()).toEqual('"d"\n2024-01-01\n');
|
|
await view.delete();
|
|
await table.delete();
|
|
});
|
|
|
|
test("day_bucket stays on the UTC calendar day at the day boundary", async function () {
|
|
const table = await perspective.table({ t: "datetime" });
|
|
|
|
// 23:59 UTC is already the next day in Europe/Amsterdam
|
|
await table.update({ t: ["2020-01-31 23:59:00"] });
|
|
const view = await table.view({
|
|
expressions: { bucket: `bucket("t", 'D')` },
|
|
});
|
|
|
|
const cols = (await view.to_columns()) as { bucket: number[] };
|
|
|
|
// 2020-01-31T00:00:00Z
|
|
expect(cols.bucket).toEqual([1580428800000]);
|
|
await view.delete();
|
|
await table.delete();
|
|
});
|
|
|
|
test("day_of_week and hour_of_day compute in UTC", async function () {
|
|
const table = await perspective.table({ t: "datetime" });
|
|
await table.update({ t: ["2020-01-31 23:59:00"] });
|
|
const view = await table.view({
|
|
expressions: {
|
|
dow: `day_of_week("t")`,
|
|
hod: `hour_of_day("t")`,
|
|
},
|
|
});
|
|
|
|
const cols = (await view.to_columns()) as {
|
|
dow: string[];
|
|
hod: number[];
|
|
};
|
|
|
|
// Friday 23:00 UTC, not Saturday 00:59 Amsterdam
|
|
expect(cols.dow).toEqual(["6 Friday"]);
|
|
expect(cols.hod).toEqual([23]);
|
|
await view.delete();
|
|
await table.delete();
|
|
});
|
|
|
|
test("JSON date output agrees with Arrow date32 day arithmetic", async function () {
|
|
const table = await perspective.table({ d: "date" });
|
|
await table.update({ d: ["2024-01-01"] });
|
|
const view = await table.view();
|
|
const cols = (await view.to_columns()) as { d: number[] };
|
|
expect(cols.d[0] % 86400000).toEqual(0);
|
|
expect(cols.d[0] / 86400000).toEqual(19723); // days since epoch
|
|
await view.delete();
|
|
await table.delete();
|
|
});
|
|
});
|