C言語の基礎 - 日付・時刻

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動

現在の日付や時刻を取得する

C言語で、現在の日付や時刻を取得するには、以下の2ステップの処理が必要になる。

  1. time関数を使用して、現在の暦時刻(Calendar Time)を取得する。
  2. localtime関数またはgmtime関数を使用して、取得した暦時刻を変換する。


 #include <time.h>
 
 time_t time(time_t *timer);


time関数
time関数は、現在の暦時刻を処理系の最良の近似で返す関数である。
time関数は、引数timerがNULLではない場合、timerが指すオブジェクトにも戻り値を格納する。
time関数の呼び出しに失敗した場合は、(time_t) - 1を返す。

time関数の返す暦時刻は、time_t型の値である。
time_t型は時刻を表すことができる算術型の型であるが、そのままでは読めないので、以下に示すgmtime関数またはlocaltime関数を使用して変換する。

localtime関数とgmtime関数
localtime関数は、timerが指す暦時刻を地方時(local time)に変換し、tm構造体に格納して、そのポインタを返す関数である。
gmtime関数は、timerが指す暦時刻を協定世界時(UTC)に変換し、tm構造体に格納して、そのポインタを返す関数である。

localtime関数とgmtime関数は、暦時刻の変換に失敗した場合は、NULLを返す。

 #include <time.h>
 
 struct tm *localtime(const time_t *timer);
 
 struct tm *gmtime(const time_t *timer);


tm構造体
localtime関数やgmtime関数が返すtm構造体は、以下のような構造になっている。

データ型 メンバ 説明
int tm_sec 秒 (0 ~ 60)
int tm_min 分 (0 ~ 59)
int tm_hour 時 (0 ~ 23)
int tm_mday 日 (1 ~ 31)
int tm_mon 1月からの月数 (0 ~ 11)
int tm_year 1900年からの年数
int tm_wday 日曜日からの日数 (0 ~ 6)
int tm_yday 1月1日からの日数 (0 ~ 365)
int tm_isdst 夏時間フラグ
夏時間を採用している場合 : 正
夏時間を採用していない場合 : 0
この情報が得られない場合 : 負


以下の例では、time関数を使用して日付・時刻を取得し、localtime関数およびgmtime関数をそれぞれ使用して表示している。

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
 int main(void)
 {
    time_t timer;
    struct tm *local;
    struct tm *utc;
 
    /* 現在時刻を取得 */
    timer = time(NULL);
 
    local = localtime(&timer); /* 地方時に変換 */
 
    /* 地方時 変換後表示 */
    printf("地方時: ");
    printf("%4d/", local->tm_year + 1900);
    printf("%2d/", local->tm_mon + 1);
    printf("%2d ", local->tm_mday);
    printf("%2d:", local->tm_hour);
    printf("%2d:", local->tm_min);
    printf("%2d", local->tm_sec);
    printf(" %d\n", local->tm_isdst);
 
    utc = gmtime(&timer); /* 協定世界時(UTC)に変換 */
 
    /* 協定世界時 変換後表示 */
    printf("協定世界時: ");
    printf("%4d/", utc->tm_year + 1900);
    printf("%2d/", utc->tm_mon + 1);
    printf("%2d ", utc->tm_mday);
    printf("%2d:", utc->tm_hour);
    printf("%2d:", utc->tm_min);
    printf("%2d", utc->tm_sec);
    printf(" %d\n", utc->tm_isdst);
 
    return EXIT_SUCCESS;
 }


実行例
上記の実行結果は以下のようになる。

地方時: 2008/12/29 19: 4:11 0
協定世界時: 2008/12/29 10: 4:11 0



2つの時刻の差を求める

C言語で、2つの時刻の差を求めるには、以下の2種類の方法がある。

  • difftime関数を使用する方法。
  • clock 関数でプロセッサ時間を 2 回取得して差分を求める方法。


difftime 関数を使用して、2つの時刻の差を求める方法
difftime関数は、2つの暦時刻の差(time1 - time0)を求め、その差を秒単位で返す関数である。
なお、一般的に、time1とtime2はtime関数を使用して取得する。

 #include <time.h>
 
 double difftime(time_t time1, time_t time0);


