C言語における日時処理は「time」「unistd」「sys/time」のランタイムをincludeすることで実現できます。
ただし、型の宣言に厳しい言語だけに、他の言語のように、フォーマット切り替えを行うことに対して制約が大きいです。
しかし、言語の制約に乗っかるのは世の常なので、きちんと言語仕様を守って行いましょう。
特殊だなと思ったのは、「time_t」「tm」などのような時間用の型が存在して、それを引っ張っていくので、数値で計算したりするのが少しやりづらい・・・と感じました。
時間操作の要件
- 1900年からの秒数(UnixTime)
- sleep処理
- 1番からYmdHisの取得(曜日含む)
- YmdHisから1番の取得
- ミリ秒の取得
- 本プログラムの経過秒数
ソース
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
time_t getUnixTime(){
time_t t = time(NULL);
return t;
}
void viewDateStringFormat(time_t t){
struct tm *local = localtime(&t);
int y = local->tm_year + 1900;
int m = local->tm_mon + 1;
int d = local->tm_mday;
int h = local->tm_hour;
int i = local->tm_min;
int s = local->tm_sec;
int w = local->tm_wday;
char *week[] = {"日","月","火","水","木","金","土"};
printf("%04d%02d/%02d %02d:%02d:%02d (%s)", y,m,d,h,i,s,week[w]);
}
time_t getYmd2Utime(int y , int m , int d , int h , int i , int s){
struct tm stm1;
stm1.tm_year = y - 1900;
stm1.tm_mon = m - 1;
stm1.tm_mday = d;
stm1.tm_hour = h;
stm1.tm_min = i;
stm1.tm_sec = s;
return mktime(&stm1);
}
time_t getMicroTime(time_t t){
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_usec;
}
void getTimezone(time_t t){
struct tm * now = localtime(&t);
char buf[16];
size_t result = strftime(buf, sizeof(buf), "%z",now);
printf("%s" , buf);
}
int main(int argc, char **argv){
// 1
// need : #include <time.h>
time_t start = getUnixTime();
printf("1 : start-time \t: ");
printf("%ld sec" , start);
printf("\n");
// 2
// need : #include <unistd.h>
printf("2 : sleep \t: ");
printf("start...");
sleep(3);
printf("finish");
printf("\n");
//3
printf("3 : Date-Format : ");
viewDateStringFormat(start);
printf("\n");
//4
printf("4 : ymd2sec \t: ");
int y1 = 2017;
int m1 = 5;
int d1 = 3;
int h1 = 12;
int i1 = 10;
int s1 = 3;
time_t tm4 = getYmd2Utime(y1,m1,d1,h1,i1,s1);
printf("%d/%d/%d %d:%d:%d -> %ld sec" , y1,m1,d1,h1,i1,s1 , tm4);
printf("\n");
//5
// need : #include <sys/time.h>
printf("5 : microsec \t: ");
printf("%ld" , getMicroTime(start));
printf("\n");
//6
printf("6 : GMT \t: ");
getTimezone(start);
printf("\n");
// 7
time_t end = getUnixTime();
printf("7 : end-time \t: ");
printf("%ld sec" , end);
printf("\n");
int s = start;
int e = end;
printf("--spend-time \t: %d sec" , (e - s));
printf("\n");
return 0;
}
実行
$ gcc -o timeFunction.cc timeFunction.c
$ time ./timeFunction.cc
1 : start-time : 1493776366 sec
2 : sleep : start...finish
3 : Date-Format : 201705/03 10:52:46 (水)
4 : ymd2sec : 2017/5/3 12:10:3 -> 1493777403 sec
5 : microsec : 676606
6 : GMT : +0900
7 : end-time : 1493776369 sec
--spend-time : 3 sec
real 0m3.015s
user 0m0.002s
sys 0m0.002s
解説
UnixTimeの取得
time_t t = time(NULL);
time.hをincludeして上記プログラムだけで取得できますが、型が「time_t」となっているところに注意しましょう。
PHPのように、数値で保持して便利に切り替えられる事は出来ないことがわかりました。
ちなみに、この型をprintするには「%ld」
time_tフォーマットを日時値として取得
struct tm *local = localtime(&t);
int y = local->tm_year + 1900;
int m = local->tm_mon + 1;
int d = local->tm_mday;
int h = local->tm_hour;
int i = local->tm_min;
int s = local->tm_sec;
int w = local->tm_wday;
これはtime_tフォーマットからの取得の為、microSecやGMTなどの情報が取れません。
timevalなどの型で全て処理したほうがいいのかな?
でも、無駄な情報を常に持っているのも無駄というメモリ管理にうるさいC言語ならではの仕様なので、おそらく適材適所だろうと思います。
ミリ秒
time_t getMicroTime(time_t t){
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_usec;
}
今回のミリ秒はstart値から取得するのではなく、その時のタイミングで新たに取得しています。
時間値という値を保持する場合、ミリ秒が必要な場合は、timevalで引っ張っていくほうが良さそうですが、この型の事はあまり調べていません。
必要だと感じたら記事にしたいと思います。
GMTの取得
void getTimezone(time_t t){
struct tm * now = localtime(&t);
char buf[16];
size_t result = strftime(buf, sizeof(buf), "%z",now);
printf("%s" , buf);
}
これも非常に特殊で、tm型でフォーマット宣言することにより取得できます。
サマータイム
ちなみに、今回は国内対応のみで考えていたので、サマータイムは考慮してません。
timeライブラリの中にはサマータイム値が得られるので、基本時間との差分も取れるようです。
グローバル・サービスなどの場合は必須でしょうね。
参考サイト
下記サイトには、C言語のtimeライブラリのリファレンスやサンプルコードが乗っています。
今回の記事で参考にさせてもらいました。ありがとうございます。
スリープ処理 | 碧色工房-blue studio-
C言語ケーススタディ 日付/時刻の操作 | C言語入門
C言語 struct tm構造体をtime_t型に変換 - time.h - [ mktime ] | 勇躍のゴミ箱
C言語で正確にミリ秒単位まで計測する方法 | 8ttyan’s blog
標準ライブラリで提供される時間・エラー処理に関する便利な機能 | @IT
日付の書式GMT | Walking Dog
0 件のコメント:
コメントを投稿