본문 바로가기

비개발자의 개발 일지

현장 팀장에서 수출 ERP까지 — AI와 함께 시스템을 만든 기록

시리즈 보기
php

MySQL DATEDIFF · TIMEDIFF — 날짜·시간 차이 완전 정리

by 왕진 2026. 6. 28.
반응형

 

 

Database · MySQL

DATEDIFF · TIMEDIFF — 날짜·시간 차이 완전 정리

두 날짜의 '일수' 차이는 DATEDIFF, 두 시간의 '시:분:초' 차이는 TIMEDIFF — 반환형이 다르면 쓰는 곳도 달라진다
시작 오늘 분석할 코드

날짜를 다루다 보면 "이 두 시점 사이에 며칠이 지났는가", "이 두 시각 사이에 몇 시간 몇 분이 지났는가"를 계산해야 할 때가 있다. MySQL은 이 둘을 서로 다른 함수로 분리해 놓았다. 아래는 두 함수를 한 문장에서 같이 써 본 원본 코드다.

SELECT DATEDIFF('2025-01-01', NOW()), -- 지정 날짜에서 현재날짜를 빼면 결과값 TIMEDIFF('23:23:59', '12:11:10'); -- 지정 시간에서 현재 시간을 빼면 결과값
실제 결과 미리보기

오늘이 2026-07-04라고 가정하고 두 함수를 각각 실행하면 아래와 같은 값이 나온다.

함수 호출 결과 반환 타입 의미
DATEDIFF('2025-01-01', NOW()) -549 정수(일수) 2025-01-01이 오늘보다 549일 더 과거라는 뜻
TIMEDIFF('23:23:59', '12:11:10') 11:12:49 TIME (시:분:초) 23시23분59초에서 12시11분10초를 뺀 시간 간격

숫자 하나(DATEDIFF)와 시:분:초 문자열(TIMEDIFF)이라는 반환 형태 자체가 완전히 다르다는 점을 눈으로 먼저 확인하고 넘어가자.

용어 용어 정리
DATEDIFF()두 날짜 사이의 '일수' 차이를 정수로 반환하는 함수
TIMEDIFF()두 시간(또는 시간이 포함된 값) 사이의 차이를 TIME 형으로 반환하는 함수
NOW()현재 날짜와 시간을 DATETIME 형으로 반환
CURDATE()현재 날짜만 DATE 형으로 반환 (시간 정보 없음)
CURTIME()현재 시각만 TIME 형으로 반환 (날짜 정보 없음)
DATEYYYY-MM-DD 형식으로 날짜만 저장하는 자료형
DATETIMEYYYY-MM-DD HH:MM:SS로 날짜+시간을 함께 저장하는 자료형
TIMEHH:MM:SS 형식이며 -838:59:59 ~ 838:59:59까지 표현 가능한 자료형
TIMESTAMPDIFF()연/월/일/시/분/초 등 원하는 단위를 지정해 차이를 구하는 범용 함수
TIME_TO_SEC()TIME 값을 순수한 '초' 단위 정수로 풀어내는 함수
SEC_TO_TIME()초 단위 정수를 다시 HH:MM:SS 형태의 TIME 값으로 조립하는 함수

1 DATEDIFF — 날짜만 보고 '일수'로 답한다
왜 정수 하나만 돌려주는가?

DATEDIFF는 인자로 DATETIME이나 TIMESTAMP를 넣어도 내부적으로 시간 부분을 버리고 날짜 부분만 비교한다. "2025-01-01 23:59:59"와 "2025-01-02 00:00:01"은 시간상으론 2초밖에 차이 나지 않지만, DATEDIFF는 날짜가 하루 바뀌었다는 사실만 보고 결과를 1로 낸다. 이것이 DATEDIFF가 시:분:초를 반환하지 않고 오직 정수 하나만 반환하는 이유다 — '일' 단위에는 애초에 시:분:초라는 개념이 들어설 자리가 없다.

※ "가입한 지 며칠째인가", "결제 마감일까지 며칠 남았는가"처럼 하루 단위로 끊어서 세는 계산에 적합하다.

2 TIMEDIFF — 시:분:초까지 그대로 보존한다
왜 반환 타입이 TIME인가?

