기주

[DB] DB에서 특정한 형식으로 출력하기(시간, 문자열) (TO_CHAR()이용하기), 타임존 설정하기 본문

TIL

[DB] DB에서 특정한 형식으로 출력하기(시간, 문자열) (TO_CHAR()이용하기), 타임존 설정하기

기주그지마 2024. 4. 5. 17:02

프로젝트를 진행하던 중 해당 게임의 위키 수정내역(히스토리) 목록을 보여줘야 했다.

 

각각의 히스토리들의 제목은 작성된 < 시각 + 사용자닉네임 >의 형태로 보여줘야했고, 이와 같은 형태로 API 내에서 값을

 

후처리해서 반환해줘야 했다.

 

 

DB에서 SELECT 해온 값을 타임존설정하기특정한 시간 형식으로 바꾸거나 특정한 문자열 형식으로 변환해서 반환하는 법을 알아보았다.

 

 

 

1.특정한 시간형식으로 변경하기)

TO_CHAR(CURRENT_DATE, 'YYYY-MM-DD HH24:MI:SS');

 

첫번째 매개변수에 시간 값, 두번째 매개변수에 출력형식을 입력한다.

 

여기서 주의할점은 시는 HH24로 해줘야 24시간 형식으로 출력이되고,  분은 MI로 해줘야한다는것. 

 

월(MM)과 분(MI)을 잘 분리해줘야한다

 

 

 

 

2.타임존설정하기

 

SELECT
	created_at  AT TIME ZONE 'Asia/Seoul'

 

 

불러온 created_at (타임스탬프)를 서울 시간으로 적용해준다

 

 

 

3. 특정 문자열 형식으로 처리해서 출력하기 

SELECT 
    TO_CHAR(h.created_at AT TIME ZONE 'Asia/Seoul', 'YYYY-MM-DD HH24:MI:SS') || ' ' || u.nickname

 

 

 

 

 

 

 

 

기존 코드) 잘못된예시)

//히스토리 목록보기
router.get('/:gameidx/history/all', async (req, res, next) => {
    const gameIdx = req.params.gameidx;
    try {
        //특정게임 히스토리목록 최신순으로 출력
        const selectHistorySQLResult = await pool.query(
            `
            SELECT 
                h.idx, h.created_at AS "createdAt", u.nickname
            FROM 
                history h 
            JOIN 
                "user" u
            ON 
                h.user_idx = u.idx
            WHERE 
                game_idx = $1
            AND
                h.created_at IS NOT NULL
            ORDER BY
                h.created_at DESC`,
            [gameIdx]
        );
        const beforeHistoryList = selectHistorySQLResult.rows;

// db에서 불러온값들을 불편하게 직접 후처리 해줬던 방식)
        let idx;
        let createdAt;
        let nickname;
        let timeStamp;
        let historyTitle;
        let history;
        let historyList = [];

        beforeHistoryList.forEach((element) => {
        // 불러온값 직접 반복문으로 후처리 했던 기존 코드)  
        //timestamp에 타임존을 적용해서 특정 시간형식으로 만들기
        // 만든 시간형식 뒤에 문자열 닉네임 붙이기
            history = {};
            idx = element.idx;
            timeStamp = element.createdAt;
            nickname = element.nickname;
            createdAt = moment(timeStamp).format('YYYY-MM-DD HH:mm:ss');

            historyTitle = createdAt + ' ' + nickname;

            history.idx = idx;
            history.title = historyTitle;

            historyList.push(history);
        });

        res.status(200).send({ data: historyList });
    } catch (e) {
        next(e);
    }
});

 

db에서 불러온 값을 직접 timezone을 적용해서 특정 시간 형식으로 만든다음,

 

뒤에 원하는 문자열을 붙여줬던 방식이다.

 

 

 

 

수정한 코드)

db에서 timezone설정, 시간형식 설정, 문자열 형식설정 다해주기

 

 

 

//히스토리 목록보기
router.get('/:gameidx/history/all', async (req, res, next) => {
    const gameIdx = req.params.gameidx;
    try {
        //특정게임 히스토리목록 최신순으로 출력
        const selectHistorySQLResult = await pool.query(
            // history idx, 히스토리 제목(YYYY-MM-DD HH24:MI:SS 사용자닉네임) 출력
            `
            SELECT 
                h.idx, 
                TO_CHAR(h.created_at AT TIME ZONE 'Asia/Seoul', 'YYYY-MM-DD HH24:MI:SS') || ' ' || u.nickname AS "title"
            FROM 
                history h 
            JOIN 
                "user" u
            ON 
                h.user_idx = u.idx
            WHERE 
                game_idx = $1
            AND
                h.created_at IS NOT NULL
            ORDER BY
                h.created_at DESC`,
            [gameIdx]
        );

        const historyList = selectHistorySQLResult.rows;

        res.status(200).send({ data: historyList });
    } catch (e) {
        next(e);
    }
});