first commit
CI / lint-and-test (push) Canceled after 0s

This commit is contained in:
Alberto-Audrix committed 2026-07-28 08:55:05 +07:00
commit 32a36cceff
444 files changed
+67186

No files matched your search

+137
View File
@@ -0,0 +1,137 @@
/**
* Date and Time Utilities for WIB (UTC+7) Timezone Handling
* Implements D-1 data filtering logic for dashboard display before 17:00 WIB
*/
const CUTOFF_HOUR = process.env.CUTOFF_HOUR_OVERRIDE
? parseInt(process.env.CUTOFF_HOUR_OVERRIDE, 10)
: 17;
/**
* Get current date/time in WIB (Asia/Jakarta, UTC+7) timezone
* @returns {Date} Current date in WIB
*/
function getCurrentWibDate() {
const now = new Date();
// Convert to WIB using toLocaleString with Jakarta timezone
const wibDateString = now.toLocaleString('en-US', {
timeZone: 'Asia/Jakarta',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
// Parse the formatted string back to Date object
return new Date(wibDateString);
}
/**
* Check if current WIB time is before the cutoff hour (default 17:00)
* @returns {boolean} True if before cutoff, false otherwise
*/
function isBeforeCutoffTime() {
const wibNow = getCurrentWibDate();
const currentHour = wibNow.getHours();
return currentHour < CUTOFF_HOUR;
}
/**
* Get the effective query date (D-1 if before cutoff, else today)
* @returns {Date} Effective date for data queries
*/
function getEffectiveQueryDate() {
const wibToday = getCurrentWibDate();
if (isBeforeCutoffTime()) {
// Return D-1 (previous day)
const yesterday = new Date(wibToday);
yesterday.setDate(yesterday.getDate() - 1);
return yesterday;
}
return wibToday;
}
/**
* Calculate effective day of cycle accounting for D-1 filter
* @param {Date|string} cycleStartDate - Cycle start date
* @returns {number} Effective cycle day (0-indexed from start date)
*/
function getEffectiveCycleDay(cycleStartDate) {
const effectiveDate = getEffectiveQueryDate();
const startDate = new Date(cycleStartDate);
// Reset hours to compare dates only
effectiveDate.setHours(0, 0, 0, 0);
startDate.setHours(0, 0, 0, 0);
const diffMs = effectiveDate.getTime() - startDate.getTime();
// Return -1 if effective date is before cycle start (edge case)
if (diffMs < 0) {
return -1;
}
const dayOfCycle = Math.floor(diffMs / (1000 * 60 * 60 * 24));
return dayOfCycle;
}
/**
* Format date as YYYY-MM-DD for database queries
* @param {Date} date - Date object to format
* @returns {string} Date in YYYY-MM-DD format
*/
function formatDateForDb(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
/**
* Get previous date (D-1) from a given date
* @param {string} dateString - Date string in YYYY-MM-DD format
* @returns {string} Previous date in YYYY-MM-DD format
*/
function getPreviousDate(dateString) {
const date = new Date(dateString);
date.setDate(date.getDate() - 1);
return formatDateForDb(date);
}
/**
* Create API response metadata for D-1 filtering
* @param {boolean} isD1Applied - Whether D-1 filter was applied
* @returns {object} Metadata object for API response
*/
function createResponseMetadata(isD1Applied = false) {
const wibNow = getCurrentWibDate();
const effectiveDate = getEffectiveQueryDate();
return {
effectiveDate: formatDateForDb(effectiveDate),
queryDate: formatDateForDb(wibNow),
isD1Filter: isD1Applied,
currentWibTime: wibNow.toLocaleTimeString('id-ID', {
timeZone: 'Asia/Jakarta',
hour: '2-digit',
minute: '2-digit'
})
};
}
module.exports = {
getCurrentWibDate,
isBeforeCutoffTime,
getEffectiveQueryDate,
getEffectiveCycleDay,
formatDateForDb,
getPreviousDate,
createResponseMetadata,
CUTOFF_HOUR // Export for testing
};