TIMEDIFF는 날짜를 버리지 않고 시간의 흐름 자체를 표현해야 하는 함수다. 그래서 결과를 정수 하나로 뭉개지 않고 HH:MM:SS 형태의 TIME 값으로 돌려준다. 예를 들어 출근 시각과 퇴근 시각의 차이를 구할 때 "8"이라는 숫자만 받으면 8시간인지 8분인지 알 수 없다. TIME 형으로 반환해야 "08:00:00"처럼 단위가 명확한 결과를 사람이 그대로 읽을 수 있다.

TIMEDIFF('18:00:00', '09:30:00') → 08:30:00 (8시간 30분)

3 인자 순서 — 앞에서 뒤를 뺀다
왜 결과에 음수가 나오는가?

두 함수 모두 함수명(첫번째, 두번째)일 때 계산 공식은 "첫번째 - 두번째"다. 원본 코드의 DATEDIFF('2025-01-01', NOW())는 '2025-01-01에서 오늘 날짜를 뺀 값'이라는 뜻이라, 2025-01-01이 오늘보다 과거이면 결과는 음수가 된다. 반대로 DATEDIFF(NOW(), '2025-01-01')로 순서를 바꾸면 부호만 뒤집혀 양수가 나온다. "얼마나 지났는가"를 양수로 보고 싶다면 항상 더 최근 날짜를 첫 번째 인자에 넣어야 한다.

※ 순서를 무심코 바꿔서 "D-day가 음수로 나온다"는 버그 리포트가 실무에서 매우 흔하다.

 

반응형

 

4 반환형이 다르면 쓰임새도 갈린다
INT 대 TIME, 무엇이 다른가?

DATEDIFF의 결과는 그냥 숫자(정수)이므로 WHERE DATEDIFF(...) > 30처럼 부등호 비교, 정렬, 합계 계산에 바로 쓸 수 있다. 반면 TIMEDIFF의 결과는 TIME 형이라서 숫자처럼 보이지만 실제로는 시:분:초 구조를 가진 값이다. 이 값을 순수한 '초' 단위 숫자로 바꾸고 싶다면 TIME_TO_SEC()으로 한 번 더 변환해야 사칙연산이나 평균 계산이 정확해진다.

DATEDIFF
반환: 정수(BIGINT)
단위: 일(day) 고정
바로 산술 연산 가능
TIMEDIFF
반환: TIME
단위: 시:분:초 표현
산술 연산 전 TIME_TO_SEC() 변환 권장

5 NOW·CURDATE·CURTIME — 현재 시점을 어떻게 넣을 것인가
왜 DATEDIFF에는 NOW()를 그냥 넣어도 되는가?

DATEDIFF는 앞서 말했듯 인자에서 날짜 부분만 추출해 비교하기 때문에, DATE 형인 CURDATE() 대신 DATETIME 형인 NOW()를 넣어도 문제없이 동작한다. 반면 TIMEDIFF는 시:분:초 정밀도가 중요한 함수이므로, 날짜가 섞인 값을 비교할 때는 두 인자의 날짜 부분이 서로 다르면 결과가 24시간을 넘거나 예상과 다르게 나올 수 있다. "오늘 안에서만" 시간 차이를 구하고 싶다면 CURTIME()처럼 순수 시간값끼리 비교하는 편이 안전하다.

현재 시점 함수 3형제
  • NOW() — 날짜 + 시간 (DATETIME)
  • CURDATE() — 날짜만 (DATE)
  • CURTIME() — 시간만 (TIME)
  • CURRENT_DATE, CURRENT_TIME — CURDATE(), CURTIME()과 동일한 별칭 표현
  • SYSDATE() — NOW()와 비슷하지만 함수가 '실행되는 순간'의 시각을 반환

6 TIMEDIFF의 한계 — 날짜가 다르면 24시간을 넘길 수 있다
왜 TIME 범위가 ±838:59:59까지 늘어나 있는가?

TIME 자료형의 표현 범위가 -838:59:59 ~ 838:59:59로 24시간을 훌쩍 넘어서게 설계된 이유가 바로 TIMEDIFF 때문이다. 두 인자에 날짜가 포함된 DATETIME 값을 넣으면 TIMEDIFF는 날짜 차이까지 반영해 "34일 걸린 시간"도 시:분:초 하나로 눌러 담아야 한다. 이때 34일은 816시간이 넘으므로, 결과가 "일 몇 시간"이 아니라 "몇백 시간 몇 분"처럼 나와 사람이 읽기 불편해진다. 여러 날에 걸친 시간 차이를 다룰 때는 TIMEDIFF보다 TIMESTAMPDIFF(HOUR, ...)TIMESTAMPDIFF(MINUTE, ...)처럼 단위를 직접 지정하는 함수가 훨씬 다루기 쉽다.

