feat: dayjs 라이브러리로 날짜 계산 로직 통합

- dayjs 패키지 설치 (타임존 지원)
- utils/date.js 유틸리티 생성 (getTodayKST, formatDate, parseDateKST 등)
- PC/모바일 Home.jsx의 날짜 계산을 유틸리티로 교체
- PC Schedule.jsx, AdminSchedule.jsx의 getTodayKST 함수를 유틸리티로 교체
- KST 타임존 기준으로 정확한 날짜 계산 보장
This commit is contained in:
caadiq 2026-01-09 09:46:54 +09:00
parent cca25b456c
commit 0d72dfe456
7 changed files with 96 additions and 23 deletions

View file

@ -9,6 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@tanstack/react-query": "^5.90.16", "@tanstack/react-query": "^5.90.16",
"dayjs": "^1.11.19",
"framer-motion": "^11.0.8", "framer-motion": "^11.0.8",
"lucide-react": "^0.344.0", "lucide-react": "^0.344.0",
"react": "^18.2.0", "react": "^18.2.0",
@ -1519,6 +1520,12 @@
"devOptional": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/dayjs": {
"version": "1.11.19",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
"license": "MIT"
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.4.3", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",

View file

@ -10,6 +10,7 @@
}, },
"dependencies": { "dependencies": {
"@tanstack/react-query": "^5.90.16", "@tanstack/react-query": "^5.90.16",
"dayjs": "^1.11.19",
"framer-motion": "^11.0.8", "framer-motion": "^11.0.8",
"lucide-react": "^0.344.0", "lucide-react": "^0.344.0",
"react": "^18.2.0", "react": "^18.2.0",

View file

@ -2,6 +2,7 @@ import { motion } from 'framer-motion';
import { ChevronRight, Clock, Tag } from 'lucide-react'; import { ChevronRight, Clock, Tag } from 'lucide-react';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { getTodayKST } from '../../utils/date';
// //
function MobileHome() { function MobileHome() {
@ -24,8 +25,8 @@ function MobileHome() {
.then(data => setAlbums(data.slice(0, 2))) .then(data => setAlbums(data.slice(0, 2)))
.catch(console.error); .catch(console.error);
// (startDate + limit ) //
const today = new Date().toISOString().split('T')[0]; const today = getTodayKST();
fetch(`/api/schedules?startDate=${today}&limit=3`) fetch(`/api/schedules?startDate=${today}&limit=3`)
.then(res => res.json()) .then(res => res.json())
.then(data => setSchedules(data)) .then(data => setSchedules(data))

View file

@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Calendar, ArrowRight, Clock, Link2, Tag } from 'lucide-react'; import { Calendar, ArrowRight, Clock, Link2, Tag } from 'lucide-react';
import { getTodayKST } from '../../utils/date';
function Home() { function Home() {
const [members, setMembers] = useState([]); const [members, setMembers] = useState([]);
@ -15,11 +16,7 @@ function Home() {
.catch(error => console.error('멤버 데이터 로드 오류:', error)); .catch(error => console.error('멤버 데이터 로드 오류:', error));
// ( 3) // ( 3)
// KST const todayStr = getTodayKST();
const now = new Date();
const kstOffset = 9 * 60; // KST UTC+9
const kstTime = new Date(now.getTime() + (kstOffset + now.getTimezoneOffset()) * 60000);
const todayStr = kstTime.toISOString().split('T')[0];
fetch(`/api/schedules?startDate=${todayStr}&limit=3`) fetch(`/api/schedules?startDate=${todayStr}&limit=3`)

View file

@ -4,18 +4,11 @@ import { motion, AnimatePresence } from 'framer-motion';
import { Clock, ChevronLeft, ChevronRight, ChevronDown, Tag, Search, ArrowLeft, Link2 } from 'lucide-react'; import { Clock, ChevronLeft, ChevronRight, ChevronDown, Tag, Search, ArrowLeft, Link2 } from 'lucide-react';
import { useInfiniteQuery } from '@tanstack/react-query'; import { useInfiniteQuery } from '@tanstack/react-query';
import { useInView } from 'react-intersection-observer'; import { useInView } from 'react-intersection-observer';
import { getTodayKST } from '../../utils/date';
function Schedule() { function Schedule() {
const navigate = useNavigate(); const navigate = useNavigate();
// KST (YYYY-MM-DD)
const getTodayKST = () => {
const now = new Date();
const kstOffset = 9 * 60 * 60 * 1000; // 9
const kstDate = new Date(now.getTime() + kstOffset);
return kstDate.toISOString().split('T')[0];
};
const [currentDate, setCurrentDate] = useState(new Date()); const [currentDate, setCurrentDate] = useState(new Date());
const [selectedDate, setSelectedDate] = useState(getTodayKST()); // KST const [selectedDate, setSelectedDate] = useState(getTodayKST()); // KST
const [showYearMonthPicker, setShowYearMonthPicker] = useState(false); const [showYearMonthPicker, setShowYearMonthPicker] = useState(false);

View file

@ -11,18 +11,11 @@ import { useInView } from 'react-intersection-observer';
import Toast from '../../../components/Toast'; import Toast from '../../../components/Toast';
import Tooltip from '../../../components/Tooltip'; import Tooltip from '../../../components/Tooltip';
import useScheduleStore from '../../../stores/useScheduleStore'; import useScheduleStore from '../../../stores/useScheduleStore';
import { getTodayKST } from '../../../utils/date';
function AdminSchedule() { function AdminSchedule() {
const navigate = useNavigate(); const navigate = useNavigate();
// KST (YYYY-MM-DD)
const getTodayKST = () => {
const now = new Date();
const kstOffset = 9 * 60 * 60 * 1000;
const kstDate = new Date(now.getTime() + kstOffset);
return kstDate.toISOString().split('T')[0];
};
// Zustand // Zustand
const { const {
searchInput, setSearchInput, searchInput, setSearchInput,

View file

@ -0,0 +1,81 @@
/**
* 날짜 관련 유틸리티 함수
* dayjs를 사용하여 KST(한국 표준시) 기준으로 날짜 처리
*/
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
// 플러그인 확장
dayjs.extend(utc);
dayjs.extend(timezone);
// 기본 타임존 설정
const KST = "Asia/Seoul";
/**
* KST 기준 오늘 날짜 (YYYY-MM-DD)
* @returns {string} 오늘 날짜 문자열
*/
export const getTodayKST = () => {
return dayjs().tz(KST).format("YYYY-MM-DD");
};
/**
* KST 기준 현재 시각
* @returns {dayjs.Dayjs} dayjs 객체
*/
export const nowKST = () => {
return dayjs().tz(KST);
};
/**
* 날짜 문자열 포맷팅
* @param {string|Date} date - 날짜
* @param {string} format - 포맷 (기본: 'YYYY-MM-DD')
* @returns {string} 포맷된 날짜 문자열
*/
export const formatDate = (date, format = "YYYY-MM-DD") => {
return dayjs(date).tz(KST).format(format);
};
/**
* 날짜에서 , , , 요일 추출
* @param {string|Date} date - 날짜
* @returns {object} { year, month, day, weekday }
*/
export const parseDateKST = (date) => {
const d = dayjs(date).tz(KST);
const weekdays = ["일", "월", "화", "수", "목", "금", "토"];
return {
year: d.year(),
month: d.month() + 1,
day: d.date(),
weekday: weekdays[d.day()],
};
};
/**
* 날짜 비교 (같은 날인지)
* @param {string|Date} date1
* @param {string|Date} date2
* @returns {boolean}
*/
export const isSameDay = (date1, date2) => {
return (
dayjs(date1).tz(KST).format("YYYY-MM-DD") ===
dayjs(date2).tz(KST).format("YYYY-MM-DD")
);
};
/**
* 날짜가 오늘인지 확인
* @param {string|Date} date
* @returns {boolean}
*/
export const isToday = (date) => {
return isSameDay(date, dayjs());
};
// dayjs 인스턴스도 export (고급 사용용)
export { dayjs };