날짜 및 시간 함수

날짜 및 시간 함수

이 페이지에서는 SQLite의 날짜 및 시간 함수들을 설명해요. 날짜와 시간 값을 표현하거나 계산하는 데 쓰이는 다양한 함수와 형식, 수정자(modifier) 사용법을 다뤄요.

출처: 문서

본문

1. 개요

SQLite는 다음과 같이 7개의 스칼라 날짜 및 시간 함수를 지원해요.

  • date(time-value, modifier, modifier, ...)
  • time(time-value, modifier, modifier, ...)
  • datetime(time-value, modifier, modifier, ...)
  • julianday(time-value, modifier, modifier, ...)
  • unixepoch(time-value, modifier, modifier, ...)
  • strftime(format, time-value, modifier, modifier, ...)
  • timediff(time-value, time-value)

첫 여섯 개의 날짜/시간 함수는 선택적 시간 값을 인수로 받고, 그 뒤에 수정자를 0개 이상 받아요. strftime() 함수는 첫 번째 인수로 형식 문자열을 추가로 받아요. timediff() 함수는 정확히 두 개의 인수를 받으며, 두 인수 모두 시간 값이에요.

SQLite에는 전용 날짜/시간 데이터 타입이 없어요. 대신 날짜와 시간 값을 다음 중 하나로 저장할 수 있어요.

형식 의미
ISO-8601 아래 1~10번 항목에 표시된 ISO 8601 날짜/시간 값 중 하나인 텍스트 문자열. 예: '2025-05-29 14:16:00'
Julian day number -4713-11-24 12:00:00 이후의 일수(소수 일수 포함). 예: 2460825.09444444
Unix timestamp 1970-01-01 00:00:00 이후의 초 수(소수 초 포함). 예: 1748528160

이 세 가지 형식을 통틀어 시간 값(time-value)이라고 해요. 모든 날짜/시간 함수는 ISO-8601 텍스트 또는 Julian day number 형태의 시간 값을 받아요. 선택적 수정자 인수로 'auto' 또는 'unixepoch'를 추가하면 유닉스 타임스탬프도 받아들일 수 있어요. timediff() 함수는 수정자를 받지 않으므로 ISO-8601 및 Julian day number 시간 값만 사용할 수 있어요.

date() 함수는 날짜를 YYYY-MM-DD 형식의 텍스트로 반환해요.

time() 함수는 시간을 HH:MM:SS 형식의 텍스트로 반환해요. subsec 수정자를 사용하면 HH:MM:SS.SSS 형식으로 반환해요.

datetime() 함수는 날짜와 시간을 YYYY-MM-DD HH:MM:SS 형식으로 반환해요. subsec 수정자를 사용하면 YYYY-MM-DD HH:MM:SS.SSS 형식으로 반환해요.

julianday() 함수는 Julian day(율리우스 일)를 반환해요. 이는 기원전 4714년 11월 24일 그리니치 정오 이후의 소수 일수예요(선행 그레고리력 기준).

unixepoch() 함수는 유닉스 타임스탬프, 즉 1970-01-01 00:00:00 UTC 이후의 초 수를 반환해요. unixepoch() 함수는 보통 정수 초를 반환하지만, 선택적 subsec 수정자를 사용하면 소수 초를 포함한 부동 소수점 수를 반환해요.

strftime() 함수는 첫 번째 인수로 지정된 형식 문자열에 따라 날짜를 반환해요. 형식 문자열은 표준 C 라이브러리의 strftime() 함수에 있는 가장 일반적인 치환자들을 지원하며, 여기에 %f%J 두 가지 새 치환자가 추가돼요. 다음은 버전 3.46.0(2024-05-23) 기준 유효한 strftime() 치환자의 전체 목록이에요. 이전 버전의 SQLite에서는 일부 치환자를 지원하지 않을 수 있어요. 정의되지 않았거나 지원되지 않는 치환자를 만나면 결과는 NULL이에요.

치환자 의미
%d 일(day of month): 01-31
%e 앞자리 0 없는 일: 1-31
%f 소수 초: SS.SSS
%F ISO 8601 날짜: YYYY-MM-DD
%G %V에 해당하는 ISO 8601 연도
%g %V에 해당하는 2자리 ISO 8601 연도
%H 시: 00-24
%I 12시간제 시: 01-12
%j 연중 일수: 001-366
%J Julian day number(소수)
%k 앞자리 0 없는 시: 0-24
%l 앞자리 0 없는 %I: 1-12
%m 월: 01-12
%M 분: 00-59
%p 시간에 따라 "AM" 또는 "PM"
%P 시간에 따라 "am" 또는 "pm"
%R ISO 8601 시간: HH:MM
%s 1970-01-01 이후 초 수
%S 초: 00-59
%T ISO 8601 시간: HH:MM:SS
%U 연중 주차(00-53) - 01주는 첫 번째 일요일에 시작
%u 요일 1-7, 월요일==1
%V ISO 8601 연중 주차
%w 요일 0-6, 일요일==0
%W 연중 주차(00-53) - 01주는 첫 번째 월요일에 시작
%Y 연: 0000-9999
%% % 기호

