閉じる

【C言語】 strftime 書式指定子一覧 基礎からの使い方と例

日時を自分の好きな形に整形するには、C言語の strftime が便利です。

本記事では、「どの指定子で何が出るのか」を初心者の方にも分かりやすく、用途別に整理して紹介します。

現場でよく使う実例や、ロケールやタイムゾーンに関する注意点、戻り値やバッファサイズの扱いまで、基礎から一気に確認できます。

C言語の strftime 基本

strftimeとは

strftime は、struct tm で表した日時を、指定したフォーマット文字列に従って可読な文字列へ変換する関数です。

任意の並びや区切り記号で年月日時分秒を組み立てられるため、ログやファイル名、画面表示などに広く使われます。

ロケール(地域設定)に依存して、曜日名や月名が現地表記になる点も特徴です。

事前準備

strftime を使うには #include <time.h> が必要です。

曜日名や月名を日本語などのロケールで表示したい場合は #include <locale.h> により setlocale(LC_TIME, "...") を設定します。

C言語
#include <stdio.h>
#include <time.h>
#include <locale.h>

int main(void) {
    // LC_TIME を環境依存の既定にする。日本語環境なら月名や曜日が日本語になる場合があります。
    // 一貫した英語表記にしたい場合は setlocale(LC_TIME, "C") を使います。
    setlocale(LC_TIME, "");

    time_t now = time(NULL);                 // 現在のUNIX時刻(秒)
    struct tm *lt = localtime(&now);         // ローカルタイムへ変換
    char buf[128];

    // 年-月-日 時:分:秒 のよくある形式
    if (strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lt) > 0) {
        printf("Now: %s\n", buf);
    } else {
        puts("バッファが不足しました");
    }
    return 0;
}
実行結果
Now: 2025-03-01 14:05:09
注意

実際の出力は実行時刻とロケールに依存します。

関数の形と引数

strftime の宣言は以下です。

C言語
#include <time.h>
size_t strftime(char *restrict s, size_t max,
                const char *restrict format,
                const struct tm *restrict tm);
  • s: 出力を書き込むバッファ
  • max: バッファのサイズ(終端のヌル文字も含む最大長)
  • format: 書式文字列。%Y%m などの書式指定子を含む
  • tm: 変換元の日時(struct tm)

戻り値は、書き込まれた文字数(終端のヌル文字は含まない)です。

結果が収まらなかった場合は 0 を返します。

基本例

日時を固定して再現性のある出力を得る例です。

ロケールは英語表記の "C" に固定しています。

C言語
#include <stdio.h>
#include <time.h>
#include <locale.h>

int main(void) {
    setlocale(LC_TIME, "C"); // 英語の月名/曜日で固定

    // 2025-03-01 14:05:09 土曜日 を構築
    struct tm t = {0};
    t.tm_year = 2025 - 1900; // 1900年からの年数
    t.tm_mon  = 3 - 1;       // 0起算の月
    t.tm_mday = 1;           // 日
    t.tm_hour = 14;          // 時(24時間)
    t.tm_min  = 5;           // 分
    t.tm_sec  = 9;           // 秒
    t.tm_wday = 6;           // 0=Sun, 6=Sat (任意設定。mktimeで正規化も可)
    t.tm_yday = 59;          // 0起算の通し日 2025は平年、3/1は60日目→0起算で59
    t.tm_isdst = -1;         // 夏時間情報不明なら -1

    char buf[128];

    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &t);
    printf("ISO風       : %s\n", buf);

    strftime(buf, sizeof(buf), "%A, %B %d, %Y", &t);
    printf("英語での長書式: %s\n", buf);

    strftime(buf, sizeof(buf), "%x %X (%a)", &t);
    printf("ロケール依存  : %s\n", buf);

    return 0;
}
実行結果
ISO風       : 2025-03-01 14:05:09
英語での長書式: Saturday, March 01, 2025
ロケール依存  : 03/01/25 14:05:09 (Sat)
ポイント

%A%B はロケール依存で曜日・月名を文字列化します。

バッファサイズと戻り値

出力がバッファに収まらないと戻り値は0になります。

必要なサイズは strftime では直接取得できないため、十分に大きなバッファを用意するか、while で拡張する戦略をとります。

C言語
#include <stdio.h>
#include <time.h>
#include <locale.h>
#include <stdlib.h>

