99 LineSeries ,
1010 AreaData ,
1111 AreaSeries ,
12+ Time , // Time 타입 추가
1213} from "lightweight-charts" ;
1314import { TrendingUp } from "lucide-react" ;
1415
@@ -50,20 +51,90 @@ const getCurrentDate = () => {
5051 ) } -${ String ( now . getDate ( ) ) . padStart ( 2 , "0" ) } `;
5152} ;
5253
53- // 현재 날짜부터 시작하는 날짜 배열 생성
54- const generateDateArray = ( months : number ) => {
55- const dates = [ ] ;
56- const startDate = new Date ( ) ;
54+ // 현재 날짜부터 시작하는 날짜 배열 생성 (Time 타입 반환)
55+ const generateDateArray = ( months : number ) : Time [ ] => {
56+ const dates : Time [ ] = [ ] ;
57+ const startDate = new Date ( ) ; // 오늘 날짜 유지
58+ startDate . setHours ( 0 , 0 , 0 , 0 ) ; // 시간만 정규화
59+
60+ console . log ( "🔍 generateDateArray 시작:" , {
61+ months,
62+ startDate : startDate . toISOString ( ) ,
63+ startDateMonth : startDate . getMonth ( ) ,
64+ startDateDay : startDate . getDate ( ) ,
65+ } ) ;
5766
5867 for ( let i = 0 ; i < months ; i ++ ) {
5968 const date = new Date ( startDate ) ;
60- date . setMonth ( date . getMonth ( ) + i ) ;
61- dates . push (
62- `${ date . getFullYear ( ) } -${ String ( date . getMonth ( ) + 1 ) . padStart ( 2 , "0" ) } -01`
63- ) ;
69+ const originalDay = date . getDate ( ) ;
70+
71+ // 월을 더함
72+ date . setMonth ( startDate . getMonth ( ) + i ) ;
73+
74+ // 날짜가 변경되었다면 (존재하지 않는 날짜였던 경우)
75+ if ( date . getDate ( ) !== originalDay ) {
76+ // 해당 월의 마지막 날로 조정
77+ const lastDayOfMonth = new Date (
78+ date . getFullYear ( ) ,
79+ date . getMonth ( ) + 1 ,
80+ 0
81+ ) ;
82+ date . setDate ( lastDayOfMonth . getDate ( ) ) ;
83+ }
84+
85+ const timestamp = Math . floor ( date . getTime ( ) / 1000 ) as Time ;
86+
87+ console . log ( `📅 월 ${ i + 1 } :` , {
88+ originalDay,
89+ finalDate : date . toISOString ( ) ,
90+ timestamp,
91+ month : date . getMonth ( ) ,
92+ day : date . getDate ( ) ,
93+ } ) ;
94+
95+ dates . push ( timestamp ) ;
6496 }
6597
66- return dates ;
98+ // 중복 제거 및 정렬
99+ const uniqueDates = [ ...new Set ( dates ) ] . sort ( ( a , b ) => Number ( a ) - Number ( b ) ) ;
100+
101+ console . log ( "🔍 최종 날짜 배열:" , {
102+ originalLength : dates . length ,
103+ uniqueLength : uniqueDates . length ,
104+ removedDuplicates : dates . length - uniqueDates . length ,
105+ firstDate : new Date ( Number ( uniqueDates [ 0 ] ) * 1000 ) . toISOString ( ) ,
106+ lastDate : new Date (
107+ Number ( uniqueDates [ uniqueDates . length - 1 ] ) * 1000
108+ ) . toISOString ( ) ,
109+ } ) ;
110+
111+ return uniqueDates ;
112+ } ;
113+
114+ // 데이터 검증 함수 추가
115+ const validateChartData = < T extends { time : Time ; value : number } > (
116+ data : T [ ] ,
117+ seriesName : string
118+ ) : T [ ] => {
119+ // 중복 제거 및 정렬
120+ const uniqueData = data . filter (
121+ ( item , index , self ) =>
122+ index === 0 || Number ( item . time ) !== Number ( self [ index - 1 ] . time )
123+ ) ;
124+
125+ const sortedData = uniqueData . sort ( ( a , b ) => Number ( a . time ) - Number ( b . time ) ) ;
126+
127+ console . log ( `🔍 ${ seriesName } 데이터 검증:` , {
128+ originalLength : data . length ,
129+ finalLength : sortedData . length ,
130+ removedDuplicates : data . length - sortedData . length ,
131+ firstTime : sortedData [ 0 ] ? Number ( sortedData [ 0 ] . time ) : null ,
132+ lastTime : sortedData [ sortedData . length - 1 ]
133+ ? Number ( sortedData [ sortedData . length - 1 ] . time )
134+ : null ,
135+ } ) ;
136+
137+ return sortedData ;
67138} ;
68139
69140export const MonthlyPathsChart = ( {
@@ -214,12 +285,12 @@ export const MonthlyPathsChart = ({
214285
215286 const area95Data : AreaData [ ] = data . fan_bands . p95 . map (
216287 ( value , index ) => ( {
217- time : dateArray [ index ] ,
288+ time : dateArray [ index ] as Time , // 타입 캐스팅 추가
218289 value : value ,
219290 } )
220291 ) ;
221292
222- area95Series . setData ( area95Data ) ;
293+ area95Series . setData ( validateChartData ( area95Data , "Fan 95%" ) ) ;
223294 seriesRef . current . push ( area95Series ) ;
224295
225296 // 25%~75% 영역 (더 진한 파랑)
@@ -232,12 +303,12 @@ export const MonthlyPathsChart = ({
232303
233304 const area75Data : AreaData [ ] = data . fan_bands . p75 . map (
234305 ( value , index ) => ( {
235- time : dateArray [ index ] ,
306+ time : dateArray [ index ] as Time , // 타입 캐스팅 추가
236307 value : value ,
237308 } )
238309 ) ;
239310
240- area75Series . setData ( area75Data ) ;
311+ area75Series . setData ( validateChartData ( area75Data , "Fan 75%" ) ) ;
241312 seriesRef . current . push ( area75Series ) ;
242313
243314 // 중앙값 라인 (굵은 선)
@@ -251,12 +322,12 @@ export const MonthlyPathsChart = ({
251322
252323 const medianData : LineData [ ] = data . fan_bands . p50 . map (
253324 ( value , index ) => ( {
254- time : dateArray [ index ] ,
325+ time : dateArray [ index ] as Time , // 타입 캐스팅 추가
255326 value : value ,
256327 } )
257328 ) ;
258329
259- medianSeries . setData ( medianData ) ;
330+ medianSeries . setData ( validateChartData ( medianData , "Median" ) ) ;
260331 seriesRef . current . push ( medianSeries ) ;
261332 }
262333
@@ -273,12 +344,12 @@ export const MonthlyPathsChart = ({
273344
274345 const principalData : LineData [ ] = data . principal_line . map (
275346 ( value , index ) => ( {
276- time : dateArray [ index ] ,
347+ time : dateArray [ index ] as Time , // 타입 캐스팅 추가
277348 value : value ,
278349 } )
279350 ) ;
280351
281- principalSeries . setData ( principalData ) ;
352+ principalSeries . setData ( validateChartData ( principalData , "Principal" ) ) ;
282353 seriesRef . current . push ( principalSeries ) ;
283354 }
284355
@@ -295,12 +366,12 @@ export const MonthlyPathsChart = ({
295366
296367 const bestData : LineData [ ] = data . representative . p95 . map (
297368 ( value , index ) => ( {
298- time : dateArray [ index ] ,
369+ time : dateArray [ index ] as Time , // 타입 캐스팅 추가
299370 value : value ,
300371 } )
301372 ) ;
302373
303- bestSeries . setData ( bestData ) ;
374+ bestSeries . setData ( validateChartData ( bestData , "Best" ) ) ;
304375 seriesRef . current . push ( bestSeries ) ;
305376
306377 // 최악 성과 (하위 5%)
@@ -314,12 +385,12 @@ export const MonthlyPathsChart = ({
314385
315386 const worstData : LineData [ ] = data . representative . p05 . map (
316387 ( value , index ) => ( {
317- time : dateArray [ index ] ,
388+ time : dateArray [ index ] as Time , // 타입 캐스팅 추가
318389 value : value ,
319390 } )
320391 ) ;
321392
322- worstSeries . setData ( worstData ) ;
393+ worstSeries . setData ( validateChartData ( worstData , "Worst" ) ) ;
323394 seriesRef . current . push ( worstSeries ) ;
324395 }
325396
@@ -337,11 +408,13 @@ export const MonthlyPathsChart = ({
337408 } ) ;
338409
339410 const lineData : LineData [ ] = path . map ( ( value , monthIndex ) => ( {
340- time : dateArray [ monthIndex ] ,
411+ time : dateArray [ monthIndex ] as Time , // 타입 캐스팅 추가
341412 value : value ,
342413 } ) ) ;
343414
344- lineSeries . setData ( lineData ) ;
415+ lineSeries . setData (
416+ validateChartData ( lineData , `Random Sample ${ index + 1 } ` )
417+ ) ;
345418 seriesRef . current . push ( lineSeries ) ;
346419 } ) ;
347420 }
@@ -382,14 +455,14 @@ export const MonthlyPathsChart = ({
382455 const dateIndex = yearStartMonth ;
383456 if ( dateIndex < dateArray . length ) {
384457 data . push ( {
385- time : dateArray [ dateIndex ] ,
458+ time : dateArray [ dateIndex ] as Time , // 타입 캐스팅 추가
386459 value : yearAverage ,
387460 } ) ;
388461 }
389462 }
390463 }
391464
392- lineSeries . setData ( data ) ;
465+ lineSeries . setData ( validateChartData ( data , `Path ${ index + 1 } ` ) ) ;
393466 seriesRef . current . push ( lineSeries ) ;
394467 } ) ;
395468 }
0 commit comments