※ 근무시간·소요시간처럼 여러 날에 걸칠 가능성이 있는 계산은 TIMEDIFF 대신 TIMESTAMPDIFF를 우선 검토할 것.

7 실전 활용 — 경과일·근무시간 계산에 적용하기
두 함수를 실제로 어디에 쓰는가?

회원 관리 테이블에서 "가입한 지 며칠 됐는지"를 보여주고 싶다면 DATEDIFF(NOW(), join_date) 한 줄로 끝난다. 반대로 근태 기록 테이블에서 "이 사람이 오늘 몇 시간 몇 분 일했는지"를 계산하려면 퇴근 시각과 출근 시각이 같은 날짜 안에 있다는 전제하에 TIMEDIFF(check_out, check_in)을 쓰면 "08:15:00"처럼 바로 화면에 붙일 수 있는 결과가 나온다.

1
경과일 표시DATEDIFF(NOW(), join_date) — "가입 549일째" 같은 문구에 사용
2
근무시간 표시TIMEDIFF(check_out, check_in) — 하루 안에서의 시:분:초 차이 표시에 사용
3
여러 날 누적 시간TIMESTAMPDIFF(HOUR, start, end) — 날짜를 넘나드는 총 시간을 단일 숫자로 집계할 때 사용
4
마감까지 남은 일수DATEDIFF(deadline, NOW()) — 값이 음수가 되면 이미 마감이 지났다는 뜻으로 활용

8 TIME_TO_SEC — TIME 값을 숫자로 바꿔서 계산하기
왜 굳이 초 단위 숫자로 다시 바꾸는가?

TIMEDIFF의 결과가 아무리 사람이 읽기 좋은 "08:30:00" 형태라도, 여러 근무 기록의 평균 근무시간을 구하거나 총합을 내야 한다면 이야기가 달라진다. TIME 값끼리는 SUM()이나 AVG()를 곧이곧대로 적용하기 어렵기 때문에, 먼저 TIME_TO_SEC()으로 순수한 초 단위 정수로 풀어낸 다음 계산하고, 마지막에 다시 SEC_TO_TIME()으로 사람이 읽는 형태로 되돌리는 흐름을 탄다.

TIMEDIFF(a, b)
TIME_TO_SEC(결과)
SUM() / AVG()
SEC_TO_TIME(집계값)
SELECT SEC_TO_TIME(AVG(TIME_TO_SEC(TIMEDIFF(check_out, check_in)))) FROM attendance; -- 근무 기록 여러 건의 평균 근무시간을 다시 시:분:초로 보여준다
※ "숫자로 풀었다가 다시 시간으로 조립한다"는 이 왕복 패턴이 TIME 값을 집계할 때 가장 흔히 쓰는 방식이다.

9 DATEDIFF vs TIMESTAMPDIFF(DAY, ...) — 결과가 같아 보여도 다른 함수
왜 굳이 두 가지 방법이 존재하는가?

DATEDIFF(a, b)TIMESTAMPDIFF(DAY, b, a)는 인자 순서만 다를 뿐 대부분의 경우 같은 결과를 낸다. 차이는 유연성에 있다. DATEDIFF는 오직 '일' 단위만 계산하도록 이름부터 고정돼 있지만, TIMESTAMPDIFF는 첫 번째 인자에 YEAR·MONTH·DAY·HOUR·MINUTE·SECOND 중 원하는 단위를 자유롭게 골라 넣을 수 있다. 즉 DATEDIFF는 "일수 계산 전용 단축 함수"이고, TIMESTAMPDIFF는 "단위를 직접 지정하는 범용 함수"라고 이해하면 된다.

함수 인자 형태 단위 선택 주 용도
DATEDIFF(a, b) 날짜 2개 일(day) 고정 단순 경과일 계산
TIMEDIFF(a, b) 시간 2개 시:분:초 고정 같은 날 안의 시간 차 계산
TIMESTAMPDIFF(단위, b, a) 단위 + 날짜/시간 2개 YEAR~SECOND 자유 선택 여러 날에 걸친 임의 단위 차이 계산
※ "일수만 필요하면 DATEDIFF, 단위를 골라야 하면 TIMESTAMPDIFF"로 기억하면 헷갈리지 않는다.