다른 날짜/시간 함수들은 strftime()으로 표현할 수 있어요.

함수 동등한 strftime()
date(...) strftime('%F', ...)
time(...) strftime('%T', ...)
datetime(...) strftime('%F %T', ...)
julianday(...) CAST(strftime('%J', ...) as REAL)
unixepoch(...) CAST(strftime('%s', ...) as INT)

date(), time(), datetime() 함수는 모두 텍스트를 반환하므로 대응하는 strftime() 표현과 정확히 일치해요. 하지만 julianday()와 unixepoch() 함수는 숫자 값을 반환해요. 이에 대응하는 strftime() 표현은 해당 숫자의 텍스트 표현을 문자열로 반환해요.

strftime() 외에 별도의 함수를 제공하는 주된 이유는 편의성과 효율성이에요. julianday()와 unixepoch() 함수는 각각 실수와 정수 값을 반환하며, strftime() 함수에서 '%J' 또는 '%s' 형식 지정자를 사용할 때 발생하는 형식 변환 비용이나 부정확성이 없어요.

timediff(A,B) 함수는 시간 A에 도달하기 위해 B에 더해야 하는 시간의 양을 설명하는 문자열을 반환해요. timediff() 결과의 형식은 사람이 읽기 쉽게 설계되었어요. 형식은 다음과 같아요.

(+|-)YYYY-MM-DD HH:MM:SS.SSS

이 시간 차이 문자열은 다른 날짜/시간 함수에서 허용되는 수정자로도 쓸 수 있어요. 시간 값 A와 B에 대해 다음 불변식이 성립해요.

datetime(A) = datetime(B, timediff(A,B))

월과 연의 길이는 서로 달라요. 2월은 3월보다 짧고, 윤년은 평년보다 길어요. timediff()의 출력은 이 모든 것을 고려해요. timediff() 함수는 시간 간격을 사람에게 친숙하게 설명하기 위한 것이에요. A와 B 두 날짜 사이의 일수나 초 수를 알고 싶다면 항상 다음 중 하나를 사용하면 돼요.

SELECT julianday(B) - julianday(A);

SELECT unixepoch(B) - unixepoch(A);

timediff(A,B)는 시작 날짜에 따라 서로 다른 일수를 포함하는 A와 B에 대해 같은 결과를 반환할 수도 있어요. 예를 들어 다음 두 timediff() 호출은 첫 번째 시간 간격이 28일이고 두 번째가 31일임에도 불구하고 둘 다 같은 결과(-0000-01-00 00:00:00.000)를 반환해요.

SELECT timediff('2023-02-15','2023-03-15');

SELECT timediff('2023-03-15','2023-04-15');

요약하면, 사람이 읽기 좋은 시간 간격을 원하면 timediff()를 사용하세요. 정확한 시간 차이(일 또는 초)를 원하면 julianday() 또는 unixepoch() 호출 두 개의 차이를 사용하세요.

2. 시간 값

시간 값은 아래에 표시된 형식 중 하나일 수 있어요. 값은 보통 문자열이지만, 형식 12의 경우 정수 또는 부동 소수점 숫자일 수 있어요.

  • YYYY-MM-DD
  • YYYY-MM-DD HH:MM
  • YYYY-MM-DD HH:MM:SS
  • YYYY-MM-DD HH:MM:SS.SSS
  • YYYY-MM-DDTHH:MM
  • YYYY-MM-DDTHH:MM:SS
  • YYYY-MM-DDTHH:MM:SS.SSS
  • HH:MM
  • HH:MM:SS
  • HH:MM:SS.SSS
  • now
  • DDDDDDDDDD

