93 lines
3.2 KiB
JavaScript
93 lines
3.2 KiB
JavaScript
function parseDateTimeValue(value) {
|
|
if (!value || typeof value !== 'string') return null;
|
|
|
|
const directDate = new Date(value);
|
|
if (!Number.isNaN(directDate.getTime())) return directDate;
|
|
|
|
const normalizedDate = new Date(value.replace(' ', 'T'));
|
|
return Number.isNaN(normalizedDate.getTime()) ? null : normalizedDate;
|
|
}
|
|
|
|
function formatDateTimeForSqlite(date = new Date()) {
|
|
const target = date instanceof Date ? date : new Date(date);
|
|
const year = target.getFullYear();
|
|
const month = String(target.getMonth() + 1).padStart(2, '0');
|
|
const day = String(target.getDate()).padStart(2, '0');
|
|
const hours = String(target.getHours()).padStart(2, '0');
|
|
const minutes = String(target.getMinutes()).padStart(2, '0');
|
|
const seconds = String(target.getSeconds()).padStart(2, '0');
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
}
|
|
|
|
function getDateKeyFromDate(date = new Date()) {
|
|
const target = date instanceof Date ? date : new Date(date);
|
|
if (Number.isNaN(target.getTime())) return null;
|
|
const year = target.getFullYear();
|
|
const month = String(target.getMonth() + 1).padStart(2, '0');
|
|
const day = String(target.getDate()).padStart(2, '0');
|
|
return `${year}-${month}-${day}`;
|
|
}
|
|
|
|
function getRecentDateKeys(days = 30, now = new Date()) {
|
|
const safeDays = Math.max(1, Math.floor(Number(days) || 30));
|
|
const keys = [];
|
|
for (let i = safeDays - 1; i >= 0; i -= 1) {
|
|
const date = new Date(now.getTime());
|
|
date.setDate(date.getDate() - i);
|
|
const key = getDateKeyFromDate(date);
|
|
if (key) keys.push(key);
|
|
}
|
|
return keys;
|
|
}
|
|
|
|
function getNextDownloadResetTime(lastResetAt, resetCycle) {
|
|
const baseDate = parseDateTimeValue(lastResetAt);
|
|
if (!baseDate) return null;
|
|
|
|
const next = new Date(baseDate.getTime());
|
|
if (resetCycle === 'daily') next.setDate(next.getDate() + 1);
|
|
else if (resetCycle === 'weekly') next.setDate(next.getDate() + 7);
|
|
else if (resetCycle === 'monthly') next.setMonth(next.getMonth() + 1);
|
|
else return null;
|
|
return next;
|
|
}
|
|
|
|
function normalizeTimeHHmm(value) {
|
|
if (typeof value !== 'string') return null;
|
|
const match = value.trim().match(/^(\d{2}):(\d{2})$/);
|
|
if (!match) return null;
|
|
const hours = Number(match[1]);
|
|
const minutes = Number(match[2]);
|
|
if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) return null;
|
|
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
|
|
}
|
|
|
|
function toMinutesOfDay(hhmm) {
|
|
const normalized = normalizeTimeHHmm(hhmm);
|
|
if (!normalized) return null;
|
|
const [hours, minutes] = normalized.split(':').map(Number);
|
|
return hours * 60 + minutes;
|
|
}
|
|
|
|
function isCurrentTimeInWindow(startTime, endTime, now = new Date()) {
|
|
const start = toMinutesOfDay(startTime);
|
|
const end = toMinutesOfDay(endTime);
|
|
if (start === null || end === null) return true;
|
|
|
|
const nowMinutes = now.getHours() * 60 + now.getMinutes();
|
|
if (start === end) return true;
|
|
if (start < end) return nowMinutes >= start && nowMinutes < end;
|
|
return nowMinutes >= start || nowMinutes < end;
|
|
}
|
|
|
|
module.exports = {
|
|
parseDateTimeValue,
|
|
formatDateTimeForSqlite,
|
|
getDateKeyFromDate,
|
|
getRecentDateKeys,
|
|
getNextDownloadResetTime,
|
|
normalizeTimeHHmm,
|
|
toMinutesOfDay,
|
|
isCurrentTimeInWindow
|
|
};
|