2023 年度「数学特論」 2024-01-31

§13.0 はじめに

時刻・時間に関する、以下の関数を使うには、time.h#include が必要である。

§13.1 時刻・時間に関係する関数(その1)

#include <stdio.h>
#include <time.h>

int main() {
  int i, j;
  time_t start, end;

  time(&start);         /* 現在時刻を取得 */

  for (i = 0; i < 10*1000; i++) {           /* 時間稼ぎ */
    for (j = 0; j < 1000*1000; j++) {
      ;
    }
  }

  end = time(NULL);     /* 現在時刻を取得 */

  printf("%f 秒かかりました.\n", difftime(end, start));
}

time_t は時刻を保持する型である。 関数 time() は現在時刻を取得する関数である。二通りの使い方がある。 一つは time(&start) のように、引数として time_t 型へのポインタをとるもの。 そこに現在時刻がはいる。 もう一つは、end = time(NULL) のように使うもの。 end に現在時刻がはいる。

この数値は、世界協定時 (UTC) の1970 年 01 月 01 日 00 時 00 分 00 秒からの経過秒数であることが多いようだ。 「計算数学a」「計算数学b」ではこの数値を乱数の種として使ったのだった。

関数 difftime(time_t time2, time_t time1) は、 time_1 から time_2 までの時間を秒を単位として返す。 返り値の型は double である。

上のプログラムは、時間稼ぎのため空(から)ループを回し、 かかった時間をはかっている。

§13.2 時刻・時間に関係する関数(その2)

#include <stdio.h>
#include <time.h>

int main() {
  time_t now;

  time(&now);           /* 現在時刻を取得 */

  printf("%s\n", ctime(&now));
}

関数 ctime(time_t *tp)tp が示す時刻を、 ローカルタイム(=地方時)に変換し、アメリカ合衆国において標準的な方法で表した文字列にして返す。 たとえば Wed Jan 31 10:40:26 2024\n\0 のようになる。

§13.3 時刻・時間に関係する関数(その3)

time.h で定義されている構造体 struct tm には次のメンバがある。

int tm_sec;秒、範囲は 0 から 61 まで。正のうるう秒にも対応
int tm_min;分、範囲は 0 から 59 まで
int tm_hour;時、範囲は 0 から 23 まで
int tm_mday;日、範囲は 1 から 31 まで
int tm_mon;月、範囲は 0 から 11 まで。一月が 0 であることに注意
int tm_year;年、1900 年からの年であることに注意
int tm_wday;曜日、日曜日が 0, 土曜日が 6
int tm_yday;年内の通算日、1 月 1 日が 0
int tm_isdst;夏時間のフラグ(詳細略)
#include <stdio.h>
#include <time.h>

void printdate(struct tm *tp);

int main() {
  time_t now;
  struct tm nowp;

  time(&now);           /* 現在時刻を取得 */

  nowp = *localtime(&now);  /* struct tm 型に変換 */

  printdate(&nowp);         /* 年月日を出力 */

  nowp.tm_mday++;           /* mday を 1 だけ増す。きょうなら 32 日になる */

  printdate(&nowp);         /* ありえない年月日を出力 */

  mktime(&nowp);            /* それを修正する */
  printdate(&nowp);         /* 今度は正しくあすの年月日を出力 */
}


/* *tp の年月日を出力 */ 
void printdate(struct tm *tp) {
  printf("%d-%02d-%02d\n", 1900 + tp->tm_year, 1 + tp->tm_mon, tp->tm_mday);
}

関数 localtime(time_t *tp)*tpstruct tm に変換する。 ただしその時刻はローカルタイム(=地方時)である。 変換されたものを nowp に代入している。 自作関数 void printdate(struct tm *tp)*tp の中の年、月、日を出力する。

mday を 1 だけ増す」の行。 きょうこれを実行すると 2024-01-32 と、ありえない年月日になる。 関数 mktime(struct tm *tp) はこれを正しい年月日に変換してくれる。 返り値は time_t 型だが、それはここでは用いていない。 次に printdate() で出力すると、今度は正しくあすの年月日を出力する。

§13.4 時刻・時間に関係する関数(その4)

関数 strftime() を使うと、日付時刻をさまざまな形で文字列化できる。 第一引数はどの文字列に書き込むか、 第二引数は文字数の上限、 第三引数は何を書き込むか、 第四引数は struct tm 型へのポインタ、である。 「何を書き込むか」は、printf() のときと同様、 普通の文字はそのまま、% で始まる文字は規則に従って変換されて、となる。 以下のプログラムに、すべての例をあげておいた。 (週番号には、 「1 月 1 日を含む週を第 1 週とするもの」と、 「1 月 4 日を含む週を第 1 週とするもの」とがあるので注意。)

#include <stdio.h>
#include <time.h>

int main() {
  char str[64+1];
  time_t now;
  struct tm nowp;

  time(&now);           /* 現在時刻を取得 */
  nowp = *localtime(&now);  /* struct tm 型に変換 */

  strftime(str, 64, "%a: 曜日の略称", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%A: 曜日", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%b: 月の略称", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%B: 月", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%c: 地方時", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%d: 日", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%H: 時、二十\四時制", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%I: 時、十\二時制", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%j: 年内通算日", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%m: 月", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%M: 分", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%p: 午前/午後", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%S: 秒", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%U: 週番号(日曜日を週の始まりとして、かつ、0 週目から始まる)", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%w: 曜日(日曜日が 0)", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%W: 週番号(月曜日を週の始まりとして、かつ、0 週目から始まる)", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%x: 日付", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%X: 時刻", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%y: 年下二桁", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%Y: 年", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%Z: タイムゾーン", &nowp);
  printf("%s\n", str);
  strftime(str, 64, "%%: %% そのもの", &nowp);
  printf("%s\n", str);
}

§13.5 課題6

現在の日付時刻について少なくとも 6 個以上の情報を出力するプログラムを書け。

レポートの本文冒頭に、氏名を、なるべく大学に届けるある通りの文字で書け。 次に、プログラムソースファイルを、添付ファイルではなく、本文に貼りつけよ。

件名は「??? kadai6」(←全て半角文字、小文字、 ??? は自分の履修者番号、その後ろに半角スペース一つ、 kadai6 の間にはスペースを入れない)とせよ。


岩瀬順一