57번 형식에서 "T"는 ISO-8601에서 요구하는, 날짜와 시간을 구분하는 리터럴 문자예요. 810번처럼 시간만 지정하는 형식은 날짜를 2000-01-01로 간주해요. 11번 형식, 즉 문자열 'now'는 사용 중인 sqlite3_vfs 객체의 xCurrentTime 메서드로 얻은 현재 날짜와 시간으로 변환돼요. date 및 time 함수에 전달되는 'now' 인수는 같은 sqlite3_step() 호출 안에서 여러 번 호출되어도 항상 정확히 같은 값을 반환해요. UTC(협정 세계시)를 사용해요. 12번 형식은 정수 또는 부동 소수점 값으로 표현된 Julian day number예요. 12번 형식은 바로 뒤에 'auto' 또는 'unixepoch' 수정자가 오면 유닉스 타임스탬프로 해석될 수도 있어요.

2~10번 형식에는 [+-]HH:MM 또는 Z 형태의 시간대 표시가 선택적으로 뒤에 올 수 있어요. 날짜/시간 함수는 내부적으로 UTC 또는 "zulu" 시간을 사용하므로 "Z" 접미사는 아무 효과가 없어요. 0이 아닌 "HH:MM" 접미사는 zulu 시간을 계산하기 위해 표시된 날짜와 시간에서 빼져요. 예를 들어 다음 시간 값들은 모두 서로 동일해요.

2013-10-07 08:23:19.120
2013-10-07T08:23:19.120Z
2013-10-07 04:23:19.120-04:00
2456572.84952685

4번, 7번, 10번 형식에서 소수 초 값 SS.SSS는 소수점 뒤에 한 자리 이상의 숫자를 가질 수 있어요. 예시에서는 정확히 세 자리를 보여주는데, 결과에 유효한 것은 처음 세 자리뿐이지만 입력 문자열은 세 자리보다 적거나 많아도 날짜/시간 함수는 여전히 올바르게 동작해요. 마찬가지로 12번 형식은 10자리 유효 숫자로 표시되지만, 날짜/시간 함수는 Julian day number를 표현하는 데 필요한 만큼 많거나 적은 숫자를 실제로 받아들여요.

ISO-8601은 다양한 대체 날짜/시간 형식을 지원하지만, SQLite는 위에 열거된 형식들만 지원해요.

timediff()를 제외한 모든 함수에서는 시간 값(및 모든 수정자)을 생략할 수 있으며, 이 경우 시간 값은 'now'로 간주돼요.

3. 수정자(Modifiers)

timediff()를 제외한 모든 날짜/시간 함수에서는 time-value 인수 뒤에 날짜 및/또는 시간을 변경하는 수정자를 0개 이상 붙일 수 있어요. 각 수정자는 왼쪽에 있는 time-value에 적용되는 변환이에요. 수정자는 왼쪽에서 오른쪽으로 적용되므로 순서가 중요해요. 사용할 수 있는 수정자는 다음과 같아요.

  • NNN days

  • NNN hours

  • NNN minutes

  • NNN seconds

  • NNN months

  • NNN years

  • ±HH:MM

  • ±HH:MM:SS

  • ±HH:MM:SS.SSS

  • ±YYYY-MM-DD

  • ±YYYY-MM-DD HH:MM

  • ±YYYY-MM-DD HH:MM:SS

  • ±YYYY-MM-DD HH:MM:SS.SSS

  • ceiling

  • floor

  • start of month

  • start of year

  • start of day

  • weekday N

  • unixepoch

  • julianday

  • auto

  • localtime

  • utc

  • subsec

  • subsecond

처음 13개 수정자(113)는 왼쪽 인수로 지정된 날짜와 시간에 지정된 양의 시간을 더해요. 16번 수정자 이름 끝의 's' 문자는 선택 사항이에요. NNN 값은 선택적으로 '+' 또는 '-' 접두사를 붙일 수 있는 임의의 부동 소수점 숫자예요.

시간 이동 수정자(713)는 지정된 년, 월, 일, 시, 분, 초 수만큼 time-value를 이동시켜요. 1013 형식에는 '+' 또는 '-' 접두사가 필수이고, 7, 8, 9 형식에는 선택이에요. 변경은 왼쪽에서 오른쪽으로 적용돼요. 먼저 연도가 YYYY만큼 이동하고, 그 다음 월이 MM만큼, 그 다음 일이 DD만큼 이동하는 식이에요. timediff(A,B) 함수는 B time-value를 A로 이동시키는 13번 형식의 시간 이동을 반환해요.

