date time

This commit is contained in:
2026-05-29 14:15:06 +07:00
parent 991d6f5257
commit 9cedf085a3
6 changed files with 82 additions and 9 deletions

View File

@@ -12,6 +12,7 @@ SQLSERVER_USER=sa
SQLSERVER_PASSWORD=change_me
SQLSERVER_ENCRYPT=false
SQLSERVER_TRUST_SERVER_CERTIFICATE=true
SQLSERVER_USE_UTC=true
AUTH_SECRET=change_this_to_a_long_random_value
SESSION_MAX_AGE_MS=28800000
SESSION_COOKIE_SECURE=true

View File

@@ -293,6 +293,16 @@ function getCurrentPath(req) {
return `${url.pathname}${url.search}` || '/';
}
function toDateInputValue(value = new Date()) {
const date = value instanceof Date ? value : new Date(value);
const safeDate = Number.isNaN(date.getTime()) ? new Date() : date;
const year = safeDate.getFullYear();
const month = String(safeDate.getMonth() + 1).padStart(2, '0');
const day = String(safeDate.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
function viewModel(req, active, title, pageData, extra = {}) {
const currentUser = pageData.currentUser || req.currentUser || {
name: 'Guest',
@@ -314,6 +324,7 @@ function viewModel(req, active, title, pageData, extra = {}) {
notice: getNotice(req),
currentPath: getCurrentPath(req),
databaseLabel: getSqlServerDisplayLabel(),
todayDate: toDateInputValue(),
helpers: helpers(),
...extra
};

View File

@@ -16,7 +16,8 @@ function getConfig() {
password: process.env.SQLSERVER_PASSWORD,
options: {
encrypt: boolFromEnv(process.env.SQLSERVER_ENCRYPT, false),
trustServerCertificate: boolFromEnv(process.env.SQLSERVER_TRUST_SERVER_CERTIFICATE, true)
trustServerCertificate: boolFromEnv(process.env.SQLSERVER_TRUST_SERVER_CERTIFICATE, true),
useUTC: boolFromEnv(process.env.SQLSERVER_USE_UTC, true)
},
pool: {
max: 10,

View File

@@ -11,10 +11,70 @@ const EMAIL_CONFIRMATION_EXPIRES_MS = Number(process.env.EMAIL_CONFIRMATION_EXPI
let emailConfirmationSchemaPromise;
let applicationOpenUrlSchemaPromise;
function padDatePart(value) {
return String(value).padStart(2, '0');
}
function getLocalDateInputValue(value = new Date()) {
const date = value instanceof Date ? value : new Date(value);
const safeDate = Number.isNaN(date.getTime()) ? new Date() : date;
return [
safeDate.getFullYear(),
padDatePart(safeDate.getMonth() + 1),
padDatePart(safeDate.getDate())
].join('-');
}
function getUtcDateInputValue(value) {
return [
value.getUTCFullYear(),
padDatePart(value.getUTCMonth() + 1),
padDatePart(value.getUTCDate())
].join('-');
}
function parseDateInputValue(value) {
if (typeof value !== 'string') return '';
const match = /^(\d{4})-(\d{2})-(\d{2})(?:T.*)?$/.exec(value.trim());
if (!match) return '';
const year = Number(match[1]);
const month = Number(match[2]);
const day = Number(match[3]);
const date = new Date(Date.UTC(year, month - 1, day));
if (
date.getUTCFullYear() !== year
|| date.getUTCMonth() !== month - 1
|| date.getUTCDate() !== day
) {
return '';
}
return `${match[1]}-${match[2]}-${match[3]}`;
}
function toDateInputValue(value) {
const date = value ? new Date(value) : new Date();
if (Number.isNaN(date.getTime())) return new Date().toISOString().slice(0, 10);
return date.toISOString().slice(0, 10);
if (!value) return '';
const parsedDateInput = parseDateInputValue(value);
if (parsedDateInput) return parsedDateInput;
const date = value instanceof Date ? value : new Date(value);
if (Number.isNaN(date.getTime())) return '';
return getUtcDateInputValue(date);
}
function toReleaseDateValue(value) {
return toDateInputValue(value) || getLocalDateInputValue();
}
function toSqlDateTime2Date(value) {
const [year, month, day] = toReleaseDateValue(value).split('-').map(Number);
return new Date(Date.UTC(year, month - 1, day));
}
function formatDate(value) {
@@ -1133,7 +1193,7 @@ async function createPackageWithVersion(input) {
.input('FileChecksumSha256', sql.Char(64), input.checksum || null)
.input('FileSizeBytes', sql.BigInt, input.fileSizeBytes || null)
.input('ChangeLog', sql.NVarChar(sql.MAX), input.changeLog || null)
.input('ReleaseDate', sql.DateTime2, input.releaseDate ? new Date(input.releaseDate) : new Date())
.input('ReleaseDate', sql.DateTime2, toSqlDateTime2Date(input.releaseDate))
.query(`
INSERT dbo.PackageVersions (
PackageId, Version, FilePath, DockerImage, FileChecksumSha256,
@@ -1175,7 +1235,7 @@ async function addPackageVersion(input) {
.input('FileChecksumSha256', sql.Char(64), input.checksum || null)
.input('FileSizeBytes', sql.BigInt, input.fileSizeBytes || null)
.input('ChangeLog', sql.NVarChar(sql.MAX), input.changeLog || null)
.input('ReleaseDate', sql.DateTime2, input.releaseDate ? new Date(input.releaseDate) : new Date())
.input('ReleaseDate', sql.DateTime2, toSqlDateTime2Date(input.releaseDate))
.query(`
INSERT dbo.PackageVersions (
PackageId, Version, FilePath, DockerImage, FileChecksumSha256,
@@ -1213,7 +1273,7 @@ async function replacePackageVersionArtifact(input) {
.input('FileChecksumSha256', sql.Char(64), input.checksum || null)
.input('FileSizeBytes', sql.BigInt, input.fileSizeBytes || null)
.input('ChangeLog', sql.NVarChar(sql.MAX), input.changeLog || null)
.input('ReleaseDate', sql.DateTime2, input.releaseDate ? new Date(input.releaseDate) : new Date())
.input('ReleaseDate', sql.DateTime2, toSqlDateTime2Date(input.releaseDate))
.query(`
UPDATE dbo.PackageVersions
SET FilePath = @FilePath,

View File

@@ -33,7 +33,7 @@
</label>
<label class="form-field">
<span>Release date</span>
<input type="date" name="releaseDate" value="2026-05-19">
<input type="date" name="releaseDate" value="<%= todayDate %>">
</label>
<div class="form-field full">
<span>Package file</span>

View File

@@ -23,7 +23,7 @@
</label>
<label class="form-field">
<span>Release date</span>
<input type="date" name="releaseDate" value="2026-05-19">
<input type="date" name="releaseDate" value="<%= todayDate %>">
</label>
<div class="form-field full">
<span>Package file</span>