int main(void) {
    setlocale(LC_TIME, "C");

    time_t now = time(NULL);
    struct tm *lt = localtime(&now);

    size_t cap = 8;                 // わざと小さく
    char *buf = malloc(cap);
    const char *fmt = "%Y-%m-%d %H:%M:%S %Z";

    while (1) {
        size_t n = strftime(buf, cap, fmt, lt);
        if (n > 0) {                // 正常に収まった
            printf("OK(%zu bytes): %s\n", n, buf);
            break;
        }
        // 収まらなかった。容量を増やして再挑戦
        cap *= 2;
        char *nbuf = realloc(buf, cap);
        if (!nbuf) { perror("realloc"); free(buf); return 1; }
        buf = nbuf;
    }
    free(buf);
    return 0;
}
実行結果
OK(24 bytes): 2025-03-01 14:05:09 JST
補足

書式が空文字列の場合、妥当な結果でも戻り値は0になります。

このため、空書式かどうかを自分で管理して判定すると安全です。

書式指定子一覧

年の書式指定子

よく使う指定子

以下は年に関する代表的な指定子です。

例は 2025-03-01 14:05:09 を英語ロケール(C)で想定したものです。

指定子意味規格
%Y西暦(4桁以上、負年も可)2025C標準
%y西暦下2桁(00-99)25C標準
%C世紀(年/100の整数部、00-99)20POSIX拡張
%GISO週番号に対応する年(週基準)2025POSIX拡張
%gISO週番号に対応する年の下2桁25POSIX拡張

注意点

%Y と %y は同じ年を異なる桁数で表すだけで、うるう年判定などの論理は関与しません。

%G/%g は ISO週単位の年で、年末年始で暦年とずれることがあります。移植性には注意してください。

月の書式指定子

よく使う指定子

指定子意味規格
%m月の数字(01-12)03C標準
%b月名の短縮形MarC標準
%B月名の完全形MarchC標準
%h%b と同じMarPOSIX拡張

注意点

%b/%B はロケール依存です。日本語ロケールで「3月」と出るかは環境のロケール設定に依存します。

日の書式指定子

よく使う指定子

指定子意味規格
%d月内通し日(01-31)01C標準
%e月内通し日(スペース詰め、 1-31)1POSIX拡張

注意点

先頭ゼロの有無を調整したい時に %e が便利ですが、Windowsなど一部実装では未対応の版があります

通し日の書式指定子

指定子と説明

指定子意味規格
%j年内通し日(001-366)060C標準

注意点

%j はうるう年で範囲が最大366になります。

日付全体の書式指定子

よく使う指定子

指定子意味規格
%xロケール依存の日付03/01/25C標準
%FISO 8601形式 日付(YYYY-MM-DD)2025-03-01POSIX拡張
%Dmm/dd/yy03/01/25POSIX拡張

注意点

可搬性重視なら %F が簡潔で読みやすいですが、古い実装では未対応の可能性があります。

代替として %Y-%m-%d を使えば確実です。

書式指定子一覧

時の書式指定子

よく使う指定子

指定子意味規格
%H時(00-23)14C標準
%I時(01-12)02C標準

注意点

12時間表記の %I%p と組み合わせるのが一般的です。

分の書式指定子

指定子と説明

指定子意味規格
%M分(00-59)05C標準

秒の書式指定子

指定子と説明

指定子意味規格
%S秒(00-60)09C標準

注意点

うるう秒のため理論上は60があり得ますが、実装やOSがうるう秒を扱わない場合もあります

午前午後の書式指定子

指定子と説明

指定子意味規格
%p午前午後の指示子(ロケール依存)PMC標準
%P%p の小文字形pmPOSIX拡張

注意点

一部言語では午前午後という文化がないため、%p の表現はロケールによって非対称だったり、空文字の場合もあります。

時刻全体の書式指定子

よく使う指定子

指定子意味規格
%Xロケール依存の時刻14:05:09C標準
%THH:MM:SS14:05:09POSIX拡張
%RHH:MM14:05POSIX拡張
%r12時間書式02:05:09 PMPOSIX拡張

注意点

移植性重視なら %H:%M[:%S] を自前で組むと確実です。

曜日・月名・その他の書式指定子

曜日の書式指定子

指定子と説明

指定子意味規格
%a曜日名の短縮形SatC標準
%A曜日名の完全形SaturdayC標準

注意点

ロケール依存。setlocale(LC_TIME, "") を設定するとOSのロケールに従います。

月名の書式指定子

指定子と説明

指定子意味規格
%b月名の短縮形MarC標準
%B月名の完全形MarchC標準
%h%b と同じMarPOSIX拡張

曜日番号の書式指定子

指定子と説明