한 달이나 1년의 길이는 달과 연도마다 다르기 때문에 날짜를 월 및/또는 연 단위로 이동할 때 모호함이 생길 수 있어요. 예를 들어 2024-02-29의 1년 뒤 날짜는 무엇일까요? 2025-02-28일까요, 2025-03-01일까요? 또는 2023-12-31의 두 달 뒤 날짜는 무엇일까요? 2024-02-29일까요, 2024-03-02일까요? 이 모호성을 해결하는 방법에는 합의가 없어서, 프로그래머가 결정할 수 있도록 "ceiling"과 "floor" 수정자(14와 15)가 있어요. 시간 이동 다음에 오는 수정자가 "ceiling"이면 날짜의 모호함은 더 나중 날짜를 선택하여 해결돼요. "floor" 수정자는 이전 달의 마지막 날로 결정함으로써 모호함을 해결해요. 기본 동작은 "ceiling"이에요.

"start of" 수정자(16~18)는 날짜를 해당 월, 연도, 또는 일의 시작 시점으로 뒤로 이동시켜요.

"weekday" 수정자는 필요한 경우 요일 번호가 N인 다음 날짜로 날짜를 앞으로 이동시켜요. 일요일은 0, 월요일은 1, 이런 식이에요. 날짜가 이미 원하는 요일이면 "weekday" 수정자는 날짜를 변경하지 않아요.

"unixepoch" 수정자(20)는 DDDDDDDDDD 형식의 time-value 바로 뒤에 올 때만 동작해요. 이 수정자는 DDDDDDDDDD가 평소처럼 율리우스 일 수로 해석되지 않고, 1970년 이후의 초 수인 Unix Time으로 해석되도록 해요. 만약 "unixepoch" 수정자가 1970년 이후의 초 수를 나타내는 DDDDDDDDDD 형식의 time-value 뒤에 오지 않거나, 다른 수정자가 "unixepoch" 수정자와 앞선 DDDDDDDDDD 사이에 있으면 동작은 정의되지 않아요.

"julianday" 수정자는 초기 time-value 바로 뒤에 와야 하며, 그 값은 DDDDDDDDD 형식이어야 해요. 'julianday' 수정자의 다른 모든 사용은 오류이며 함수가 NULL을 반환하게 해요. 'julianday' 수정자는 time-value 숫자가 율리우스 일 수로 해석되도록 강제해요. 이것은 기본 동작이므로 'julianday' 수정자는 사실상 no-op(아무 작업도 하지 않는 것)과 다름없어요. 유일한 차이점은 'julianday'를 추가하면 DDDDDDDDD time-value 형식이 강제되고, 다른 time-value 형식이 사용되면 NULL이 반환된다는 점이에요.

"auto" 수정자는 초기 time-value 바로 뒤에 와야 해요. time-value가 숫자(DDDDDDDDDD 형식)이면 'auto' 수정자는 그 값을 크기에 따라 율리우스 일 수 또는 유닉스 타임스탬프로 해석해요. 값이 0.0과 5373484.499999 사이이면 율리우스 일 수(-4713-11-24 12:00:00에서 9999-12-31 23:59:59 사이의 날짜에 해당)로 해석돼요. 유효한 율리우스 일 수 범위를 벗어나지만 -210866760000에서 253402300799 사이의 숫자 값이면 'auto' 수정자는 그 값을 유닉스 타임스탬프로 해석해요. 그 외의 숫자 값은 범위를 벗어나므로 NULL을 반환해요. 'auto' 수정자는 ISO 8601 텍스트 time-value에는 아무 효과가 없어요. 'auto' 수정자는 데이터베이스 파일에 어떤 time-value 형식이 저장되어 있는지 알 수 없거나, 같은 열에 서로 다른 행들이 서로 다른 형식의 time-value를 저장하는 경우에도 작동하도록 설계되었어요. 'auto' 수정자는 적절한 형식을 자동으로 선택해요. 다만 약간의 모호함이 있어요. 1970년의 첫 63일 유닉스 타임스탬프는 율리우스 일 수로 해석될 거예요. 'auto' 수정자는 데이터셋에 그 범위의 날짜가 없음이 보장될 때 아주 유용하지만, 1970년 초반의 날짜를 사용할 수 있는 애플리케이션에서는 피해야 해요.

"localtime" 수정자는 왼쪽의 time-value가 UTC(Universal Coordinated Time)라고 가정하고 그 값을 현지 시간(localtime)으로 조정해요. 'localtime' 뒤에 UTC가 아닌 시간이 오면 동작은 정의되지 않아요. "utc" 수정자는 'localtime'의 반대예요. 'utc'는 왼쪽의 time-value가 현지 시간대라고 가정하고 그 값을 UTC로 조정해요. 왼쪽 시간이 현지 시간이 아니면 'utc'의 결과는 정의되지 않아요.