실제로 두 함수가 같은 결과를 내는지 나란히 놓고 비교해보면 이해가 빠르다.

DATEDIFF(NOW(), join_date) -- 결과: 549 TIMESTAMPDIFF(DAY, join_date, NOW()) -- 결과: 549 (인자 순서가 반대이고 단위를 명시했을 뿐 값은 동일)

10 자주 하는 실수
실수 증상 해결
DATEDIFF 인자 순서를 반대로 넣음 D-day, 경과일이 음수로 표시됨 "최근 날짜 - 과거 날짜" 순서로 항상 최근 값을 앞에 배치
여러 날에 걸친 시간차를 TIMEDIFF로 계산 결과가 "34:00:00"처럼 이상하게 커 보이거나 읽기 어려움 TIMESTAMPDIFF(HOUR, 시작, 종료) 등 단위 지정 함수로 대체
TIMEDIFF 결과를 숫자로 착각해 바로 더하기·평균 계산 합계·평균 값이 실제 시간과 맞지 않음 TIME_TO_SEC()으로 초 단위 정수로 변환 후 연산
DATEDIFF에 시:분:초까지 다른 걸 기대 같은 날 안의 시간차가 무시되고 항상 0이나 정수만 나옴 시간 단위 차이가 필요하면 TIMEDIFF나 TIMESTAMPDIFF 사용
TIMEDIFF에 서로 다른 날짜의 DATETIME을 넣고 24시간 이내라고 가정 결과가 예상보다 훨씬 큰 시:분:초로 출력됨 날짜가 섞일 가능성이 있으면 TIMESTAMPDIFF로 전환
TIMESTAMPDIFF의 단위 인자를 빼먹거나 잘못 지정 기대와 다른 스케일(초 대신 일 등)의 값이 나옴 YEAR/MONTH/DAY/HOUR/MINUTE/SECOND 중 원하는 단위를 첫 인자에 정확히 명시

11 실무 체크 포인트 — 어떤 함수로 저장·집계할지 결정하기

날짜 차이 함수는 결과를 화면에 보여주는 데서 끝나지 않고, 집계·정렬·필터 조건에 다시 들어가는 경우가 많다. 그래서 "보여줄 값"과 "계산할 값"을 분리해서 생각하면 실수가 줄어든다.

1
일수만 필요하면 DATEDIFF가입일, 마감일, 유효기간처럼 하루 단위로 끊어 세는 값은 정수로 받는 편이 가장 단순하다.
2
시:분:초 표시가 필요하면 TIMEDIFF하루 안의 출근·퇴근 차이처럼 사용자가 시간 형태를 그대로 봐야 하는 화면에 적합하다.
3
집계는 숫자 단위로 변환평균·합계·정렬을 해야 하면 TIME_TO_SEC 또는 TIMESTAMPDIFF로 숫자를 만든 뒤 계산한다.
4
출력 직전에 다시 포맷초 단위로 계산한 값은 SEC_TO_TIME 또는 애플리케이션 포맷 함수로 마지막에 보기 좋게 바꾼다.
핵심은 저장·집계 단계에서는 숫자가 편하고, 화면 표시 단계에서는 날짜/시간 형식이 편하다는 점이다. 한 함수로 모든 단계를 해결하려고 하면 쿼리가 더 복잡해진다.

핵심 한 줄 요약

DATEDIFF(a, b)a - b를 '일수'(정수)로 반환 — 시:분:초는 무시
TIMEDIFF(a, b)a - b를 '시:분:초'(TIME)로 반환 — 정밀한 시간 흐름 표현
인자 순서항상 "최근 값 - 과거 값" 순서로 넣어야 결과가 양수로 나온다
여러 날 걸친 시간 차TIMEDIFF 대신 TIMESTAMPDIFF로 단위를 직접 지정할 것

Tags

#MySQL #DATEDIFF #TIMEDIFF #날짜차이 #시간차이 #날짜함수 #NOW #CURDATE #TIMESTAMPDIFF #SQL #데이터베이스 #DB #날짜계산 #시간계산 #웹개발 #티스토리
▼ 티스토리 태그 입력란 복사용
MySQL, DATEDIFF, TIMEDIFF, 날짜차이, 시간차이, 날짜함수, NOW, CURDATE, TIMESTAMPDIFF, SQL, 데이터베이스, DB, 날짜계산, 시간계산, 웹개발, 티스토리
반응형

댓글