138 lines
3.8 KiB
JavaScript
138 lines
3.8 KiB
JavaScript
/**
|
|
* 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
|
|
};
|