"subsecond" 수정자("subsec"로 줄여 쓸 수 있어요)는 datetime(), time(), unixepoch()의 출력과 strftime()의 "%s" 형식 문자열의 해상도를 높여요. 'subsecond' 수정자는 다른 날짜/시간 함수에는 영향을 주지 않아요. 현재 구현은 해상도를 초에서 밀리초로 높이지만, SQLite의 향후 릴리스에서는 더 높은 해상도로 높아질 수 있어요. 'subsec'을 datetime()이나 time()과 함께 사용하면 끝의 초 필드 뒤에 소수점과 한 자리 이상의 숫자가 붙어 분수 초를 보여줘요. 'subsec'을 unixepoch()과 함께 사용하면 결과는 1970-01-01 이후의 초 및 분수 초를 나타내는 부동 소수점 값이에요. 'subsecond'와 'subsec' 수정자는 날짜/시간 함수의 첫 번째 인수(또는 strftime()의 형식 문자열 다음 첫 번째 인수)로 올 수 있는 특별한 속성이 있어요. 이 경우 보통 첫 번째 인수에 오는 time-value는 "now"로 간주돼요. 예를 들어, 1970년 이후 현재 시간을 밀리초 정밀도의 초 단위로 얻는 지름길은 다음과 같아요:

SELECT unixepoch('subsec');

4. 예시

현재 날짜를 계산해요.

SELECT date();

현재 달의 마지막 날을 계산해요.

SELECT date('now','start of month','+1 month','-1 day');

유닉스 타임스탬프 1092941466이 주어졌을 때 날짜와 시간을 계산해요.

SELECT datetime(1092941466, 'unixepoch');

SELECT datetime(1092941466, 'auto'); -- Does not work for early 1970!

유닉스 타임스탬프 1092941466이 주어졌을 때 날짜와 시간을 계산하고, 현지 시간대를 보정해요.

SELECT datetime(1092941466, 'unixepoch', 'localtime');

현재 유닉스 타임스탬프를 계산해요.

SELECT unixepoch();

SELECT strftime('%s');

미국 독립 선언 서명 이후 경과한 일 수를 계산해요.

SELECT julianday('now') - julianday('1776-07-04');

2004년의 특정 시점 이후 경과한 초 수를 계산해요.

SELECT unixepoch() - unixepoch('2004-01-01 02:34:56');

올해 10월의 첫 번째 화요일 날짜를 계산해요.

SELECT date('now','start of year','+9 months','weekday 2');

유닉스 시대 이후의 시간을 밀리초 정밀도의 초 단위로 계산해요.

SELECT (julianday('now') - 2440587.5)*86400.0;

SELECT unixepoch('now','subsec');

에이브러햄 링컨이 오늘날까지 살아 있다면 그의 나이가 몇인지 계산해요.

SELECT timediff('now','1809-02-12');

5. 주의사항 및 버그

현지 시간 계산은 정치인의 변덕에 크게 의존하므로 모든 지역에서 정확하게 계산하기 어려워요. 이 구현에서는 표준 C 라이브러리 함수인 localtime_r()을 사용하여 현지 시간 계산을 돕고 있어요. localtime_r() C 함수는 일반적으로 1970년에서 2037년 사이의 연도에서만 작동해요. 이 범위를 벗어난 날짜의 경우 SQLite는 연도를 이 범위 안의 동등한 연도로 매핑한 다음 계산을 수행하고, 다시 연도를 매핑해요.

이 함수들은 0000-01-01 00:00:00에서 9999-12-31 23:59:59 사이의 날짜에서만 작동해요(율리우스 일 수 1721059.5부터 5373484.5까지). 이 범위를 벗어난 날짜에 대한 함수 결과는 정의되지 않아요.

Non-Vista Windows 플랫폼은 한 세트의 DST(일광 절약 시간) 규칙만 지원해요. Vista는 두 세트만 지원해요. 따라서 이러한 플랫폼에서는 과거의 DST 계산이 부정확할 거예요. 예를 들어, 미국에서는 2007년에 DST 규칙이 변경되었어요. Non-Vista Windows 플랫폼은 이전의 모든 해에도 새로운 2007 DST 규칙을 적용해요. Vista는 규칙이 역시 변경된 1986년까지는 결과를 다소 더 정확하게 얻을 수 있어요.

모든 내부 계산은 그레고리력(Gregorian calendar) 체계를 가정해요. 또한 매일의 길이가 정확히 86400초라고 가정하며, 윤초는 포함되지 않아요.

이 페이지는 2026-07-11 15:07:16Z에 마지막으로 업데이트되었어요.

더 알아보기 (Learn more)