C言語で現在時刻を扱うときに最初に出会うのがtime関数によるUNIX時刻の取得です。
この記事では、UNIX時刻の基礎から、time関数で現在のUNIX時刻(秒)を取得し、それを人間が読める年月日・時刻に変換して表示する方法までを、C言語初心者向けに順序立てて解説します。
サンプルコードも用意していますので、自分の環境で動かしながら学んでみてください。
time関数とは?UNIX時刻と仕組みの基礎
UNIX時刻(epoch)とは何か
C言語で時刻を扱うとき、「UNIX時刻」という概念がよく登場します。
これは「ある基準となる日時からの経過時間を秒で表した値」です。
一般的なUNIX系OSや多くのプログラミング言語では、次の時刻を基準(エポック、epoch)としています。
- 1970年1月1日 00時00分00秒(UTC)
この基準からの経過秒数を整数で数えたものがUNIX時刻です。
例えば、ある時点のUNIX時刻が1700000000であれば、それは「1970年1月1日 00:00:00(UTC)」から1700000000秒経過していることを意味します。
UNIX時刻の特徴として、時計表示のような「2025/11/01 12:34:56」といった人間に読みやすい形式ではなく、単なる整数である点が挙げられます。
このおかげで、時間差の計算(2つの時刻の差分を秒単位で求めるなど)がとても扱いやすくなります。
time関数で取得できる値と型
C言語の標準ライブラリには、現在のUNIX時刻(秒)を取得するためのtimeという関数が用意されています。
ヘッダファイルtime.hで宣言されています。
関数のプロトタイプは次のようになっています。
time_t time(time_t *t);
ここでのtime_tは、時刻を表すための型です。
多くの環境ではlongやlong longなどの整数型として定義されていますが、環境によって実際の中身が異なる抽象的な型だと理解しておくことが大切です。
time関数の戻り値は、現在のUNIX時刻(秒)を表すtime_t型の値です。
例えば、戻り値を変数nowに受け取れば、その時点のUNIX時刻がnowに格納されます。
C言語初心者が知っておきたいヘッダファイル
C言語で時刻関連の関数を使う場合、まずtime.hをインクルードする必要があります。
初心者の方は、次の3つをセットで覚えておくと良いです。
#include <time.h>
time関数、struct tm、localtime、gmtimeなどの宣言が含まれます。#include <stdio.h>printfで画面に出力するために必要です。#include <stdlib.h>
場合によってexitを使うときなどに必要です。必須ではありませんが、エラー処理を丁寧に書く場合によく使われます。
時刻に関するプログラムを書くときは、まずtime.hをインクルードするという習慣をつけておくと良いでしょう。
time関数で現在のUNIX時刻(秒)を取得する
time関数の基本的な使い方と戻り値
time関数の最も基本的な使い方は、引数にNULLを渡す方法です。
この場合、timeは現在のUNIX時刻を戻り値として返すだけです。
time_t now = time(NULL);
また、time関数にはもう1つの使い方があります。
time_t型の変数のアドレスを引数に渡すことで、その変数にも同じ値を書き込むことができます。
time_t now;
time(&now); /* now に現在のUNIX時刻が書き込まれる */
この2つの書き方は、どちらもほぼ同じ意味です。
初心者のうちは、time(NULL)という書き方に慣れておくと読みやすいでしょう。
戻り値の型がtime_tであることに注意してください。
intやlongにそのまま代入すると、環境によっては桁あふれを起こす可能性があります。
必ずtime_t型の変数を使うことが基本です。
現在のUNIX時刻を取得するサンプルコード
ここでは、現在のUNIX時刻(秒)を取得して表示するだけの最小限のサンプルを示します。
C言語初心者でも理解しやすいように、1行ずつコメントを付けています。
#include <stdio.h> /* printf の宣言 */
#include <time.h> /* time, time_t の宣言 */
int main(void)
{
/* 現在のUNIX時刻(秒)を格納するための変数。型は time_t を使う */
time_t now;
/* time 関数を使って現在のUNIX時刻を取得する */
now = time(NULL); /* 引数に NULL を渡す場合、戻り値に現在時刻が返る */
/* 取得したUNIX時刻を整数として表示する
%ld ではなく %ld, %lld, %jd など環境で違う場合があるため、
一旦簡易的にキャストして出力しています。
本格的に書く場合は後述のように注意してください。 */
printf("現在のUNIX時刻は %ld 秒です\n", (long)now);
return 0;
}
出力例は次のようになります(実行した日時によって値は変わります)。
現在のUNIX時刻は 1732252800 秒です
表示された値はあくまで「1970年1月1日00:00:00(UTC)から何秒経ったか」を示しているだけで、人間がすぐに理解できる年月日・時刻ではありません。
後のセクションで、これを年月日・時刻に変換する方法を解説します。
time関数のエラー時の扱い
time関数は、通常の環境ではほとんどエラーになりませんが、理論上はエラーが起こる可能性があります。
- 成功した場合
現在のUNIX時刻(秒)を表すtime_tの値が返ります。 - 失敗した場合
(time_t)-1が返ります。
初心者のうちからエラーをちゃんとチェックする癖をつけておくと、バグの少ないプログラムが書けます。
次に、エラー処理を含めた例を示します。
#include <stdio.h>
#include <stdlib.h> /* exit, EXIT_FAILURE を使う場合に必要 */
#include <time.h>
int main(void)
{
time_t now;
/* time 関数で現在のUNIX時刻を取得する */
now = time(NULL);
/* エラーかどうかを (time_t)-1 との比較で判断する */
if (now == (time_t)-1) {
/* エラーの場合のメッセージを表示する */
fprintf(stderr, "time 関数の呼び出しに失敗しました\n");
/* 異常終了を示す終了コードでプログラムを終了する */
exit(EXIT_FAILURE);
}
printf("現在のUNIX時刻は %ld 秒です\n", (long)now);
return 0;
}
出力例(正常時):
現在のUNIX時刻は 1732252800 秒です
現代的なOSではほぼエラーになりませんが、教科書どおりにエラー処理を書いておくことは良い習慣です。
取得したUNIX時刻を人間が読める時刻に変換する
UNIX時刻から構造体tmへ変換する
UNIX時刻はただの秒数なので、そのままでは「何年何月何日何時何分何秒」か分かりません。
そこで、C言語の標準ライブラリでは、UNIX時刻を「カレンダー時刻」の形に分解する関数が用意されています。
代表的なものは次の2つです。
struct tm *localtime(const time_t *timer);
現在のローカルタイム(日本のPCなら通常は日本時間)に変換します。struct tm *gmtime(const time_t *timer);
UTC(協定世界時)に変換します。時差の影響を受けません。
ここではまず、日常的によく使われるlocaltimeを使って、UNIX時刻をstruct tmという構造体に変換する方法を見てみます。
struct tm *local_time = localtime(&now);
このように、UNIX時刻を保持したtime_t型の変数のアドレスを渡すと、struct tmへのポインタが返ってきます。
このstruct tmの中には、年、月、日、時、分、秒といった情報が個別のメンバとして格納されています。
struct tmの各メンバ(year, mon, dayなど)の意味
struct tmはカレンダー時刻を表す構造体で、time.hで定義されています。
代表的なメンバと意味を表にまとめます。
| メンバ名 | 型 | 意味 | 値の範囲や注意点 |
|---|---|---|---|
tm_year | int | 西暦年から1900を引いた値 | 2025年なら 2025 – 1900 = 125 |
tm_mon | int | 月(0〜11) | 0が1月、11が12月 |
tm_mday | int | 日(1〜31) | カレンダー上の「日」 |
tm_hour | int | 時(0〜23) | 24時間制 |
tm_min | int | 分(0〜59) | |
tm_sec | int | 秒(0〜60) | うるう秒の関係で最大60になることがあります |
tm_wday | int | 曜日(0〜6) | 0が日曜、1が月曜…6が土曜 |
tm_yday | int | 1月1日から数えた日数(0〜365) | 0が1月1日、365が12月31日(うるう年の場合) |
tm_isdst | int | 夏時間かどうか(サマータイム) | 正の値:夏時間、0:通常時間、負の値:不明 |
tm_yearやtm_monはそのまま西暦年・月の数字ではない点が初心者がよくつまずくところです。
- 西暦年を求めるには
tm_year + 1900を計算します。 - 月を人間向けに表示するには
tm_mon + 1を使います(0が1月なので)。
表示するときに+1900や+1を忘れると、意味不明な年や月が出てしまうので注意が必要です。
printfで年月日と時刻を表示するサンプルコード
ここでは、UNIX時刻からローカル時間を計算し、「YYYY-MM-DD HH:MM:SS」の形式で表示する完全なサンプルを示します。
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t now; /* 現在のUNIX時刻(秒)を格納する変数 */
struct tm *local_time; /* ローカル時間を表す構造体へのポインタ */
/* 現在のUNIX時刻を取得 */
now = time(NULL);
if (now == (time_t)-1) {
fprintf(stderr, "time 関数の呼び出しに失敗しました\n");
return 1;
}
/* UNIX時刻をローカルタイム(日本なら通常は日本時間)に変換 */
local_time = localtime(&now);
if (local_time == NULL) {
fprintf(stderr, "localtime 関数の呼び出しに失敗しました\n");
return 1;
}
/* struct tm の内容を使って「YYYY-MM-DD HH:MM:SS」形式で表示
年は tm_year + 1900、月は tm_mon + 1 にする点が重要です。 */
printf("現在のローカル時刻: %04d-%02d-%02d %02d:%02d:%02d\n",
local_time->tm_year + 1900, /* 西暦年 */
local_time->tm_mon + 1, /* 月(1〜12) */
local_time->tm_mday, /* 日(1〜31) */
local_time->tm_hour, /* 時(0〜23) */
local_time->tm_min, /* 分(0〜59) */
local_time->tm_sec); /* 秒(0〜60) */
return 0;
}
現在のローカル時刻: 2025-11-22 15:34:56
このサンプルでは、UNIX時刻の取得、エラー処理、ローカルタイムへの変換、年月日・時刻の整形表示までの一連の流れが確認できます。
gmtimeでUTC(協定世界時)に変換する場合
時刻を扱うプログラムでは、タイムゾーンの違いが問題になることがあります。
日本時間(JST)などのローカルタイムではなく、世界共通の基準時刻であるUTCを使いたい場合にはgmtime関数を使います。
gmtimeの使い方はlocaltimeとほぼ同じです。
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t now;
struct tm *utc_time;
now = time(NULL);
if (now == (time_t)-1) {
fprintf(stderr, "time 関数の呼び出しに失敗しました\n");
return 1;
}
/* UNIX時刻をUTC(協定世界時)に変換 */
utc_time = gmtime(&now);
if (utc_time == NULL) {
fprintf(stderr, "gmtime 関数の呼び出しに失敗しました\n");
return 1;
}
printf("現在のUTC時刻: %04d-%02d-%02d %02d:%02d:%02d\n",
utc_time->tm_year + 1900,
utc_time->tm_mon + 1,
utc_time->tm_mday,
utc_time->tm_hour,
utc_time->tm_min,
utc_time->tm_sec);
return 0;
}
現在のUTC時刻: 2025-11-22 06:34:56
日本時間が「2025-11-22 15:34:56」のとき、UTCは9時間前の「2025-11-22 06:34:56」になります。
ローカルタイムとUTCのどちらを使うべきかは、アプリケーションの要件によりますが、ログのタイムスタンプなどはUTCで記録することも多いです。
time関数と他の時間関数との違いを理解する
time関数とclock関数の違い
C言語にはtime関数のほかにclock関数も存在します。
名前が似ているため混同しやすいのですが、用途は大きく異なります。
time関数
「現在のカレンダー時刻」をUNIX時刻(秒)として返します。人間の生活時間や日付に対応した「実世界の時間」を扱うときに使います。clock関数
「プログラムが使用したCPU時間」を返します。これは経過時間の測定(ある関数にどれくらい時間がかかったかなど)に使うものであり、現在の日付や時刻を知るためのものではありません。
clock関数の戻り値の型はclock_tであり、秒に変換するにはCLOCKS_PER_SECで割る必要があります。
#include <stdio.h>
#include <time.h>
/* 処理時間の測定例 (現在時刻を取得するものではない点に注意) */
int main(void)
{
clock_t start, end;
double elapsed;
start = clock(); /* 測定開始時刻(CPU時間) */
/* ここに何らかの重い処理を書くとよい */
end = clock(); /* 測定終了時刻(CPU時間) */
/* 経過したCPU時間[秒]を計算 */
elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("処理に要したCPU時間: %.6f 秒\n", elapsed);
return 0;
}
このように、現在の日付や時刻を知りたいときはtime関数を使い、処理時間の計測にはclock関数を使うと覚えておくと混乱しません。
time関数とtime_tの注意点
time関数の戻り値であるtime_tには、いくつか注意点があります。
初心者の段階で知っておくと、後で困りにくくなります。
- time_tの正体は環境依存
time_tがlongとは限りません。32ビット環境では4バイト整数、64ビット環境では8バイト整数になっていることが多いですが、これは実装依存です。勝手にintやlongにキャストして使わないことが大切です。
- printfで出力するときの書式指定子
簡単な学習用コードでは(long)nowとキャストして%ldで出力することもありますが、厳密には環境に依存しない方法を使うべきです。
例えばC99以降ではstdint.hとinttypes.hを使い、intmax_tにキャストしてPRIdMAXを利用します。
#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
time_t now = time(NULL);
if (now == (time_t)-1) {
fprintf(stderr, "time 関数の呼び出しに失敗しました\n");
return 1;
}
/* intmax_t にキャストし、PRIdMAX で安全に出力する */
printf("UNIX時刻: %" PRIdMAX " 秒\n", (intmax_t)now);
return 0;
}
UNIX時刻: 1732252800 秒
学習中は(long)キャストでも実害がないことが多いですが、本番コードではできるだけ正しい書式指定を使うようにしましょう。
- 2038年問題
古い32ビット環境では、time_tが32ビット符号付き整数(約±21億秒)で実装されていることが多く、2038年1月19日以降の時刻が正しく表現できないという問題があります。
ただし、現代の多くの64ビット環境ではtime_tは64ビット整数になっており、実用上ほぼ問題ないと考えられています。
C言語で時刻を扱うときの初心者向けTips
最後に、C言語初心者が時刻まわりでつまずかないためのポイントをいくつか挙げます。
- 必ず
#include <time.h>を忘れない
time、localtime、gmtime、struct tm、time_tなど、時刻関連の機能はすべてtime.hで宣言されています。インクルードを忘れるとコンパイルエラーや警告の原因になります。 - time_t型のまま扱う
UNIX時刻を保存したり計算したりするときは、intやlongではなくtime_t型の変数を使います。型を勝手に決めつけないことが安全です。 - struct tmでは+1900、+1を忘れない
tm_yearは「1900年からの年数」、tm_monは「0から始まる月番号」です。tm_year + 1900、tm_mon + 1を必ず意識しましょう。 - localtimeとgmtimeの違いを理解する
ローカルタイム(日本時間など)が必要なのか、UTCが必要なのかを場面ごとに考えます。localtimeはタイムゾーンや夏時間の影響を受けることがある点も覚えておくと良いです。 - 文字列フォーマットにはstrftimeも便利
この記事ではprintfで直接フォーマットしましたが、strftimeを使うと"%Y-%m-%d %H:%M:%S"のような書式指定で日時文字列を作れます。慣れてきたらこちらも調べてみると良いでしょう。
まとめ
time関数は、C言語で現在のUNIX時刻(秒)を取得するための最も基本的な関数です。
time関数で得られるtime_tは、そのままではただの秒数なので、localtimeやgmtimeを使ってstruct tmに変換し、tm_year + 1900やtm_mon + 1のように補正して年月日・時刻を表示します。
また、clock関数との違い、time_tの型が環境依存であることなども理解しておくと、より安全で汎用的なコードが書けます。
サンプルコードを実際に動かしながら、自分のPCで現在時刻を取得・表示する流れを体験してみてください。
