MySQL은 날짜와 시간 데이터를 다루기 위한 다양한 내장 함수를 제공합니다. 이 글에서는 현재 날짜/시간 획득, 특정 값 추출, 계산, 변환 및 타임스탬프 처리에 이르기까지 주요 함수들을 상세히 살펴봅니다.
1. 현재 날짜 및 시간 정보 가져오기
1.1 NOW() - 현재 날짜 + 시간
NOW()는 가장 일반적으로 사용되는 함수로, 쿼리가 실행되는 순간의 날짜와 시간을 반환합니다.
SELECT NOW(); -- 예: 2024-05-21 14:30:00
다음 함수들은 NOW()와 동일한 결과를 제공합니다:
CURRENT_TIMESTAMP()
CURRENT_TIMESTAMP
LOCALTIME()
LOCALTIME
LOCALTIMESTAMP()
LOCALTIMESTAMP
1.2 SYSDATE() - 실행 시점의 시간
SYSDATE()는 NOW()와 유사하지만, 함수가 호출되는 시점의 시간을 반환합니다. NOW()는 문장(statement) 실행 시작 시점의 시간을 기준으로 하는 반면, SYSDATE()는 함수가 평가되는 순간의 시간을 가져옵니다.
SELECT SYSDATE();
1.3 CURDATE() - 현재 날짜
현재 시스템 날짜만 필요할 때 사용합니다.
SELECT CURDATE(); -- 예: 2024-05-21
SELECT CURRENT_DATE(); -- 동일
SELECT CURRENT_DATE; -- 동일
1.4 CURTIME() - 현재 시간
SELECT CURTIME(); -- 예: 14:30:00
SELECT CURRENT_TIME(); -- 동일
SELECT CURRENT_TIME; -- 동일
1.5 UTC 시간 함수
국제 표준시(UTC) 기준의 시간을 제공합니다. 한국(KST)은 UTC+9입니다.
SELECT UTC_DATE(); -- 예: 2024-05-21
SELECT UTC_TIME(); -- 예: 05:30:00
SELECT UTC_TIMESTAMP(); -- 예: 2024-05-21 05:30:00
2. 날짜/시간 값의 특정 부분 추출
2.1 기본 추출 함수
SET @sample_dt = '2008-09-10 07:15:30.123456';
SELECT DATE(@sample_dt); -- 2008-09-10
SELECT TIME(@sample_dt); -- 07:15:30.123456
SELECT YEAR(@sample_dt); -- 2008
SELECT QUARTER(@sample_dt); -- 3 (7-9월)
SELECT MONTH(@sample_dt); -- 9
SELECT WEEK(@sample_dt); -- 36 (연 기준 주차)
SELECT DAY(@sample_dt); -- 10
SELECT HOUR(@sample_dt); -- 7
SELECT MINUTE(@sample_dt); -- 15
SELECT SECOND(@sample_dt); -- 30
SELECT MICROSECOND(@sample_dt); -- 123456
2.2 EXTRACT() 함수
EXTRACT()는 YEAR, MONTH 등 단일 단위뿐 아니라 YEAR_MONTH와 같은 복합 단위도 지원합니다. 복합 단위는 지정된 첫 번째 필드부터 마지막 필드까지의 연속된 값을 반환합니다.
SET @sample_dt = '2008-09-10 07:15:30.123456';
-- 단일 단위 추출
SELECT EXTRACT(YEAR FROM @sample_dt); -- 2008
SELECT EXTRACT(QUARTER FROM @sample_dt); -- 3
SELECT EXTRACT(MONTH FROM @sample_dt); -- 9
SELECT EXTRACT(WEEK FROM @sample_dt); -- 36
SELECT EXTRACT(DAY FROM @sample_dt); -- 10
SELECT EXTRACT(HOUR FROM @sample_dt); -- 7
SELECT EXTRACT(MINUTE FROM @sample_dt); -- 15
SELECT EXTRACT(SECOND FROM @sample_dt); -- 30
SELECT EXTRACT(MICROSECOND FROM @sample_dt); -- 123456
-- 복합 단위 추출 (연속된 값)
SELECT EXTRACT(YEAR_MONTH FROM @sample_dt); -- 200809
SELECT EXTRACT(DAY_HOUR FROM @sample_dt); -- 1007
SELECT EXTRACT(DAY_MINUTE FROM @sample_dt); -- 100715
SELECT EXTRACT(DAY_SECOND FROM @sample_dt); -- 10071530
SELECT EXTRACT(DAY_MICROSECOND FROM @sample_dt); -- 10071530123456
SELECT EXTRACT(HOUR_MINUTE FROM @sample_dt); -- 715
SELECT EXTRACT(HOUR_SECOND FROM @sample_dt); -- 71530
SELECT EXTRACT(HOUR_MICROSECOND FROM @sample_dt); -- 71530123456
SELECT EXTRACT(MINUTE_SECOND FROM @sample_dt); -- 1530
SELECT EXTRACT(MINUTE_MICROSECOND FROM @sample_dt); -- 1530123456
SELECT EXTRACT(SECOND_MICROSECOND FROM @sample_dt); -- 30123456
2.3 주(Week) 및 요일 관련 함수
SET @target_date = '2008-08-08';
-- 일자 기준 위치
SELECT DAYOFWEEK(@target_date); -- 6 (1=일요일, 2=월요일 ... 7=토요일)
SELECT DAYOFMONTH(@target_date); -- 8
SELECT DAYOFYEAR(@target_date); -- 221
-- 주차 계산
SELECT WEEK(@target_date); -- 31 (기본 모드)
SELECT WEEK(@target_date, 3); -- 32 (월요일 시작 모드)
SELECT WEEKOFYEAR(@target_date); -- 32 (WEEK(@dt, 3)과 동일)
-- 요일 인덱스 (0=월요일 기준)
SELECT WEEKDAY(@target_date); -- 4 (0=월, 1=화 ... 6=일)
-- 연도 + 주차
SELECT YEARWEEK(@target_date); -- 200831
-- 요일/월 이름
SELECT DAYNAME(@target_date); -- Friday
SELECT MONTHNAME(@target_date); -- August
2.4 LAST_DAY() - 월의 마지막 날짜
SELECT LAST_DAY('2008-02-01'); -- 2008-02-29 (윤년)
SELECT LAST_DAY('2008-08-08'); -- 2008-08-31
3. 날짜 및 시간 연산
3.1 DATE_ADD() - 시간 더하기
SET @current = NOW();
SELECT DATE_ADD(@current, INTERVAL 1 DAY); -- 1일 후
SELECT DATE_ADD(@current, INTERVAL 1 HOUR); -- 1시간 후
SELECT DATE_ADD(@current, INTERVAL 1 MINUTE); -- 1분 후
SELECT DATE_ADD(@current, INTERVAL 1 SECOND); -- 1초 후
SELECT DATE_ADD(@current, INTERVAL 1 MICROSECOND); -- 1마이크로초 후
SELECT DATE_ADD(@current, INTERVAL 1 WEEK); -- 1주 후
SELECT DATE_ADD(@current, INTERVAL 1 MONTH); -- 1개월 후
SELECT DATE_ADD(@current, INTERVAL 1 QUARTER); -- 1분기 후
SELECT DATE_ADD(@current, INTERVAL 1 YEAR); -- 1년 후
-- 음수 값을 사용하여 빼기
SELECT DATE_ADD(@current, INTERVAL -1 DAY); -- 1일 전
복합 시간 단위(예: 시:분:초)를 더할 수도 있습니다. ADDDATE()나 ADDTIME() 대신 DATE_ADD() 사용을 권장합니다.
SET @dt = '2008-08-09 12:12:33';
SELECT DATE_ADD(@dt, INTERVAL '01:15:30' HOUR_SECOND);
-- 결과: 2008-08-09 13:28:03 (1시간 15분 30초 후)
SELECT DATE_ADD(@dt, INTERVAL '1 01:15:30' DAY_SECOND);
-- 결과: 2008-08-10 13:28:03 (1일 1시간 15분 30초 후)
3.2 DATE_SUB() - 시간 빼기
DATE_SUB()는 DATE_ADD()와 사용법이 완전히 동일하지만 값을 뺍니다. SUBDATE()나 SUBTIME()보다 DATE_SUB()를 사용하는 것이 좋습니다.
SELECT DATE_SUB(NOW(), INTERVAL 3 DAY); -- 3일 전
3.3 PERIOD_ADD() / PERIOD_DIFF() - 월 단위 연산
인수 P는 'YYYYMM' 또는 'YYMM' 형식이어야 합니다.
SELECT PERIOD_ADD(200808, 2); -- 200810 (2개월 후)
SELECT PERIOD_DIFF(200810, 200808); -- 2 (월 차이)
3.4 DATEDIFF() / TIMEDIFF() - 날짜/시간 차이
SELECT DATEDIFF('2008-08-08', '2008-08-01'); -- 7 (일 수)
SELECT DATEDIFF('2008-08-01', '2008-08-08'); -- -7
SELECT TIMEDIFF('2008-08-08 08:08:08', '2008-08-08 00:00:00'); -- 08:08:08
SELECT TIMEDIFF('08:08:08', '00:00:00'); -- 08:08:08
4. 날짜/시간 형식 변환
4.1 시간과 초 간 변환
SELECT TIME_TO_SEC('01:00:05'); -- 3605
SELECT SEC_TO_TIME(3605); -- 01:00:05
4.2 날짜와 '0000-00-00' 이후 일수 간 변환
SELECT TO_DAYS('2008-08-08'); -- 733627
SELECT FROM_DAYS(733627); -- 2008-08-08
4.3 문자열을 날짜/시간으로 변환: STR_TO_DATE()
SELECT STR_TO_DATE('08/09/2008', '%m/%d/%Y'); -- 2008-08-09
SELECT STR_TO_DATE('08/09/08', '%m/%d/%y'); -- 2008-08-09
SELECT STR_TO_DATE('08.09.2008', '%m.%d.%Y'); -- 2008-08-09
SELECT STR_TO_DATE('08:09:30', '%h:%i:%s'); -- 08:09:30
SELECT STR_TO_DATE('08.09.2008 08:09:30', '%m.%d.%Y %h:%i:%s'); -- 2008-08-09 08:09:30
4.4 날짜/시간을 문자열로 변환: DATE_FORMAT() / TIME_FORMAT()
STR_TO_DATE()의 역함수입니다. TIME_FORMAT()은 시간 관련 형식 지정자만 사용해야 합니다.
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'); -- 2024-05-21 14:30:00
4.5 지역별 표준 형식 가져오기: GET_FORMAT()
SELECT GET_FORMAT(DATE, 'USA'); -- %m.%d.%Y
SELECT GET_FORMAT(DATE, 'JIS'); -- %Y-%m-%d
SELECT GET_FORMAT(DATE, 'ISO'); -- %Y-%m-%d
SELECT GET_FORMAT(DATE, 'EUR'); -- %d.%m.%Y
SELECT GET_FORMAT(DATE, 'INTERNAL'); -- %Y%m%d
SELECT GET_FORMAT(DATETIME, 'USA'); -- %Y-%m-%d %H.%i.%s
SELECT GET_FORMAT(DATETIME, 'INTERNAL'); -- %Y%m%d%H%i%s
SELECT GET_FORMAT(TIME, 'USA'); -- %h:%i:%s %p
SELECT GET_FORMAT(TIME, 'INTERNAL'); -- %H%i%s
4.6 MAKEDATE() / MAKETIME() - 구성 요소로 날짜/시간 생성
SELECT MAKEDATE(2001, 31); -- 2001-01-31 (연도 + 31번째 날)
SELECT MAKEDATE(2001, 32); -- 2001-02-01 (연도 + 32번째 날)
SELECT MAKETIME(12, 15, 30); -- 12:15:30
5. 타임스탬프(TIMESTAMP) 관련 함수
5.1 현재 UNIX 타임스탬프
SELECT UNIX_TIMESTAMP(); -- 예: 1716280200
5.2 UNIX 타임스탬프와 DATETIME 간 변환
SELECT UNIX_TIMESTAMP('2008-08-08 12:00:00'); -- 1218168000
SELECT FROM_UNIXTIME(1218168000); -- 2008-08-08 12:00:00
SELECT FROM_UNIXTIME(1218168000, '%Y-%m-%d'); -- 2008-08-08
5.3 TIMESTAMP() / TIMESTAMPADD() / TIMESTAMPDIFF()
-- DATE를 TIMESTAMP 값으로 변환
SELECT TIMESTAMP('2008-08-08'); -- 2008-08-08 00:00:00
-- DATETIME에 TIME 더하기
SELECT TIMESTAMP('2008-08-08', '12:00:00'); -- 2008-08-08 12:00:00
-- 시간 간격 더하기/빼기
SELECT TIMESTAMPADD(HOUR, 5, '2008-08-08'); -- 2008-08-08 05:00:00
SELECT TIMESTAMPADD(MONTH, -1, '2008-08-08'); -- 2008-07-08
-- 두 datetime의 차이 (지정된 단위로 반환)
SELECT TIMESTAMPDIFF(DAY, '2008-08-01', '2008-08-08'); -- 7
SELECT TIMESTAMPDIFF(HOUR, '2008-08-08 12:00:00', '2008-08-09 12:00:00'); -- 24
6. 타임존 변환
CONVERT_TZ()를 사용하여 시간대를 변환할 수 있습니다.
SELECT CONVERT_TZ('2008-08-08 12:00:00', '+09:00', '+00:00');
-- 결과: 2008-08-08 03:00:00 (KST -> UTC)
다음과 같은 함수로도 타임존 변환을 구현할 수 있습니다.
SELECT DATE_ADD('2008-08-08 12:00:00', INTERVAL -9 HOUR); -- 2008-08-08 03:00:00
SELECT DATE_SUB('2008-08-08 12:00:00', INTERVAL 9 HOUR); -- 2008-08-08 03:00:00
SELECT TIMESTAMPADD(HOUR, -9, '2008-08-08 12:00:00'); -- 2008-08-08 03:00:00