具体的には、以下のように記述する。

 double diff;
 clock_t time1, time0;
 
 /* 暦時刻を取得 */
 time0 = time(NULL);
 
 /* 何らかの処理 */
 
 /* 処理後の暦時刻を取得 */
 time1 = time(NULL);
 
 /* 差分を求める */
 diff = difftime(time1, time0);


clock関数を使用して、2つの時刻の差を求める方法
clock関数は、そのプログラムの実行にだけ関連した処理系定義の時点から、そのプログラムで使用したプロセッサ時間を処理系の最良の近似で返す関数である。
clock関数の呼び出しに失敗した場合は、(clock_t) - 1を返す。
2つの時刻の差を求めるには、clock関数を2回呼び出し、差分を求める。

 #include <time.h>
 
 clock_t clock(void);


具体的には以下のように記述する。

 double diff;
 clock_t start, stop;
 
 /* プロセッサ時間を取得 */
 start = clock();
 
 /* 何らかの処理 */
 
 /* 処理後のプロセッサ時間を取得 */
 stop = clock();
 
 /* 差分を求める */
 diff = (double)(stop - start) / CLOCKS_PER_SEC;


以下の例では、difftime関数およびclock関数を使用して、2つの時刻の差を求めている。

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
 void gain_time(void);
 
 int main(void)
 {
    clock_t start, stop;
    double diff;
 
    /* -------- difftime を使う -------- */
    /* 暦時刻を取得 */
    start = time(NULL);
    /* 時間稼ぎ */
    gain_time();
    /* 時間稼ぎ後の暦時刻を取得 */
    stop = time(NULL);
    /* 差分を求める */
    diff = difftime(stop, start);
    /* 差分を表示 */
    printf("difftime 関数 で計測: %.3f[sec]\n", diff);
 
    /* -------- clock を使う -------- */
    /* プロセス時間を取得 */
    start = clock();
    /* 時間稼ぎ */
    gain_time();
    /* 時間稼ぎ後のプロセス時間を取得 */
    stop = clock();
    /* 差分を求める */
    diff = (double)(stop - start) / CLOCKS_PER_SEC;
    /* 差分を表示 */
    printf("clock 関数 で計測: %.3f[sec]\n", diff);
 
    return EXIT_SUCCESS;
 }
 
 /* 時間稼ぎ */
 void gain_time(void)
 {
    for (int i = 0; i <= 100000; i++ )
    {
       for (int j = 0; j <= 10000; j++ )
       {
          if ( i % 10000 == 0 )
          {
             putchar('-');
          }
       }
    }
    printf("\n");
 }



プログラムの実行開始時点からの経過時間を取得する

C言語で、プログラムの実行開始時点からの経過時間を取得するには、time.hのclock関数を使用する。

clock関数は、プログラムの実行にだけ関連した処理系定義の時点から、そのプログラムで使用したプロセッサ時間を処理系の最良の近似で返す関数である。
clock関数を呼び出すと、プログラムの実行開始時点からの経過時間が取得できる。

clock関数の呼び出しに失敗した場合は、(clock_t) - 1を返す。
経過時間を秒単位で取得する場合は、戻り値をCLOCKS_PRE_SECマクロの値で除算する。

 #include <time.h>
 
 clock_t clock(void);


以下の例では、clock関数を使用して、プログラム開始時点からの経過時間を取得している。

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
 int main(void)
 {
    clock_t passage;
    double sec;
 
    /* 時間稼ぎ */
    for (int i = 0; i <= 100000; i++)
    {
       for (int j = 0; j <= 10000; j++)
       {
          if ( i % 10000 == 0 )
          {
             putchar('-');
          }
       }
    }
 
    /* 経過時間を取得 */
    if ( (passage = clock()) == (clock_t)(-1) )
    {
       fprintf(stderr,"経過時間の取得に失敗しました.\n");
 
       return EXIT_FAILURE;
    }
    sec = (double)passage / CLOCKS_PER_SEC;
 
    /* 経過時間を秒単位で表示 */
    printf("\nプログラム開始から%.2f秒経過しました.\n", sec);
 
    return EXIT_SUCCESS;
 }



