Add {{timestamp}} built-in routine variable

Renders as a human-readable date and time in UTC (e.g. "April 28,
2026 at 12:17 PM UTC"), complementing the existing {{date}} variable.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-04-28 07:21:31 -05:00
1 parent d3123be870
commit 55364835e9
2 files changed
+30 -6

No files matched your search

+14 -4
View File
@@ -46,8 +46,10 @@ describe("routine variable helpers", () => {
it("identifies built-in variable names", () => {
expect(isBuiltinRoutineVariable("date")).toBe(true);
expect(isBuiltinRoutineVariable("timestamp")).toBe(true);
expect(isBuiltinRoutineVariable("repo")).toBe(false);
expect(BUILTIN_ROUTINE_VARIABLE_NAMES.has("date")).toBe(true);
expect(BUILTIN_ROUTINE_VARIABLE_NAMES.has("timestamp")).toBe(true);
});
it("getBuiltinRoutineVariableValues returns date in YYYY-MM-DD format", () => {
@@ -56,9 +58,17 @@ describe("routine variable helpers", () => {
expect(values.date).toBe(new Date().toISOString().slice(0, 10));
});
it("getBuiltinRoutineVariableValues returns a human-readable timestamp with year, time, and UTC", () => {
const values = getBuiltinRoutineVariableValues();
const year = String(new Date().getUTCFullYear());
expect(values.timestamp).toContain(year);
expect(values.timestamp).toMatch(/\d{1,2}:\d{2}\s?(AM|PM)/);
expect(values.timestamp).toContain("UTC");
});
it("excludes built-in variables from syncRoutineVariablesWithTemplate", () => {
const result = syncRoutineVariablesWithTemplate(
"Daily report for {{date}} — {{repo}}",
"Daily report for {{date}} at {{timestamp}} — {{repo}}",
[],
);
expect(result).toEqual([
@@ -66,11 +76,11 @@ describe("routine variable helpers", () => {
]);
});
it("interpolates built-in date variable alongside user variables", () => {
it("interpolates built-in variables alongside user variables", () => {
const builtins = getBuiltinRoutineVariableValues();
const allVars = { ...builtins, repo: "paperclip" };
expect(
interpolateRoutineTemplate("Report for {{date}} on {{repo}}", allVars),
).toBe(`Report for ${builtins.date} on paperclip`);
interpolateRoutineTemplate("Report for {{date}} ({{timestamp}}) on {{repo}}", allVars),
).toBe(`Report for ${builtins.date} (${builtins.timestamp}) on paperclip`);
});
});
+16 -2
View File
@@ -7,19 +7,33 @@ type RoutineTemplateInput = string | null | undefined | Array<string | null | un
* Built-in variable names that are automatically available in routine templates
* without needing to be defined in the routine's variables list.
*/
export const BUILTIN_ROUTINE_VARIABLE_NAMES = new Set(["date"]);
export const BUILTIN_ROUTINE_VARIABLE_NAMES = new Set(["date", "timestamp"]);
export function isBuiltinRoutineVariable(name: string): boolean {
return BUILTIN_ROUTINE_VARIABLE_NAMES.has(name);
}
const HUMAN_TIMESTAMP_FORMATTER = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "2-digit",
hour12: true,
timeZone: "UTC",
timeZoneName: "short",
});
/**
* Returns current values for all built-in routine variables.
* `date` expands to the current date in YYYY-MM-DD format (UTC).
* `timestamp` expands to a human-readable date and time (e.g. "April 28, 2026 at 12:17 PM UTC").
*/
export function getBuiltinRoutineVariableValues(): Record<string, string> {
const now = new Date();
return {
date: new Date().toISOString().slice(0, 10),
date: now.toISOString().slice(0, 10),
timestamp: HUMAN_TIMESTAMP_FORMATTER.format(now),
};
}