From e1a07f48490ee23276feaca16c04e9bcf502f7d2 Mon Sep 17 00:00:00 2001 From: caadiq Date: Wed, 21 Jan 2026 12:10:08 +0900 Subject: [PATCH] =?UTF-8?q?X=20=EB=82=A0=EC=A7=9C=20=ED=8F=AC=EB=A7=B7?= =?UTF-8?q?=ED=8C=85=EC=9D=84=20dayjs=20=EA=B8=B0=EB=B0=98=20=EC=9C=A0?= =?UTF-8?q?=ED=8B=B8=EB=A6=AC=ED=8B=B0=EB=A1=9C=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - formatXDateTime 함수를 utils/date.js로 이동 - PC/모바일 XSection에서 공통 유틸리티 사용 - 사용하지 않는 closeLightbox 변수 제거 Co-Authored-By: Claude Opus 4.5 --- .../pages/mobile/public/ScheduleDetail.jsx | 38 +------------------ .../pc/public/schedule-sections/XSection.jsx | 23 +---------- frontend/src/utils/date.js | 25 ++++++++++++ 3 files changed, 28 insertions(+), 58 deletions(-) diff --git a/frontend/src/pages/mobile/public/ScheduleDetail.jsx b/frontend/src/pages/mobile/public/ScheduleDetail.jsx index a2cfcb2..6df9243 100644 --- a/frontend/src/pages/mobile/public/ScheduleDetail.jsx +++ b/frontend/src/pages/mobile/public/ScheduleDetail.jsx @@ -5,6 +5,7 @@ import { motion, AnimatePresence } from 'framer-motion'; import { Calendar, Clock, ChevronLeft, Check, Link2, MapPin, Navigation, ExternalLink, X, ChevronRight } from 'lucide-react'; import Linkify from 'react-linkify'; import { getSchedule } from '../../../api/public/schedules'; +import { formatXDateTime } from '../../../utils/date'; import '../../../mobile.css'; // 카카오맵 SDK 키 @@ -177,26 +178,6 @@ const extractXUsername = (url) => { return match ? match[1] : null; }; -// X용 날짜/시간 포맷팅 (오후 2:30 · 2026년 1월 15일) -const formatXDateTime = (dateStr, timeStr) => { - if (!dateStr) return ''; - const date = new Date(dateStr); - const year = date.getFullYear(); - const month = date.getMonth() + 1; - const day = date.getDate(); - - let result = `${year}년 ${month}월 ${day}일`; - - if (timeStr) { - const [hours, minutes] = timeStr.split(':').map(Number); - const period = hours < 12 ? '오전' : '오후'; - const hour12 = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours; - result = `${period} ${hour12}:${String(minutes).padStart(2, '0')} · ${result}`; - } - - return result; -}; - // 유튜브 섹션 컴포넌트 function YoutubeSection({ schedule }) { const videoId = extractYoutubeVideoId(schedule.source?.url); @@ -367,21 +348,6 @@ function XSection({ schedule }) { ); - // datetime 포맷팅 - const formatDateTime = (datetime) => { - if (!datetime) return ''; - const [datePart, timePart] = datetime.split(' '); - const [year, month, day] = datePart.split('-').map(Number); - let timeStr = ''; - if (timePart) { - const [hour, minute] = timePart.split(':').map(Number); - const period = hour >= 12 ? '오후' : '오전'; - const hour12 = hour > 12 ? hour - 12 : hour === 0 ? 12 : hour; - timeStr = `${period} ${hour12}:${String(minute).padStart(2, '0')} · `; - } - return `${timeStr}${year}년 ${month}월 ${day}일`; - }; - return ( <> - {formatDateTime(schedule.datetime)} + {formatXDateTime(schedule.datetime)} diff --git a/frontend/src/pages/pc/public/schedule-sections/XSection.jsx b/frontend/src/pages/pc/public/schedule-sections/XSection.jsx index 692aa2b..7da1278 100644 --- a/frontend/src/pages/pc/public/schedule-sections/XSection.jsx +++ b/frontend/src/pages/pc/public/schedule-sections/XSection.jsx @@ -3,24 +3,7 @@ import { motion } from 'framer-motion'; import Linkify from 'react-linkify'; import { decodeHtmlEntities } from './utils'; import Lightbox from '../../../../components/common/Lightbox'; - -// datetime 포맷팅 (2026-01-18 19:00 → 오후 7:00 · 2026년 1월 18일) -const formatXDateTime = (datetime) => { - if (!datetime) return ''; - - const [datePart, timePart] = datetime.split(' '); - const [year, month, day] = datePart.split('-').map(Number); - - let timeStr = ''; - if (timePart) { - const [hour, minute] = timePart.split(':').map(Number); - const period = hour >= 12 ? '오후' : '오전'; - const hour12 = hour > 12 ? hour - 12 : hour === 0 ? 12 : hour; - timeStr = `${period} ${hour12}:${String(minute).padStart(2, '0')} · `; - } - - return `${timeStr}${year}년 ${month}월 ${day}일`; -}; +import { formatXDateTime } from '../../../../utils/date'; // X(트위터) 섹션 컴포넌트 function XSection({ schedule }) { @@ -39,10 +22,6 @@ function XSection({ schedule }) { window.history.pushState({ lightbox: true }, ''); }, []); - const closeLightbox = useCallback(() => { - setLightboxOpen(false); - }, []); - // 뒤로가기 처리 useEffect(() => { const handlePopState = () => { diff --git a/frontend/src/utils/date.js b/frontend/src/utils/date.js index 3367fbb..04446da 100644 --- a/frontend/src/utils/date.js +++ b/frontend/src/utils/date.js @@ -77,5 +77,30 @@ export const isToday = (date) => { return isSameDay(date, dayjs()); }; +/** + * X(트위터) 스타일 날짜/시간 포맷팅 + * 입력: "2026-01-18 19:00" 또는 "2026-01-18" + * 출력: "오후 7:00 · 2026년 1월 18일" 또는 "2026년 1월 18일" + * @param {string} datetime - 날짜/시간 문자열 + * @returns {string} 포맷된 문자열 + */ +export const formatXDateTime = (datetime) => { + if (!datetime) return ''; + + const d = dayjs(datetime).tz(KST); + const datePart = d.format('YYYY년 M월 D일'); + + // 시간이 포함된 경우 + if (datetime.includes(' ') || datetime.includes('T')) { + const hour = d.hour(); + const minute = d.minute(); + const period = hour >= 12 ? '오후' : '오전'; + const hour12 = hour > 12 ? hour - 12 : hour === 0 ? 12 : hour; + return `${period} ${hour12}:${String(minute).padStart(2, '0')} · ${datePart}`; + } + + return datePart; +}; + // dayjs 인스턴스도 export (고급 사용용) export { dayjs };