mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-19 16:16:45 +00:00
fix(grid): keep tz-aware Now values and duckdb lockfile in sync
This commit is contained in:
Generated
-1
@@ -1252,7 +1252,6 @@ dependencies = [
|
||||
"fs2",
|
||||
"futures",
|
||||
"httpdate",
|
||||
"iana-time-zone",
|
||||
"insta",
|
||||
"json5",
|
||||
"jsonwebtoken",
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { FocusOutsideEvent, PointerDownOutsideEvent } from "reka-ui";
|
||||
import { CalendarClock, ChevronDown, ChevronUp, CircleSlash } from "@lucide/vue";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { formatTemporalInputValue, parseTemporalInputValue, stepTemporalInputValue, temporalOffsetSuffix, type TemporalCellEditorKind } from "@/lib/dataGrid/dataGridTemporalEditor";
|
||||
import { formatTemporalInputValue, hostTimezoneOffsetSuffix, parseTemporalInputValue, stepTemporalInputValue, temporalOffsetSuffix, type TemporalCellEditorKind } from "@/lib/dataGrid/dataGridTemporalEditor";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -192,9 +192,12 @@ function setNow() {
|
||||
const now = new Date();
|
||||
const dateText = [String(now.getFullYear()).padStart(4, "0"), String(now.getMonth() + 1).padStart(2, "0"), String(now.getDate()).padStart(2, "0")].join("-");
|
||||
const nextTime = [String(now.getHours()).padStart(2, "0"), String(now.getMinutes()).padStart(2, "0"), String(now.getSeconds()).padStart(2, "0")].join(":") + nowFractionSuffix(now);
|
||||
// tz-aware columns must carry an explicit offset, otherwise the server parses
|
||||
// the host wall clock in its own session timezone
|
||||
const offsetSuffix = temporalOffsetSuffix(localValue.value, props.kind) ? hostTimezoneOffsetSuffix(now) : "";
|
||||
if (props.kind === "date") setModelValue(dateText, true);
|
||||
else if (props.kind === "time") setModelValue(nextTime, true);
|
||||
else setModelValue(`${dateText} ${nextTime}`, true);
|
||||
else if (props.kind === "time") setModelValue(`${nextTime}${offsetSuffix}`, true);
|
||||
else setModelValue(`${dateText} ${nextTime}${offsetSuffix}`, true);
|
||||
}
|
||||
|
||||
function finishCommit() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { formatTemporalInputValue, parseTemporalInputValue, stepTemporalInputValue, temporalCellEditorConfig, temporalCellEditorKind } from "@/lib/dataGrid/dataGridTemporalEditor";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { formatTemporalInputValue, hostTimezoneOffsetSuffix, parseTemporalInputValue, stepTemporalInputValue, temporalCellEditorConfig, temporalCellEditorKind } from "@/lib/dataGrid/dataGridTemporalEditor";
|
||||
|
||||
describe("dataGridTemporalEditor", () => {
|
||||
it("resolves temporal editor configs with fractional precision", () => {
|
||||
@@ -54,4 +54,26 @@ describe("dataGridTemporalEditor", () => {
|
||||
expect(formatTemporalInputValue("2026-07-09 12:34:56", "datetime")).toBe("2026-07-09T12:34:56");
|
||||
expect(parseTemporalInputValue("2026-07-09T12:34:56", "datetime")).toBe("2026-07-09 12:34:56");
|
||||
});
|
||||
|
||||
it("formats the host timezone offset for tz-aware Now values", () => {
|
||||
const now = new Date("2026-09-13T12:00:00Z");
|
||||
const spy = vi.spyOn(Date.prototype, "getTimezoneOffset");
|
||||
|
||||
try {
|
||||
spy.mockReturnValue(-480);
|
||||
expect(hostTimezoneOffsetSuffix(now)).toBe("+08:00");
|
||||
|
||||
spy.mockReturnValue(330);
|
||||
expect(hostTimezoneOffsetSuffix(now)).toBe("-05:30");
|
||||
|
||||
spy.mockReturnValue(0);
|
||||
expect(hostTimezoneOffsetSuffix(now)).toBe("+00:00");
|
||||
} finally {
|
||||
spy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -78,6 +78,13 @@ export function temporalOffsetSuffix(value: string, kind: TemporalCellEditorKind
|
||||
return basePattern.test(withoutOffset) ? offset : "";
|
||||
}
|
||||
|
||||
export function hostTimezoneOffsetSuffix(now: Date): string {
|
||||
const minutes = -now.getTimezoneOffset();
|
||||
const sign = minutes >= 0 ? "+" : "-";
|
||||
const abs = Math.abs(minutes);
|
||||
return `${sign}${String(Math.floor(abs / 60)).padStart(2, "0")}:${String(abs % 60).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
export function stepTemporalInputValue(value: string, kind: TemporalCellEditorKind, part: TemporalCellEditorPart, delta: number): string {
|
||||
const dateParts = temporalDateParts(value);
|
||||
const timeParts = temporalTimeParts(value, kind);
|
||||
|
||||
Reference in New Issue
Block a user