C Snippets

C の Unix タイムスタンプ スニペット

現在の Unix タイムスタンプの取得、strftime() でのエポック秒の読みやすい日付への変換、timegm() での暦日からのタイムスタンプ構築を行う C の例。

Current Unix timestamp (seconds)
#include <time.h>

time_t ts = time(NULL);
Current timestamp (milliseconds, POSIX)
#include <time.h>

struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
long ms = (long)ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
Format timestamp as UTC string
#include <time.h>
#include <stdio.h>

time_t ts = 1700000000;
struct tm *tm_info = gmtime(&ts);  // UTC
char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm_info);
printf("%s\n", buf);  // "2023-11-15 06:13:20"
Format timestamp as local time string
#include <time.h>

time_t ts = 1700000000;
struct tm *tm_info = localtime(&ts);  // host timezone
char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm_info);
Timestamp from calendar date (UTC, GNU)
#define _GNU_SOURCE
#include <time.h>

struct tm t = {0};
t.tm_year = 2023 - 1900;  // years since 1900
t.tm_mon  = 10;           // 0-indexed; 10 = November
t.tm_mday = 15;
t.tm_hour = 6;
t.tm_min  = 13;
t.tm_sec  = 20;
time_t ts = timegm(&t);   // GNU/POSIX; use mktime() for local
Time difference in seconds
#include <time.h>

time_t start = time(NULL);
/* ... work ... */
time_t end = time(NULL);
double elapsed = difftime(end, start);

C のタイムスタンプの基本

C は Unix 時間を time_t(<time.h> で定義される符号付き整数型)として表します。64 ビットシステムでは time_t は 64 ビットで、2038 年問題のオーバーフローの影響を受けません。32 ビットシステムでは多くのプラットフォームで依然 32 ビットです。確認には sizeof(time_t) を調べます。標準関数 time(NULL) は現在の Unix 時間を秒で返します。

gmtime と localtime

gmtime() は time_t を UTC の struct tm に変換します。localtime() はホストシステムのローカルタイムゾーンに変換します。再現可能でタイムゾーンに依存しない結果が必要なときは、常に gmtime() を使います。どちらの関数も共有の静的 struct へのポインタを返します。関数呼び出しをまたいで必要なときは、ローカルの struct tm 変数に結果をコピーします。

C の本番運用メモ

秒未満の精度には gettimeofday() より clock_gettime(CLOCK_REALTIME) を優先してください。POSIX は gettimeofday() を廃止予定としています。暦の日付を UTC タイムスタンプに変換するときは timegm()(GNU/BSD)または移植可能な同等手段を使います。mktime() は入力をローカル時刻として解釈し、UTC でない環境では静かに誤った結果を生みます。

  • 組み込みターゲットでは sizeof(time_t) を確認する。32 ビットの time_t は 2038 年 1 月に巻き戻る
  • マルチスレッドコードでは、データ競合を避けるため gmtime_r() と localtime_r() を使う
  • strftime() の書式文字列はロケール非依存。相互運用性のため %x より %Y-%m-%d を優先する
  • timegm() は POSIX にない。Windows では _mkgmtime() を使うか、mktime() + UTC オフセットで手動実装する

Linux 時刻を変換する:date(1)、time_t、gmtime、strftime

「convert linux time」や Linux のタイムスタンプ変換の検索は、通常シェルコマンド date(1)、または下記の C ライブラリの time_t 関数を意味します。Linux は Unix タイムスタンプを time_t として保存します — 旧システムでは符号付き 32 ビット(Y2038 限界)、最新では符号付き 64 ビットです。

  • Shell (GNU date): date -u -d @1700000000 — epoch → UTC 日時
  • Shell (BSD/macOS): date -ur 1700000000 — -d @ ではなく -r に注意
  • Shell の現在のエポック: date +%s(秒)、date +%s%3N(ミリ秒、GNU のみ)
  • C ライブラリ: time_t t = time(NULL); struct tm *u = gmtime(&t); strftime(buf, sizeof(buf), '%Y-%m-%dT%H:%M:%SZ', u);
  • C ライブラリ: timegm(struct tm *) は UTC の暦時刻に対する time_t を返す
  • POSIX time_t: 符号付き 32 ビットは 2038-01-19 にオーバーフローする。64 ビット time_t が最新の修正

Linux エポック時間、Linux タイムスタンプから時刻へ、オンライン Linux 変換

バリエーション:「linux epoch time」(Linux 上の Unix 時間)、「linux timestamp to time」(epoch → 壁掛け時計)、「linux timestamp converter online」(このページ)。

  • Linux epoch time / linux epoch time — Unix 時間と同じ。現在の値:date +%s
  • Linux timestamp to time / linux timestamp to time — date -u -d @1700000000 は UTC の壁掛け時計の時刻を返す
  • Linux timestamp converter online / linux timestamp converter online — このページは date(1) のブラウザ版に相当する

FAQ

C で Unix タイムスタンプにはどの型を使うべきか?
秒精度には time_t を、ミリ秒やナノ秒を保存する必要があるときは int64_t(<stdint.h> から)を使ってください。int や long はサイズがプラットフォーム依存なので避けてください。
C でミリ秒を得るには?
<time.h> の clock_gettime(CLOCK_REALTIME, &ts) を使います。結果は ts.tv_sec(秒)と ts.tv_nsec(ナノ秒)に入ります。ミリ秒は ts.tv_sec * 1000LL + ts.tv_nsec / 1000000 で計算します。