날짜와 시간 자료
R의 날짜와 시간
“2018년 최대 황금연휴였던 추석은 2019년엔 아쉬움을 줄 것 같습니다.”
R에서 날짜와 시간을 나타내는 데 쓰이는 클래스는 세 다음의 세 가지이다.
Date
: 날짜를 나타낸다. 내부적으로 1970년 1월 1일 이후 경과된 일 수를 저장한다.POSIXct
: 날짜-시간을 나타낸다. 내부적으로 1970년 1월 1일에서 경과된 초 수와 타임존을 저장한다.POSIXlt
: 날짜-시간을 나타낸다. 내부적으로는 1900년에서 경과된 년수, 월, 일, 시간, 분, 초, 타임존 등을 리스트의 형태로 저장한다.
다음은 R 함수를 활용하여 현재 날짜와 시간을 구한 후 이를 저장하고 데이터 타입을 확인한다.
dateNow <- Sys.Date()
print(dateNow)
class(dateNow)
## [1] "2019-04-11" ## [1] "Date"
timeNow <- Sys.time()
print(timeNow)
class(timeNow)
## [1] "2019-04-11 03:06:19 KST" ## [1] "POSIXct" "POSIXt"
unclass
는 dateNow
와 timeNow
에 날짜와 시간이 어떻게 저장되어 있는지를 보여준다. print.default()
를 써도 된다.
unclass(dateNow); print.default(dateNow)
## [1] 17997
## [1] 17997 ## attr(,"class") ## [1] "Date"
unclass(timeNow); print.default(timeNow)
## [1] 1554919579
## [1] 1554919579 ## attr(,"class") ## [1] "POSIXct" "POSIXt"
날짜의 표기
-
날짜를 표기하는 방식은 나라마다, 그리고 상황에 따라 다르다. 우리나라는 '2020년 1월 3일'이라고 쓰고, 미국에서는 'Jan. 3. 2020'이라고 쓰며, 유럽에서는 '3. Jan. 2020'이라고 쓴다.
-
나라마다 다르게 표기될 수 있는 날짜를 R의 날짜(
Date
) 타입으로 변환할 때에는 주의를 해야 한다. 예를 들어 '01-03-2020'은 미국에서는 '2020년 1월 3일'이지만, 유럽(영국)에서는 '2020년 3월 1일'을 의미한다.
ISO 8601 날짜
ISO는 국제 표준을 만드는 국제기관으로 날짜를 표기하는 표준인 ISO 8601에서 명시하는 날짜 표기 표준은 다음과 같다.
스타일 | 표기 | 의미 | 예 |
---|---|---|---|
기본형 | (+-)YYYYMMDD |
년월일 | 20200103 |
확장형 | (+-)YYYY-MM-DD |
년-월-일 | 2020-01-03 |
기본형 | (+-)YYYYDDD |
년일(1년의 몇번째 일) | 2020003 |
확장형 | (+-)YYYY-DDD |
년-일(1년의 몇번째 일) | 2020-003 |
기본형 | (+-)YYYYWwwD |
년주일 | 2020W013 |
확장형 | (+-)YYYY-Www-D |
년-W주-일 | 2020-W01-3 |
ISO 8601 시간
스타일 | 표기 | 의미 |
---|---|---|
기본형 | hhmmss(,ss)(Z)(+-hh(:)mm) |
시분초(,100분의 1초)(Z )(타임존) |
확장형 | hh:mm:ss(,ss)(Z)(+-hh(:)mm) |
년-월-일(,100분의 1초)(Z )(타임존) |
- 기본형으로
061415,99
는 6시 14분 15초 99를,123544,01
는 12시 35분 44초 01을 나타낸다. - 확장형의 예로
06:14:15,99Z+09:00
는 우리나라 시간(GMT+9)으로 6시 14분 15초 99를 나타낸다.
ISO 8601 날짜-시간
만약 날짜와 시간을 한꺼번에 나타내고자 한다면 날짜와 시간 사이를 바로 연결하거나 T
또는 공란으로 연결한다.
예를 들어 “2020년 1월 3일 16시 14분 15초 99"는 다음 중의 하나로 쓸 수 있다.
20200103161415,99
20200103T161415,99
20200103 161415,99
날짜 표기 변환
현재 시간을 ISO 8601의 날짜 시간 표기방법으로 나타내는 방법은 다음과 같다.
x <- Sys.time()
format(x, '%Y-%m-%d %H:%M:%S')
format(x, '%Y-%jT%H:%M:%S')
format(x, '%G-W%V-%u %H:%M:%S')
## [1] "2019-04-11 03:06:19" ## [1] "2019-101T03:06:19" ## [1] "2019-W15-4 03:06:19"
앞에서 날짜 표기를 변환할 때 쓰인 기호와 의미는 다음과 같다.
기호 | 의미 |
---|---|
%Y |
4자리 년 |
%G |
4자리 년(아래 설명 참조) |
%m |
2자리 월 |
%d |
2자리 (월 중) 일(01-31) |
%H |
2자리 시간(00-23) |
%M |
2자리 분(00-59) |
%S |
2자리 초(00-59) |
%j |
3자리 (년 중) 일(001-366) |
%V |
2자리 (년 중) 주(01-53) |
%u |
1자리 (주 중) 일(1-7, 1=월요일) |
여기서 (년 중) 주와 (주 중) 일을 표기하는 방식은 다음에서 보듯이 여러 가지가 있다.
-
(년 중) 주
%V
: ISO 8601의 주와 일치한다. 1월 1일이 월, 화, 수, 목요일이면 새해의 첫째주, 금, 토, 일요일이면 지난 해의 마지막 주로 표기한다.%U
: 1월 1일이 일요일이면 첫번째 주, 그 밖에는 0번째 주로 표기한다.
-
(주 중) 일
%u
: 일월화수목금토일 순서로 71234567%w
: 일월화수목금토일 순서로 01234560
for (y in 2020:2027)
print(format(as.Date(paste0(y, '-01-01', sep='')), '%Y/%m/%d, V=%V U=%U u=%u w=%w A=%A a=%a'))
## [1] "2020/01/01, V=01 U=00 u=3 w=3 A=수요일 a=수" ## [1] "2021/01/01, V=53 U=00 u=5 w=5 A=금요일 a=금" ## [1] "2022/01/01, V=52 U=00 u=6 w=6 A=토요일 a=토" ## [1] "2023/01/01, V=52 U=01 u=7 w=0 A=일요일 a=일" ## [1] "2024/01/01, V=01 U=00 u=1 w=1 A=월요일 a=월" ## [1] "2025/01/01, V=01 U=00 u=3 w=3 A=수요일 a=수" ## [1] "2026/01/01, V=01 U=00 u=4 w=4 A=목요일 a=목" ## [1] "2027/01/01, V=53 U=00 u=5 w=5 A=금요일 a=금"
날짜시간 표기 인식
ISO 8601
위에서 소개한 ISO 8601의 날짜 표기를 날짜 타입으로 정확하게 인식하기 위해서는 as.Date('', format='')
의 format=
에 정확한 값을 넣어야 한다.
표기 | 의미 | 예 | 날짜로 변환 |
---|---|---|---|
(+-)YYYYMMDD |
년월일 | 20250103 |
format='%Y%m%d' |
(+-)YYYY-MM-DD |
년-월-일 | 2025-01-03 |
format='%Y-%m-%d' |
(+-)YYYYDDD |
년일(1년의 몇번째 일) | 2025003 |
format='%Y%j' |
(+-)YYYY-DDD |
년-일(1년의 몇번째 일) | 2025-003 |
format='%Y-%j' |
(+-)YYYYWwwD |
년주일 | 2025W013 |
|
(+-)YYYY-Www-D |
년-W주-일 | 2025-W01-3 |
library(parsedate)
as.Date('20210102', format='%Y%m%d'); as.Date(parse_iso_8601('20210102'))
as.Date('2021-01-02', format='%Y-%m-%d'); as.Date(parse_iso_8601('2021-01-02'))
## [1] "2021-01-02" ## [1] "2021-01-02" ## [1] "2021-01-02" ## [1] "2021-01-02"
as.Date('2021002', format='%Y%j'); as.Date(parse_iso_8601('2021002'))
as.Date('2021-002', format='%Y-%j'); as.Date(parse_iso_8601('2021-002'))
## [1] "2021-01-02" ## [1] "2021-01-02" ## [1] "2021-01-02" ## [1] "2021-01-02"
%V
의 경우는 as.Date
의 format=
에 사용될 수 없다. 따라서 YYY-Www-D
형식의 문자열을 날짜 타입으로 바꾸려면 parsedate::parse_iso_8601()
함수를 사용하는 게 편하다. 이때 타임존이 'UTC'
로 설정되므로 적절하게 바꿔줘야 함을 유의하자.
as.Date(parse_iso_8601('2025W013'))
as.Date(parse_iso_8601('2025-W01-3'))
as.Date(parse_iso_8601('2020W536'))
as.Date(parse_iso_8601('2020-W53-6'))
## [1] "2021-01-02" ## [1] "2021-01-02"
일상적인 날짜시간 표기 인식
- 앞에서도 얘기했듯이 미국에서는
Jan. 1, 2020
또는January 1 2020
과 같은 표기를 자주 쓴다. 이를 R에서 날짜타입으로 인식하려면Jan
또는January
를 1월로 인식해야 한다. 한 가지 방법은Sys.setlocale("LC_ALL", "English")
을 통해 잠시 지역 설정을 미국으로 변경하는 것이다.[date0]
[date0]: Sys.setlocale()
로 지역을 설정하는 방법은 운영체제에 따라 다르다. 예를 들어 시간 설정을 독일로 하려면 대부분의 Unix에서는 Sys.setlocale("LC_TIME","de_DE")
, 윈도우에서는 Sys.setlocale("LC_TIME", "German")
으로 쓴다. 이 책에서는 윈도우 체제를 기본으로 하였다. 자세한 사항은 ?Sys.setlocale
(Sys.setlocale
도움말)을 참조하기 바란다.
library(magrittr)
as.Date('Jan 01 2020', format='%b %d %Y')
as.Date('January 01 2020', format='%B %d %Y')
Sys.getlocale("LC_ALL") %>% strsplit(";")
## [1] NA ## [1] NA ## [[1]] ## [1] "LC_COLLATE=Korean_Korea.949" "LC_CTYPE=Korean_Korea.949" ## [3] "LC_MONETARY=Korean_Korea.949" "LC_NUMERIC=C" ## [5] "LC_TIME=Korean_Korea.949"
Sys.setlocale("LC_ALL", "English") %>% strsplit(";")
as.Date('Jan 01 2020', format='%b %d %Y')
as.Date('January 01 2020', format='%B %d %Y')
## [[1]] ## [1] "LC_COLLATE=English_United States.1252" ## [2] "LC_CTYPE=English_United States.1252" ## [3] "LC_MONETARY=English_United States.1252" ## [4] "LC_NUMERIC=C" ## [5] "LC_TIME=English_United States.1252" ## ## [1] "2020-01-01" ## [1] "2020-01-01"
Sys.setlocale("LC_ALL", "Korean") %>% strsplit(";")
package:lubridate
의ymd()
,ydm()
,dmy()
등의 함수를 활용하면 좀 더 편하게 일상적인 날짜 표기를 날짜 타입으로 변환할 수 있다. 하지만 다음의 예를 보면 영어를 제외한 언어에서는 문제가 있어 보인다. 이런 결과는 아마도 플랫폼(예. 윈도우, 유닉스 등)에 따라 달라질 것이다.
as.Date('March 01 2020', format='%B %d %Y')
# Mars is the 3rd month of the year in French
as.Date('Mars 01 2020', format='%B %d %Y')
## [1] NA ## [1] NA
mdy('March 01 2020')
mdy('Mars 01 2020', locale='French')
Sys.setlocale("LC_ALL", "French") %>% strsplit(";")
## [1] "2020-03-01" ## [1] "2020-01-20" ## [[1]] ## [1] "LC_COLLATE=French_France.1252" "LC_CTYPE=French_France.1252" ## [3] "LC_MONETARY=French_France.1252" "LC_NUMERIC=C" ## [5] "LC_TIME=French_France.1252"
as.Date('Mars 01 2020', format='%B %d %Y')
as.Date('March 01 2020', format='%B %d %Y')
mdy('March 01 2020')
mdy('Mars 01 2020')
## [1] "2020-03-01" ## [1] NA ## [1] "2020-03-01" ## [1] "2020-01-20"
Sys.setlocale("LC_ALL", "Korean") %>% strsplit(";")
mdy('Mars 01 2020', locale='French_France.1252')
## [[1]] ## [1] "LC_COLLATE=Korean_Korea.949" "LC_CTYPE=Korean_Korea.949" ## [3] "LC_MONETARY=Korean_Korea.949" "LC_NUMERIC=C" ## [5] "LC_TIME=Korean_Korea.949" ## ## [1] "2020-01-20"
wday( , label=TRUE)
,month( , label=TRUE)
등은 제대로 작동한다.
wday(today(), label = TRUE, abbr = FALSE, locale = "German")
## Error in wday(today(), label = TRUE, abbr = FALSE, locale = "German"): unused arguments (label = TRUE, abbr = FALSE, locale = "German")
wday(today(), label = TRUE, abbr = FALSE, locale = "French")
## Error in wday(today(), label = TRUE, abbr = FALSE, locale = "French"): unused arguments (label = TRUE, abbr = FALSE, locale = "French")
month(today(), label = TRUE, abbr = FALSE, locale = "German")
## Error in month(today(), label = TRUE, abbr = FALSE, locale = "German"): unused arguments (label = TRUE, abbr = FALSE, locale = "German")
month(today(), label = TRUE, abbr = FALSE, locale = "French")
## Error in month(today(), label = TRUE, abbr = FALSE, locale = "French"): unused arguments (label = TRUE, abbr = FALSE, locale = "French")
날짜와 시간을 동시에 인식하기 위해서는 strptime()
/as.POSIXct()
또는 ymd_hms()
류의 함수를 사용할 수 있다.
strptime()
과as.POSIXct()
의 경우 타임존을 정해주지 않고 현재 사용하고 있는 타임존으로 설정한다. 현재 타임존은Sys.timezone()
으로 알 수 있다.ymd_hms()
의 경우tz=
로 타임존을 정해주지 않으면 타임존의 기본값은UTC
이다.tz=
설정 시tz='KST'
는 작동하지 않는다.tz='Asia/Seoul'
로 해야 한다.
Sys.setlocale("LC_ALL", "English") %>% strsplit(";")
as.POSIXct('March 01 2020 11:13:22', format='%B %d %Y %H:%M:%S')
strptime('March 01 2020 11:13:22', format='%B %d %Y %H:%M:%S')
mdy_hms('March 01 2020 11:13:22')
mdy_hms('March 01 2020 11:13:22', tz='Asia/Seoul')
## [[1]] ## [1] "LC_COLLATE=English_United States.1252" ## [2] "LC_CTYPE=English_United States.1252" ## [3] "LC_MONETARY=English_United States.1252" ## [4] "LC_NUMERIC=C" ## [5] "LC_TIME=English_United States.1252" ## ## [1] "2020-03-01 11:13:22 KST" ## [1] "2020-03-01 11:13:22 KST" ## [1] "2020-03-01 11:13:22 UTC" ## [1] "2020-03-01 11:13:22 KST"
Sys.setlocale("LC_ALL", "French") %>% strsplit(";")
as.POSIXct('Mars 01 2020 11:13:22', format='%B %d %Y %H:%M:%S')
strptime('Mars 01 2020 11:13:22', format='%B %d %Y %H:%M:%S')
mdy_hms('Mars 01 2020 11:13:22')
mdy_hms('Mars 01 2020 11:13:22', tz='Asia/Seoul')
Sys.setlocale("LC_ALL", "Korean") %>% strsplit(";")
## [[1]] ## [1] "LC_COLLATE=French_France.1252" "LC_CTYPE=French_France.1252" ## [3] "LC_MONETARY=French_France.1252" "LC_NUMERIC=C" ## [5] "LC_TIME=French_France.1252" ## ## [1] "2020-03-01 11:13:22 KST" ## [1] "2020-03-01 11:13:22 KST" ## [1] "2020-01-20 11:13:22 UTC" ## [1] "2020-01-20 11:13:22 KST" ## [[1]] ## [1] "LC_COLLATE=Korean_Korea.949" "LC_CTYPE=Korean_Korea.949" ## [3] "LC_MONETARY=Korean_Korea.949" "LC_NUMERIC=C" ## [5] "LC_TIME=Korean_Korea.949"
위에서 봤듯이 날짜-시간 표기의 의미는 타임존에 따라 달라진다. 한국시간(tz='Asia/Seoul'
) March 01 2020 11:13:22
는 그린위치 천문대의 시간(tz='GMT'
) March 01 2020 11:13:22
보다 9시간 빠르다.
- R이 현재 사용하고 있는 타임존은
Sys.timezone()
으로 알 수 있다. - R이 사용하는 타임존을 바꾸려면
Sys.setenv(TZ='')
을 통해 바꿀 수 있다. Sys.setsen(TZ='')
에서TZ=
에 사용할 수 있는 타임존의 이름은OlsonNames()
로 확인할 수 있다. 세계 타임존은<
부록 2>
에서 확인할 수 있다.
이 밖의 날짜, 시간 연산, 날짜(시간)의 특정한 정보 참조, 날짜(시간) 갱신에 관한 내용은 R로 하는 빅데이터 분석: 데이터 전처리와 시각화에서 확인할 수 있습니다.
Related Posts
Comments on this post
2 Comments-
네. DST가 적용된 시간입니다. https://data.iana.org/time-zones/tz-link.html 의 자료를 쓴다고 하는데요. DST는 각 정부가 정하는 거라, 과거 정보는 정확하지만 미래에는 어떻게 될지 불확실하다고 합니다.
Seongdeok
혹시 as.POSIXct 함수에서 timezone을 지정하게 되면
Daylight Saving Time 을 조정한 시간을 주게 되는 상황인가요?