interface PowerUsageData {
dailyKWh: number[]; // 일별 전력 사용량 (kWh)
meterReadingDay: number; // 검침일 (1일 ~ 31일)
currentDate: Date; // 현재 날짜
}
interface Tariff {
threshold: number; // 누진 구간 시작 kWh
ratePerKWh: number; // 해당 구간 kWh당 요금
}
const TARIFF_RATES: Tariff[] = [
{ threshold: 0, ratePerKWh: 93.3 }, // 200kWh 이하
{ threshold: 201, ratePerKWh: 187.9 }, // 201 ~ 400kWh
{ threshold: 401, ratePerKWh: 280.6 } // 401kWh 이상
];
function calculateEstimatedMonthlyBill(data: PowerUsageData, scenarioReductionKWhPerDay: number = 0): { totalKWh: number; estimatedBill: number; nextTierKWh: number | null } {
const { dailyKWh, meterReadingDay, currentDate } = data;
const currentDayOfMonth = currentDate.getDate();
// 월 시작일 (이번 달 검침일 다음날) 계산
let startDay: Date;
if (currentDayOfMonth >= meterReadingDay) {
// 이번 달 검침일이 이미 지났으면, 이번 달 검침일 다음날이 시작일
startDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), meterReadingDay + 1);
} else {
// 이번 달 검침일이 아직 안 지났으면, 지난 달 검침일 다음날이 시작일
startDay = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, meterReadingDay + 1);
}
// 월 종료일 (다음 달 검침일) 계산
const endDay = new Date(startDay.getFullYear(), startDay.getMonth() + 1, meterReadingDay);
const daysInCycle = Math.ceil((endDay.getTime() - startDay.getTime()) / (1000 * 60 * 60 * 24));
let daysPassed = Math.ceil((currentDate.getTime() - startDay.getTime()) / (1000 * 60 * 60 * 24));
if (daysPassed < 0) { // 검침일 다음날 이전에 시작일이 설정될 수 있으므로 보정
const prevMonthEndDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), meterReadingDay);
startDay = new Date(prevMonthEndDay.getFullYear(), prevMonthEndDay.getMonth() -1, meterReadingDay + 1);
daysPassed = Math.ceil((currentDate.getTime() - startDay.getTime()) / (1000 * 60 * 60 * 24));
}
const currentUsage = dailyKWh.slice(0, daysPassed).reduce((sum, kwh) => sum + kwh, 0);
const averageDailyUsage = currentUsage / daysPassed;
// 시나리오 적용: 남은 기간 동안 일일 사용량 감소
const remainingDays = daysInCycle - daysPassed;
const estimatedRemainingUsage = Math.max(0, (averageDailyUsage - scenarioReductionKWhPerDay) * remainingDays);
const totalEstimatedKWh = currentUsage + estimatedRemainingUsage;
let estimatedBill = 0;
let remainingKWh = totalEstimatedKWh;
let nextTierKWh: number | null = null;
for (let i = 0; i < TARIFF_RATES.length; i++) {
const tariff = TARIFF_RATES[i];
const nextThreshold = TARIFF_RATES[i + 1] ? TARIFF_RATES[i + 1].threshold : Infinity;
const tierKWh = Math.min(remainingKWh, nextThreshold - tariff.threshold);
if (remainingKWh > 0) {
estimatedBill += tierKWh * tariff.ratePerKWh;
remainingKWh -= tierKWh;
}
if (remainingKWh > 0 && i < TARIFF_RATES.length - 1) {
nextTierKWh = TARIFF_RATES[i + 1].threshold - (totalEstimatedKWh - remainingKWh);
} else if (remainingKWh <= 0 && i === TARIFF_RATES.length - 1) {
nextTierKWh = 0; // 최상위 구간에 도달했거나 초과
}
}
estimatedBill += totalEstimatedKWh * 730; // 기본 요금 약 730원 (복잡도 위해 단순화)
return {
totalKWh: Math.round(totalEstimatedKWh),
estimatedBill: Math.round(estimatedBill / 100) * 100, // 100원 단위 반올림
nextTierKWh: nextTierKWh !== null ? Math.round(nextTierKWh) : null
};
}
// --- 사용 예시 ---
const sampleDailyUsage = [
10, 12, 15, 11, 13, 16, 14, 18, 20, 22, // 10일치
25, 23, 27, 26, 28, 30, 32, 35, 33, 37 // 다음 10일치 (오늘까지 사용량)
];
const today = new Date('2026-08-26'); // 예시: 오늘 날짜
const meterDay = 10; // 검침일 10일
const currentData: PowerUsageData = {
dailyKWh: sampleDailyUsage,
meterReadingDay: meterDay,
currentDate: today
};
// 현재 추세 유지 시
const resultCurrent = calculateEstimatedMonthlyBill(currentData);
// console.log("현재 추세 유지 시:");
// console.log(`- 예상 총 사용량: ${resultCurrent.totalKWh} kWh`);
// console.log(`- 예상 전기 요금: ${resultCurrent.estimatedBill} 원`);
// if (resultCurrent.nextTierKWh !== null) {
// console.log(`- 다음 누진 구간까지 남은 kWh: ${resultCurrent.nextTierKWh} kWh`);
// }
// 하루 5kWh 절전 시나리오 적용 시
const resultScenario = calculateEstimatedMonthlyBill(currentData, 5);
// console.log("\n하루 5kWh 절전 시나리오 적용 시:");
// console.log(`- 예상 총 사용량: ${resultScenario.totalKWh} kWh`);
// console.log(`- 예상 전기 요금: ${resultScenario.estimatedBill} 원`);
// if (resultScenario.nextTierKWh !== null) {
// console.log(`- 다음 누진 구간까지 남은 kWh: ${resultScenario.nextTierKWh} kWh`);
// }