指定子意味範囲規格
%w曜日番号(日曜=0)0-6C標準
%u曜日番号(月曜=1)1-7POSIX拡張

注意点

曜日の基準が異なるため、アルゴリズムで使う際は混同に注意します。

週番号の書式指定子

指定子と説明

指定子意味規格
%U週番号。日曜始まり。年初の最初の日曜を含む週が第1週。範囲00-53C標準
%W週番号。月曜始まり。年初の最初の月曜を含む週が第1週。範囲00-53C標準
%VISO 8601の週番号。月曜始まり。第1週は1月4日を含む週。範囲01-53POSIX拡張
%GISO週番号に対応する年POSIX拡張
%gISO週番号に対応する年の下2桁POSIX拡張

例(2025-03-01 土曜)

%U は 08、%W も 08、%V は 09、%G は 2025、%g は 25 となります。

注意点

ISO週番号は年末年始で年がまたがる場合があります。

請求週やISO準拠の週次集計には %V/%G を、汎用的な週番号には %U/%W を使うなど、用途で使い分けると良いです。

日時まとめの書式指定子

指定子と説明

指定子意味規格
%cロケール依存の日時(長書式)Sat Mar 1 14:05:09 2025C標準

注意点

出力はロケール定義に大きく依存します。ログなど機械処理が前提なら %Y-%m-%d %H:%M:%S を推奨します。

タイムゾーンの書式指定子

指定子と説明

指定子意味規格
%Zタイムゾーン名または略称JST, UTC 等C標準
%zUTCからの数値オフセット(+hhmm)+0900, +0000 等POSIX拡張

動作例

C言語
#include <stdio.h>
#include <time.h>
#include <locale.h>

int main(void) {
    setlocale(LC_TIME, "C");

    time_t now = time(NULL);
    struct tm *lt = localtime(&now);

    char buf1[64], buf2[64];
    strftime(buf1, sizeof(buf1), "%Y-%m-%d %H:%M:%S %Z", lt);
    strftime(buf2, sizeof(buf2), "%Y-%m-%d %H:%M:%S %z", lt);

    printf("Zone name : %s\n", buf1);
    printf("UTC offset: %s\n", buf2);
    return 0;
}
実行結果
Zone name : 2025-03-01 14:05:09 JST
UTC offset: 2025-03-01 14:05:09 +0900
注意

%Z/%z の対応は実装依存です。

特に %z はPOSIX拡張で、古いWindows Cランタイムでは未対応のことがあります。

パーセントそのもの

指定子と説明

指定子意味規格
%%文字 % を出力%C標準

ロケールで表示が変わる指定子

%a%A%b%B%c%p%x%X%Z はロケール依存です。

必要に応じて以下を使い分けます。

  • ロケールに依存しない安定出力が必要な場合は、“C” ロケールを明示するか、数値指定子を組み合わせて自前でフォーマットします。
  • POSIXロケール拡張では、E/O 修飾子により暦法や数字体系の代替表現を出すことがありますが、移植性は低めです。
参考

ロケール設定の例

C言語
#include <locale.h>

// システムの既定ロケール
setlocale(LC_TIME, "");

// 英語固定
setlocale(LC_TIME, "C");

// 日本語(UTF-8)の一例。OSに該当ロケールがインストールされている必要があります。
setlocale(LC_TIME, "ja_JP.UTF-8");

実行結果の例(ロケール別)

LC_TIME="C"           => Sat Mar  1 14:05:09 2025
LC_TIME="ja_JP.UTF-8" => 2025年03月01日 14時05分09秒 土曜日
注意

実際の表示は各ロケール定義に依存します。

上記は一例です。

まとめ

strftime は「tm構造体を自在に成形する道具」です。

年なら %Y%y、月なら %m%B、日なら %d%j、時刻なら %H/%M/%S、日時まとめなら %F%T%c のように、用途に応じて組み合わせるのが基本です。

ロケール依存の指定子は見た目の豊かさが得られる一方で、機械処理やログの安定性を重視する場合は数値指定子の組み合わせが堅実です。

また、バッファサイズ不足時は戻り値が0になる点を必ず考慮しましょう。

最後に、POSIX拡張の指定子(例: %F, %T, %z など)は移植性に差があるため、ターゲット環境の対応状況を確認してから採用するのが安心です。

C言語 標準ライブラリの活用

この記事を書いた人
エーテリア編集部
エーテリア編集部

プログラミングの基礎をしっかり学びたい方向けに、C言語の基本文法から解説しています。ポインタやメモリ管理も少しずつ理解できるよう工夫しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!