Skip to content

Commit 69390b4

Browse files
authored
Make CLI generate migrations using UTC, like Supabase CLI (#136)
* refactor: improve UTC handling and timestamp functions in copy-migrations script - Updated date formatting to use UTC components for consistency - Modified timestamp parsing to validate and create dates in UTC - Enhanced timestamp generation to produce strictly increasing UTC-based timestamps - Clarified helper function comments and adjusted date validation logic * chore: add changeset to ensure migrations use UTC timestamps during install
1 parent d6ee014 commit 69390b4

File tree

2 files changed

+26
-21
lines changed

2 files changed

+26
-21
lines changed

.changeset/proud-singers-smile.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'pgflow': patch
3+
---
4+
5+
Make sure install command creates migrations using UTC timestamps

pkgs/cli/src/commands/install/copy-migrations.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,18 @@ function getTimestampFromFilename(filename: string): string {
7878
return '';
7979
}
8080

81-
// Helper function to format a Date object into a migration timestamp string (YYYYMMDDhhmmss)
81+
// Helper function to format a Date object into a migration timestamp string (YYYYMMDDhhmmss) using UTC
8282
function formatDateToTimestamp(date: Date): string {
83-
const year = date.getFullYear();
84-
const month = String(date.getMonth() + 1).padStart(2, '0');
85-
const day = String(date.getDate()).padStart(2, '0');
86-
const hours = String(date.getHours()).padStart(2, '0');
87-
const minutes = String(date.getMinutes()).padStart(2, '0');
88-
const seconds = String(date.getSeconds()).padStart(2, '0');
83+
const year = date.getUTCFullYear();
84+
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
85+
const day = String(date.getUTCDate()).padStart(2, '0');
86+
const hours = String(date.getUTCHours()).padStart(2, '0');
87+
const minutes = String(date.getUTCMinutes()).padStart(2, '0');
88+
const seconds = String(date.getUTCSeconds()).padStart(2, '0');
8989
return `${year}${month}${day}${hours}${minutes}${seconds}`;
9090
}
9191

92-
// Helper function to parse a timestamp string into a Date object
92+
// Helper function to parse a timestamp string into a Date object (interpreted as UTC)
9393
function parseTimestampToDate(timestamp: string): Date | null {
9494
// Validate format: YYYYMMDDhhmmss
9595
if (!timestamp || timestamp.length !== 14 || !/^\d{14}$/.test(timestamp)) {
@@ -103,42 +103,42 @@ function parseTimestampToDate(timestamp: string): Date | null {
103103
const minutes = parseInt(timestamp.substring(10, 12), 10);
104104
const seconds = parseInt(timestamp.substring(12, 14), 10);
105105

106-
// Create date and validate (invalid dates like Feb 31 will be auto-corrected by JS Date)
107-
const date = new Date(year, month, day, hours, minutes, seconds);
106+
// Create date in UTC and validate (invalid dates like Feb 31 will be auto-corrected by JS Date)
107+
const date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
108108

109109
// Additional validation to ensure the parsed date matches the input
110110
// This catches edge cases like month=13 that JS Date would autocorrect
111111
if (
112-
date.getFullYear() !== year ||
113-
date.getMonth() !== month ||
114-
date.getDate() !== day ||
115-
date.getHours() !== hours ||
116-
date.getMinutes() !== minutes ||
117-
date.getSeconds() !== seconds
112+
date.getUTCFullYear() !== year ||
113+
date.getUTCMonth() !== month ||
114+
date.getUTCDate() !== day ||
115+
date.getUTCHours() !== hours ||
116+
date.getUTCMinutes() !== minutes ||
117+
date.getUTCSeconds() !== seconds
118118
) {
119119
return null;
120120
}
121121

122122
return date;
123123
}
124124

125-
// Helper function to generate a new timestamp that's higher than the reference timestamp
125+
// Helper function to generate a new timestamp that's higher than the reference timestamp (using UTC)
126126
function generateNewTimestamp(
127127
referenceTimestamp: string,
128128
increment = 1
129129
): string {
130130
// First try to parse the reference timestamp to a Date
131131
const parsedDate = parseTimestampToDate(referenceTimestamp);
132132

133-
// If we couldn't parse it, use current time
133+
// If we couldn't parse it, use current UTC time
134134
if (!parsedDate) {
135135
return formatDateToTimestamp(new Date());
136136
}
137137

138138
// Add the specified number of seconds (default: 1)
139-
parsedDate.setSeconds(parsedDate.getSeconds() + increment);
139+
parsedDate.setUTCSeconds(parsedDate.getUTCSeconds() + increment);
140140

141-
// Get current time for comparison
141+
// Get current UTC time for comparison
142142
const now = new Date();
143143

144144
// Return either the incremented timestamp or current time, whichever is later
@@ -147,7 +147,7 @@ function generateNewTimestamp(
147147
return formatDateToTimestamp(parsedDate);
148148
} else {
149149
// If we're already at or past current time, add increment to now
150-
now.setSeconds(now.getSeconds() + increment);
150+
now.setUTCSeconds(now.getUTCSeconds() + increment);
151151
return formatDateToTimestamp(now);
152152
}
153153
}

0 commit comments

Comments
 (0)