제 35강) 라이브러리 함수3 - 날짜 및 시간 |
오늘은 "강의에서 다루지 않았던"의 다섯번째 시간입니다.
이번 시간에는 라이브러리 함수3인 날짜 및 시간 라이브러리에 대해서 다뤄보려고 합니다.
C언어에서 제공하는 "날짜 및 시간" 라이브러리는 time.h를 포함하면 사용이 가능합니다.
자료형 |
time.h 에는 다음과 같이 4개의 자료형을 선언하고 있습니다.
이름 | 자료형 원형 | 기능 |
clock_t | Tick 수를 샐 수 있는 시계 전용 자료형(시스템 시간을 잴 때 사용) | |
size_t | unsigned int | 부호 없는 정수 자료형으로 바이트 단위의 크기를 나타낼 때 사용 |
time_t | 시간을 나타내기 위한 자료형 | |
struct tm | 시간을 받아서 저장하는 구조체 |
여기서struct tm을 좀더 자세히 봅시다.
멤버 | 자료형 | 뜻 | 범위 |
tm_sec | int | 초(seconds after the minute) | 0 ~ 60 |
tm_min | int | 분(minutes after the hour) | 0 ~ 59 |
tm_hour | int | 시간(hours since midnight) | 0 ~ 23 |
tm_mday | int | 날짜(day of the month) | 1 ~ 31 |
tm_mon | int | 달(months since January) | 0 ~ 11 |
tm_year | int | 년도(years since 1900) | |
tm_wday | int | 요일(days since Sunday) | 0 ~ 6 |
tm_yday | int | 해당 년도의 1월부터 지금까지의 일수(days since January 1) | 0 ~ 365 |
tm_isdst | int | 서머타임 여부(Daylight Saving Time flag) |
(표 내용 출처: http://www.cplusplus.com/reference/ctime/tm/)
이렇습니다.
이때 tm_year는 1900년도 이후로 측정되기 때문에 2018년은 118년으로 매깁니다. 그렇기 때문에 1900을 항상 더해주어서 출력해야합니다.
tm_mon는 1월은 0, 12월은 11로 나타내기 때문에1을 더해주어서 표현해야 합니다.
함수 |
time.h 에서 자주쓰이는 함수들에 대해서 알아봅시다.
먼저 time 함수와 localtime 함수입니다.
#include <time.h>
time_t time (time_t* timer);
-> 현재 시간을 time_t 자료형태로 반환 또는 timer에 저장한다.
struct tm* localtime (const time_t* timer);
-> timer의 내용을 struct tm의 형태로 변환하여 저장한다.
여기서 time 함수는 2가지 형태로 자료를 저장할 수 있는데요.
time_t now_t;
now_t = time(0);
time(&now_t);
이렇게 사용합니다만 4번줄 방식이 3번줄 방식보다 더 많이 사용됩니다.
예제를 바로 봅시다.
#include <stdio.h>
#include <time.h>
int main()
{
struct tm* now;
time_t now_t;
// now_t = time(0) 과 같은 뜻입니다.
time(&now_t); // 현재 시간을 now_t에 time_t 형태로 저장
now = localtime(&now_t); // time_t 형태의 자료를 struct tm 형태로
printf("[현재의 날짜와 시간]\n");
printf("%d년 ", now->tm_year + 1900);
printf("%d월 ", now->tm_mon + 1);
printf("%d일 ", now->tm_mday);
printf("%d시 ", now->tm_hour);
printf("%d분 ", now->tm_min);
printf("%d초\n", now->tm_sec);
return 0;
}
현재 시간을 받아서 localtime 함수를 이용하여 struct tm형식의 자료형에 저장하여 출력합니다.
다음은 mktime 함수와 acstime 함수, ctime 함수 입니다.
#include <time.h>
time_t mktime (struct tm* timeptr);
-> struct tm 형태의 시간을 time_t 형태로 반환한다. (localtime의 반대)
char* asctime (const struct tm* timeptr);
-> struct tm 형태의 시간을 문자열로 나타내어줍니다.
-> 이때 출력되는 포멧은 "Www Mmm dd hh:mm:ss yyyy" 입니다.
char* ctime (const time_t* timer);
-> time_t 형태의 시간을 문자열로 나타태어줍니다.
-> 이때 출력되는 포멧은 "Www Mmm dd hh:mm:ss yyyy" 입니다.
여기서 mktime은 localtime과는 반대의 성격을 띕니다.
하지만 이때 기존의 timeptr은 입력되어 있는 값을 기준으로 재계산이 들어가게 됩니다.
timeptr의 tm_year, tm_mon, tm_mday만 입력되어 있었다고 한다면 mktime이 실행되면 나머지 인자들이 저절로 계산되어 값이 들어가게 됩니다.
이렇게 계산되어진 timeptr을 가지고 time_t로 변환을 하게 되는 것이죠.
asctime과 ctime의 기능은 같으나 asctime은 struct tm형을, ctime은 time_t형을 인자로 받습니다.
#include <stdio.h>
#include <time.h>
int main()
{
struct tm* now;
time_t now_t;
time(&now_t); // now_t = time(0) 과 같은 뜻입니다.
now = localtime(&now_t);
printf("[현재의 날짜와 시간]\n");
printf("asctime: %s \n", asctime(now));
printf("ctime: %s \n", ctime(&now_t));
return 0;
}
위의 예제는 asctime과 ctime 예제입니다.
mktime은 예제가 조금은 복잡합니다.
/* 출처: http://www.cplusplus.com/reference/ctime/mktime/ */
/* mktime example: weekday calculator */
#include <stdio.h> /* printf, scanf */
#include <time.h> /* time_t, struct tm, time, mktime */
int main ()
{
time_t rawtime;
struct tm * timeinfo;
int year, month ,day;
const char * weekday[] = { "Sunday", "Monday",
"Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
/* prompt user for date */
printf ("Enter year: "); fflush(stdout); scanf ("%d",&year);
printf ("Enter month: "); fflush(stdout); scanf ("%d",&month);
printf ("Enter day: "); fflush(stdout); scanf ("%d",&day);
/* get current timeinfo and modify it to the user's choice */
time ( &rawtime );
timeinfo = localtime ( &rawtime );
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
/* mktime 계산하기 전 */
printf("Before: That day is a %s.\n", weekday[timeinfo->tm_wday]);
/* call mktime: timeinfo->tm_wday will be set */
mktime(timeinfo);
/* mktime 계산한 후 */
printf("After: That day is a %s.\n", weekday[timeinfo->tm_wday]);
return 0;
}
직접 날짜를 입력받습니다. (16 ~ 18줄)
그렇게 입력받은 날짜를 timeinfo에 저장합니다.(21 ~ 25)
입력받은 3가지 인자를 토대로 mktime을 실행하게 되면 나머지 인자들도 자동 계산되어집니다.
여기서 기존의 날짜에 새롭게 입혀진 tm_year, tm_mon, tm_mday를 기반으로 다시 계산되어서 tm_wday가 새롭게 해당날짜에 맞게 바뀌게 됩니다.
그렇기 때문에 28번줄의 tm_wday(오늘 기준)와 34번줄의 tm_wday(입력된 값 기준)는 다르게 됩니다.
그렇죠?
이제 우리가 직접 출력 형식을 지정해줄 수 있는 함수인 strftime 함수를 봅시다.
#include <time.h>
size_t strftime (char* ptr, size_t maxsize, const char* format, const struct tm* timeptr);
-> ptr에 maxsize만큼 format 형식으로 timeptr을 문자열로 저장합니다.
여기서 format에서 사용할 수 있는 형식 지정자들을 확인하여봅시다.
형식 | 설명 | 예 |
%a | 축약 형식의 요일 (Abbreviated weekday name) |
Sun |
%A | 요일 (Full weekday name) |
Sunday |
%b | 축약 형식의 월 (Abbreviated month name) |
Jan |
%B | 월 (Full month name) |
January |
%c | 날짜와 시간 (Date and time representation) |
Sun Jan 10 11:11:11 2018 |
%C | 세기로 나타냄 (Year divided by 100 and truncated to integer (00-99) |
21 |
%d | 일 (Day of the month, zero-padded (01-31)) |
22 |
%D | MM/DD/YY로 나타냄, %m/%d/%y와 같음 (Short MM/DD/YY date, equivalent to %m/%d/%y) |
08/23/01 |
%e | %d와 같으나 일 한자리 일수 앞에 공백이 붙음( 1-30) (Day of the month, space-padded ( 1-31)) |
23 |
%F | YYYY-MM-DD로 나타냄, %Y-%m-%d와 같음 (Short YYYY-MM-DD date, equivalent to %Y-%m-%d) |
2018-01-01 |
%g | 주 날짜의 두자리 연도 (Week-based year, last two digits (00-99)) |
18 |
%G | 주 날짜의 네자리 연도 (Week-based year) |
|
%h | %b와 같음 (Abbreviated month name * (same as %b)) |
|
%H | 시(24시간) (Hour in 24h format (00-23)) |
13 |
%I | 시(12시간) (Hour in 12h format (01-12)) |
8 |
%j | 이번 년도의 일 (Day of the year (001-366)) |
256 |
%m | 월 (Month as a decimal number (01-12)) |
12 |
%M | 분 (Minute (00-59)) |
52 |
%n | 개행 (New-line character ('\n')) |
|
%p | AM 또는 PM (AM or PM designation) |
PM |
%r | 12시간 기반의 시간 (12-hour clock time) |
02:55:02 PM |
%R | 24시간 기반의 HH:MM 시간, %H:%M과 같음 (24-hour HH:MM time, equivalent to %H:%M) |
22:00 |
%S | 초 (Second (00-61)) |
12 |
%t | 탭 (Horizontal-tab character ('\t')) |
|
%T | 24시간 기반의 HH:MM:SS 시간, %H:%M:%S와 같음 (time format (HH:MM:SS), equivalent to %H:%M:%S) |
13:55:02 |
%u | 요일(월요일 : 1) (weekday as number with Monday as 1 (1-7)) |
5 |
%U | 연도의 해당 주 번호(첫번째 요일은 일요일) (Week number with the first Sunday as the first day of week one (00-53)) |
25 |
%V | 연도의 해당 주 번호 (week number (01-53)) |
52 |
%w | 요일(일요일 : 0) (Weekday as a decimal number with Sunday as 0 (0-6)) |
4 |
%W | 연도의 해당 주 번호(첫번째 요일은 월요일) (Week number with the first Monday as the first day of week one (00-53)) |
17 |
%x | 로케일 기반의 날짜 (Date representation) |
08/23/01 |
%X | 로케일 기반의 시간 (Time representation) |
14:55:02 |
%y | 두자리 연도 (Year, last two digits (00-99)) |
18 |
%Y | 연도 (Year) |
2018 |
%z | UTC 오프셋, +는 GMT 동쪽, -GMT 서쪽, 1분 = 1, 1시간 = 100) (offset from UTC in timezone (1 minute=1, 1 hour=100) If timezone cannot be determined, no characters) |
+100 |
%Z | 로케일 기반 시간대 이름 (Timezone name or abbreviation, If timezone cannot be determined, no characters) |
CDT |
%% | %문자 |
(표 출처: http://www.cplusplus.com/reference/ctime/strftime/)
문자가 정말정말 많죠?
필요할때마다 보면서 사용하면 되지만 대다수의 프로그래밍 언어의 시간관련 형식 지정자가 같으니 몇 번 쓰다보면 몇몇가지는 자연스레 외워집니다.
#include <stdio.h>
#include <time.h>
#define MAX 100
int main ()
{
struct tm* now;
time_t now_t;
char str1[MAX] = { 0, };
char str2[MAX] = { 0, };
time(&now_t);
now = localtime(&now_t);
strftime(str1, MAX, "오늘은 %F %A 입니다.", now);
strftime(str2, MAX, "지금 시간은 %p %I시 %M분 %S초 입니다.", now);
printf("%s\n", str1);
printf("%s\n", str2);
return 0;
}
가장 간단한 몇가지 지정자를 이용한 예제입니다.
마지막으로 시간을 계산할 때 쓰이는 함수인 difftime 함수와 clock 함수입니다.
#include <time.h>
double difftime (time_t end, time_t beginning);
-> beginning시간 부터 end시간까지의 차를 구하여 걸린 시간을 구함
clock_t clock(void);
-> 프로그램이 시작한 이후부터 clock()함수를 호출할 때 까지의 시간을 구함
간단하게 예제를 봅시다.
#include <stdio.h>
#include <time.h>
int main ()
{
int total = 0;
time_t start, end;
double timer1;
clock_t timer2;
time(&start);
for (int i = 1; i <= 100000000; i++)
total += i;
time(&end);
timer1 = difftime(end, start);
timer2 = clock();
printf("for문이 걸린 시간(difftime): %f초\n", timer1);
printf("프로그램 수행 시간(clock): %f초\n", timer2 / CLOCKS_PER_SEC);
return 0;
}
clock 함수의 경우에는 CLOCKS_PER_SEC으로 나누어줘야 초(Seconds)로 바뀝니다.
다음 시간에는 |
이로서 기본적인 라이브러리 함수는 끝이 났습니다.
다음시간부터는 아주아주 기본적인 "알고리즘"을 보도록 하겠습니다.
'Study > C언어' 카테고리의 다른 글
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 37 [정렬 알고리즘(선택 정렬)] (0) | 2020.01.29 |
---|---|
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 38 [정렬 알고리즘(삽입 정렬)] (0) | 2020.01.29 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 34 [라이브러리 함수2(문자, 수학)] (0) | 2019.02.16 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 33 [라이브러리 함수1(변환, 랜덤)] (0) | 2019.02.16 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 32 [다루지 않았던2(Call by ~)] (0) | 2018.10.28 |