@@ -215,7 +215,9 @@ async function enrichDataWithMySQL(results, currentUserId = null) {
215215 location : post . region ? `${ post . region } ${ post . district ? ` > ${ post . district } ` : "" } ` : "온라인" ,
216216 region : post . region || "온라인" ,
217217 district : post . district || "" ,
218- dateDisplay : ( post . start_date && post . end_date ) ? `${ format ( post . start_date , post . is_start_time_set ) } ~ ${ format ( post . end_date , post . is_end_time_set ) } ` : "상시 진행" ,
218+ ddateDisplay : ( post . start_date && post . end_date )
219+ ? `${ formatForUI ( post . start_date , post . is_start_time_set ) } ~ ${ formatForUI ( post . end_date , post . is_end_time_set ) } `
220+ : "상시 진행" ,
219221 start_date : post . start_date ,
220222 end_date : post . end_date ,
221223
@@ -252,17 +254,30 @@ const getSortParams = () => {
252254 * 정렬 스크립트 파라미터 생성 헬퍼
253255 * 서버의 로컬 타임존 설정에 상관없이 KST 기준 오늘 시작/종료 시점을 UTC 숫자로 계산
254256 */
257+ // 1. UI용 날짜 포맷 (000Z 제거 버전)
258+ const formatForUI = ( dateStr , isTimeSet ) => {
259+ if ( ! dateStr ) return "" ;
260+ const d = new Date ( dateStr ) ;
261+ const pad = ( n ) => n . toString ( ) . padStart ( 2 , '0' ) ;
262+
263+ const datePart = `${ d . getFullYear ( ) } . ${ pad ( d . getMonth ( ) + 1 ) } . ${ pad ( d . getDate ( ) ) } ` ;
264+ const timePart = isTimeSet ? ` ${ pad ( d . getHours ( ) ) } :${ pad ( d . getMinutes ( ) ) } ` : '' ;
265+
266+ return `${ datePart } ${ timePart } ` ;
267+ } ;
268+
269+ // 2. 정렬 파라미터 (KST 오차 없는 절대 숫자값)
255270const getSortParams = ( ) => {
256271 const now = new Date ( ) ;
257272 const kstOffset = 9 * 60 * 60 * 1000 ;
258-
259- // 한국 시간 기준으로 오늘 경계값 계산
260273 const kstNow = new Date ( now . getTime ( ) + kstOffset ) ;
274+
275+ // KST 기준 오늘 00:00:00과 23:59:59의 UTC 타임스탬프
261276 const dayStart = new Date ( kstNow . getFullYear ( ) , kstNow . getMonth ( ) , kstNow . getDate ( ) , 0 , 0 , 0 , 0 ) . getTime ( ) - kstOffset ;
262277 const dayEnd = new Date ( kstNow . getFullYear ( ) , kstNow . getMonth ( ) , kstNow . getDate ( ) , 23 , 59 , 59 , 999 ) . getTime ( ) - kstOffset ;
263278
264279 return {
265- now : now . getTime ( ) , // 현재 시각 타임스탬프
280+ now : now . getTime ( ) ,
266281 dayStart : dayStart ,
267282 dayEnd : dayEnd
268283 } ;
@@ -327,30 +342,29 @@ exports.searchPosts = async (req, res) => {
327342 query : esQuery . bool . must . length > 0 || esQuery . bool . filter . length > 0 ? esQuery : { match_all : { } } ,
328343 // searchPosts와 getAllPosts의 sort 부분을 아래 내용으로 교체하세요.
329344 // searchPosts 및 getAllPosts의 sort 부분 공통 수정
330- sort : [
331- {
332- _script : {
333- type : "number" ,
334- script : {
335- lang : "painless" ,
336- source : `
337- if (doc['end_date'].size() == 0) return 2; // 상시
338- long end = doc['end_date'].value.toInstant().toEpochMilli();
339-
340- // 1. 현재 시각(now)이 마감 시간(end)을 지났으면 무조건 마감 그룹(3)으로
341- if (end < params.now) return 3;
342-
343- // 2. 아직 지나지 않았다면 오늘 종료(0)와 미래 종료(1) 구분
344- if (end >= params.dayStart && end <= params.dayEnd) return 0;
345- return 1;
346- ` ,
347- params : getSortParams ( )
348- } ,
349- order : "asc"
350- }
351- } ,
352- { "created_at" : { "order" : "desc" } } // 그룹 내에서는 최신순
353- ]
345+ sort : [
346+ {
347+ _script : {
348+ type : "number" ,
349+ script : {
350+ lang : "painless" ,
351+ source : `
352+ if (doc['end_date'].size() == 0) return 2; // 상시
353+ long end = doc['end_date'].value.toInstant().toEpochMilli();
354+
355+ // 현재 시각(now)이 마감(end)보다 크면 즉시 마감 그룹(3)으로 이동
356+ if (end < params.now) return 3;
357+
358+ if (end >= params.dayStart && end <= params.dayEnd) return 0; // 오늘 종료
359+ return 1; // 미래 종료
360+ ` ,
361+ params : getSortParams ( )
362+ } ,
363+ order : "asc"
364+ }
365+ } ,
366+ { "created_at" : { "order" : "desc" } } // 2순위: 최신순
367+ ]
354368 } ) ;
355369
356370 const cardData = await enrichDataWithMySQL ( response . hits . hits . map ( hit => hit . _source ) , req . user ?. id ) ;
@@ -377,30 +391,29 @@ exports.getAllPosts = async (req, res) => {
377391 query : { match_all : { } } ,
378392 // searchPosts와 getAllPosts의 sort 부분을 아래 내용으로 교체하세요.
379393 // searchPosts 및 getAllPosts의 sort 부분 공통 수정
380- sort : [
381- {
382- _script : {
383- type : "number" ,
384- script : {
385- lang : "painless" ,
386- source : `
387- if (doc['end_date'].size() == 0) return 2; // 상시
388- long end = doc['end_date'].value.toInstant().toEpochMilli();
389-
390- // 1. 현재 시각(now)이 마감 시간(end)을 지났으면 무조건 마감 그룹(3)으로
391- if (end < params.now) return 3;
392-
393- // 2. 아직 지나지 않았다면 오늘 종료(0)와 미래 종료(1) 구분
394- if (end >= params.dayStart && end <= params.dayEnd) return 0;
395- return 1;
396- ` ,
397- params : getSortParams ( )
398- } ,
399- order : "asc"
400- }
401- } ,
402- { "created_at" : { "order" : "desc" } } // 그룹 내에서는 최신순
403- ]
394+ sort : [
395+ {
396+ _script : {
397+ type : "number" ,
398+ script : {
399+ lang : "painless" ,
400+ source : `
401+ if (doc['end_date'].size() == 0) return 2; // 상시
402+ long end = doc['end_date'].value.toInstant().toEpochMilli();
403+
404+ // 현재 시각(now)이 마감(end)보다 크면 즉시 마감 그룹(3)으로 이동
405+ if (end < params.now) return 3;
406+
407+ if (end >= params.dayStart && end <= params.dayEnd) return 0; // 오늘 종료
408+ return 1; // 미래 종료
409+ ` ,
410+ params : getSortParams ( )
411+ } ,
412+ order : "asc"
413+ }
414+ } ,
415+ { "created_at" : { "order" : "desc" } } // 2순위: 최신순
416+ ]
404417 } ) ;
405418
406419 const cardData = await enrichDataWithMySQL ( response . hits . hits . map ( hit => hit . _source ) , req . user ?. id ) ;
0 commit comments