日付を指定して曜日を取得する

曜日を取得するアルゴリズムは、ツェラーの公式(Zeller's congruence)が有名であるが、
ここでは、time.hのmktime関数を使用する方法を記載する。

mktime関数は、引数timeptrが指すtm構造体の内容を、暦時刻(Calendar Time)の値に変換する関数である。
変換の際には、tm_wday要素(日曜日からの日数)とtm_yday要素(1月1日からの日数)の元の値は無視されて、自動的に適切な値が格納される。
この"適切な値"により、この性質を利用すると日付から曜日を求めることができる。

 #include <time.h>
 
 time_t mktime(struct tm *timeptr);


以下の例では、mktime関数を使用して、日付から曜日を取得している。

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
 int GetDayOfWeek(int year, int month, int day);
 void DisplayWeek(int wday);
 
 int main(void)
 {
    int year = 2020;
    int month = 5;
    int day = 1;
    int week;
 
    /* 日付の表示 */
    printf("%d/%d/%d: ", year, month, day);
 
    /* 曜日を求める */
    week = GetDayOfWeek(year, month, day);
 
    /* 曜日の表示 */
    DisplayWeek(week);
 
    return EXIT_SUCCESS;
 }
 
 /* 曜日を求める                                      */
 /* @param[in] year 年                                */
 /* @param[in] month 月                               */
 /* @param[in] day 日                                 */
 /* @return 曜日(0を日曜日とする. エラー時は-1を返す) */
 int GetDayOfWeek(int year, int month, int day)
 {
    struct tm time_in, *local;
    time_t t;
 
    /* 年月日を入力 */
    time_in.tm_year = year - 1900; /* 年 */
    time_in.tm_mon  = month - 1; /* 月 */
    time_in.tm_mday = day; /* 日 */
 
    /* 時分秒曜日を適当に入力 */
    time_in.tm_hour = 1; /* 時 (適当に入力)  */
    time_in.tm_min  = 0; /* 分 (適当に入力)  */
    time_in.tm_sec  = 0; /* 秒 (適当に入力)  */
    time_in.tm_wday = 0; /* 曜日 (適当に入力) */
    time_in.tm_yday = 0; /* 1月1日からの日数 (適当に入力) */
 
    /* mktime 関数で変換 */
    if ( (t = mktime(&time_in) ) == (time_t)(-1) )
    {
       return -1;
    }
 
    /* 地方時に変換 */
    local = localtime(&t);
 
    return local->tm_wday;
 }
 
 /* 曜日を表示する                        */
 /* @param[in] wday 曜日(0を日曜日とする) */
 void DisplayWeek(int wday)
 {
    char weeks[][16] = {
        "日曜日",
        "月曜日",
        "火曜日",
        "水曜日",
        "木曜日",
        "金曜日",
        "土曜日"
    };
 
    printf("%s\n", weeks[wday]);
 }



暦時刻を地方時に変換する

C言語で、暦時刻(Calendar Time)を地方時(Local Time)に変換するには、time.hのlocaltime関数を使用する。

localtime関数は、timerが指す暦時刻を地方時に変換して、tm構造体に格納して、そのポインタを返す関数である。

localtime関数は、暦時刻の変換に失敗した場合はNULLを返す。

 #include <time.h>
 
 struct tm *localtime(const time_t *timer);


tm構造体
再度、localtime関数やgmtime関数が返すtm構造体を下表に示す。

データ型 メンバ 説明
int tm_sec 秒 (0 ~ 60)
int tm_min 分 (0 ~ 59)
int tm_hour 時 (0 ~ 23)
int tm_mday 日 (1 ~ 31)
int tm_mon 1月からの月数 (0 ~ 11)
int tm_year 1900年からの年数
int tm_wday 日曜日からの日数 (0 ~ 6)
int tm_yday 1月1日からの日数 (0 ~ 365)
int tm_isdst 夏時間フラグ
夏時間を採用している場合 : 正
夏時間を採用していない場合 : 0
この情報が得られない場合 : 負


以下の例では、localtime関数を使用して、暦時刻を地方時に変換している。

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
 int main(void)
 {
    time_t timer;
    struct tm *local;
 
    /* 現在時刻を取得 */
    timer = time(NULL);
 
    local = localtime(&timer); /* 地方時に変換 */
 
    /* 地方時 変換後表示 */
    printf("地方時: ");
    printf("%4d/", local->tm_year + 1900);
    printf("%2d/", local->tm_mon + 1);
    printf("%2d ", local->tm_mday);
    printf("%2d:", local->tm_hour);
    printf("%2d:", local->tm_min);
    printf("%2d", local->tm_sec);
    printf(" %d\n", local->tm_isdst);
 
    return EXIT_SUCCESS;
 }


実行例
上記の実行結果は以下のようになる。(環境によって差異があるので注意する)

地方時: 2008/12/29 19: 4:11 0



暦時刻を文字列形式の地方時に変換する

C言語で、暦時刻(Calendar Time)を文字列形式の地方時(Local Time)に変換するには、time.hのctime関数を使用する。

ctime関数は、timerが指す暦時刻を文字列形式の地方時に変換して返す関数である。

 #include <time.h>
 
 char *ctime(const time_t *timer);


以下の例では、ctime関数を使用して、現在の時刻を文字列形式の地方時として表示している。

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
 int main(void)
 {
    time_t timer;
    char *p = nullptr;
 
    /* 現在時刻を取得 */
    timer = time(NULL);
 
    /* 文字列(地方時)への変換 */
    p = ctime(&timer);
    printf("%s\n", p);
 
    return EXIT_SUCCESS;
 }


実行例
上記の実行結果は以下のようになる。(結果は実行環境により異なる)

Mon Dec 29 19:18:14 2008



暦時刻を協定世界時(UTC)に変換する

C言語で、暦時刻(Calendar Time)を協定世界時(UTC)に変換するには、time.hのgmtime関数を使用する。

gmtime関数は、timerが指す暦時刻を協定世界時(UTC)に変換して、tm構造体に格納して、そのポインタを返す関数である。
gmtime関数は、暦時刻の変換に失敗した場合はNULLを返す。

 #include <time.h>
 
 struct tm *gmtime(const time_t *timer);


tm構造体
再度、gmtime関数が返すtm構造体を下表に示す。

データ型 メンバ 説明
int tm_sec 秒 (0 ~ 60)
int tm_min 分 (0 ~ 59)
int tm_hour 時 (0 ~ 23)
int tm_mday 日 (1 ~ 31)
int tm_mon 1月からの月数 (0 ~ 11)
int tm_year 1900年からの年数
int tm_wday 日曜日からの日数 (0 ~ 6)
int tm_yday 1月1日からの日数 (0 ~ 365)
int tm_isdst 夏時間フラグ
夏時間を採用している場合 : 正
夏時間を採用していない場合 : 0
この情報が得られない場合 : 負


以下の例では、gmtime関数を使用して、暦時刻を協定世界時(UTC)に変換している。

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
 int main(void)
 {
    time_t timer;
    struct tm *utc;
 
    /* 現在時刻を取得 */
    timer = time(NULL);
 
    utc = gmtime(&timer); /* 協定世界時(UTC)に変換 */
 
    /* 協定世界時 変換後表示 */
    printf("協定世界時: ");
    printf("%4d/", utc->tm_year + 1900);
    printf("%2d/", utc->tm_mon + 1);
    printf("%2d ", utc->tm_mday);
    printf("%2d:", utc->tm_hour);
    printf("%2d:", utc->tm_min);
    printf("%2d", utc->tm_sec);
    printf(" %d\n", utc->tm_isdst);
 
    return EXIT_SUCCESS;
 }


実行例
上記の実行結果は以下のようになる。(結果は実行環境により異なる)

協定世界時: 2008/12/29 10: 4:11 0