strftime(3) 日付および時刻の文字列への変換

書式

#include <time.h>


size_t strftime(char *s, size_t max, const char *format,
const struct tm *tm);

説明

strftime() 関数 は、要素別の時刻 tm の内容を format で指定された書式指定にしたがって変換し、 長さ max の文字列 s に書き込む。

書式指定はヌル終端された文字列であり、 「変換指定 (conversion specification)」と呼ばれる特別な文字列を 含まることができる。 各々の変換指定は '%' 文字で始まり、 「変換指定文字 (conversion specifier character)」と呼ばれる 何らか他の文字で終端される。上記以外の全ての文字列は 「通常の文字列 (ordinary character sequence)」となる。

(NULL バイトも含む) 通常の文字列内の文字は、 そのまま format から s にコピーされる。 一方、変換指定の文字は以下のように置換される。

%a
現在のロケールにおける曜日の省略名。
%A
現在のロケールにおける曜日の完全な名前。
%b
現在のロケールにおける月の省略名。
%B
現在のロケールにおける月の完全な名前。
%c
現在のロケールにおいて一般的な日付・時刻の表記。
%C
世紀 (西暦年の上 2 桁)。 (SU)
%d
月内通算日 (10 進数表記) (01-31)。
%D
%m/%d/%y と等価。(うえっ、アメリカ専用だ。アメリカ以外の国では %d/%m/%y の方が一般的だ。紛らわしいので、使用すべきではない。) (SU)
%e
%d と同様に月内通算日を 10 進数で表現するが、 1 桁の場合 10 の位にゼロを置かずスペースを置く。(SU)
%E
別形式を使用する際の修飾子。下記参照。 (SU)
%F
%Y-%m-%d と等価 (ISO 8601 形式の日付フォーマット)。 (C99)
%G
ISO 8601 週単位表記の年 (week-based year; 「注意」の節を参照)。 世紀も 10 進数で表す。 ISO 週番号 (%V を参照) に対応した 4 桁の西暦年。 これは基本的には %Y と同じ形式だが、ISO 週数が前年や翌年になる 場合にはその年が使用される点が異なる。(TZ)
%g
%G と同様。但し、世紀を含まず下 2 桁のみを表示 (00-99)。 (TZ)
%h
%b と等価 (SU)
%H
24 時間表記での時 (hour)。 (00-23)
%I
12 時間表記での時 (hour)。 (01-12)
%j
年の初めから通算の日数。 (001-366)
%k
24 時間表記での時 (0-23)。 1 桁の場合には前にゼロでなくスペースが置かれる。 (%H も参照) (TZ)
%l
12 時間表記での時 (0-12)。 1 桁の場合には前にゼロでなくスペースが置かれる。 (%I も参照) (TZ)
%m
月 (10 進数表記)。 (01-12)
%M
分 (10 進数表記) (00-59)
%n
改行。 (SU)
%O
別形式を使用する際の修飾子。下記参照。 (SU)
%p
現在のロケールにおける「午前」「午後」に相当する文字列。 英語の場合には "AM" または "PM" となる。 正午は「午後」、真夜中は「午前」として扱われる。
%P
%p と同様であるが小文字が使用される。 英語の場合には "am" や "pm" となる。(GNU)
%r
午前・午後形式での時刻。 POSIX ロケールでは %I:%M:%S %p と等価である。(SU)
%R
24 時間表記での時刻、秒は表示しない (%H:%M)。 秒を含んだものは以下の %T を参照すること。(SU)
%s
紀元 (Epoch; 1970-01-01 00:00:00 +0000 (UTC)) からの秒数。 (TZ)
%S
秒 (10 進数表記) (00-60) (時々ある閏秒に対応するため、値の範囲は 60 までとなっている)
%t
タブ文字 (SU)
%T
24 時間表記の時間 (%H:%M:%S) (SU)
%u
週の何番目の日 (10 進数表記) か。月曜日を 1 とする (1-7)。 %w も参照。(SU)
%U
年の初めからの通算の週番号 (10 進数表記) (00-53)。 その年の最初の日曜日を、第 1 週の始まりとして計算する。 %V%W も参照すること。
%V
ISO 8601 形式での年の始めからの週番号 (「注意」の節を参照)。 10 進数表記で、01 から 53 の値となる。週番号は、 新しい年が少なくとも 4 日以上含まれる最初の週を 1 として計算する。 %U%W も参照のこと。(SU)
%w
週の何番目の日 (10 進数表記) か。日曜日を 0 とする。(0-6)。 %u も参照。(SU)
%W
年の初めからの通算の週番号 (10 進数表記) (00-53)。 その年の最初の月曜日を、第 1 週の始まりとして計算する。
%x
現在のロケールで一般的な日付表記。時刻は含まない。
%X
現在のロケールで一般的な時刻表記。日付は含まない。
%y
西暦の下2桁 (世紀部分を含まない年) (00-99)。
%Y
世紀部分を含めた ( 4 桁の) 西暦年。
%z
+hhmm-hhmm の形式のタイムゾーン (UTC へのオフセット時間)。(SU)
%Z
タイムゾーン名または省略名。
%+
date(1) 形式での日時。(TZ) (glibc2 ではサポートされていない)
%%
'%' 文字。

いくつかの変換指定では、変換指定文字の前に EO 「修飾子」を置くことによって別書式を使用するように指定することができる。 現在のロケールにおいて別書式が存在しない場合には、 通常の変換指定が使用されたかのように動作する (SU)。 統一 UNIX 規格 (Single UNIX Specification) では %Ec, %EC, %Ex, %EX, %Ey, %EY, %Od, %Oe, %OH, %OI, %Om, %OM, %OS, %Ou, %OU, %OV, %Ow, %OW, %Oy, について記述がある。ここで O 修飾子は別形式の数値 (ローマ数字とか) を指定するために使用する。 E 修飾子はロケール依存の別表現を指定するのに使用する。 (訳注: E 修飾子は日本で使用されている「昭和」「平成」 などの元号による年表記を指定する。glibc 2.2 以降でのみ有効)

要素別の時刻構造体 tm の詳細は <time.h> に定義されている。 ctime(3) も参照すること。

返り値

終端のヌルバイトを含めた結果の文字列の長さが max バイトを超えなかった場合、 strftime() 関数は配列 s に格納されたバイト数を返す (このバイト数に終端のヌルバイトは含まれない)。 終端のヌルバイトを含めた結果の文字列の長さが max バイトを超える場合には、 strftime() は 0 を返し、配列の内容は不定となる。 (少なくとも libc 4.4.4 以降ではこの動作となる。 libc 4.4.1 などの非常に古いバージョンの libc では配列が短かすぎた場合には max が返される。)

返り値 0 は必ずしもエラーを意味している訳ではないので注意すること。 例えば、多くのロケールでは %p は空文字列を返す。 同様に、空の format 文字列は空文字列を返す。

環境変数

環境変数 TZLC_TIME が使用される。 (訳注: LC_ALL が設定されている場合には LC_TIME よりもそちらが優先される。 LC_TIMELC_ALL も設定されていない場合には LANG が使用される。)

準拠

SVr4, C89, C99. 個々の変換が厳密にどの規格に含まれるかは、 ANSI C (印なし)、統一 UNIX 規格 (SU印)、Olson の timezone パッケージ (TZ印)、 glibc 独自 (GNU印) で示している。glibc2 では %+ はサポートされていないが、 いくつかの拡張が行われている。POSIX.1 では ANSI C のみを参照している。 POSIX.2 の date(1) のところに記述されている幾つかの拡張は strftime() にも適用できるだろう。 %F 変換は C99 と POSIX.1-2001 にある。

SUSv2 では、 %S は 00 から 61 の範囲をとると規定されている。 これは、1分間のうち閏秒が 2つ入る可能性が理論的にはあることを 考慮してのものである (実際には、このような状況はこれまで一度も 起こっていない)。

注意

ISO 8601 の週・曜日表記 (Week Dates)

%G, %g, %V は、ISO 8601 標準により定義された週単位表記の年により 計算される値を出力する。 ISO 8601 標準の週単位表記では、週は月曜日から開始され、 週番号は、年の最初の週が 01 となり、最後の週は 52 か 53 となる。 週 01 は、新しい年が 4 日以上含まれる最初の週である。 言い換えると、週 01 は、その年の木曜日を含む最初の週、 つまり 1 月 4 日を含む週ということである。 新しい年のカレンダー上の最初の週に新しい年が 3 日以下しか含まれない場合、 ISO 8601 の週単位表記では、これらの日を前の年の週 53 の一部とみなす。 例えば、2010 年 1 月 1 日は金曜日であり、 その週には 2010 年の日が 3 日しか含まれない。 したがって、ISO 8601 の週単位表記では、これらの日は 2009 年 (%G) の週 53 (%V) の一部となる。 ISO 8601 の 2010 年の週 01 は 2010 年 1 月 4 日の月曜日から始まる。

glibc での注意

glibc では変換指定にいくつか拡張を行っている (これらの拡張は POSIX.1-2001 には規定されていないが、 他のいくつかのシステムで同様の機能が提供されている)。 '%' 文字と変換指定文字の間に、オプションとして flag とフィールドの を指定できる (これらを指定する場合には EO 修飾子の前に置く)。

以下のフラグ文字が使用できる:

_
(下線) 数値の結果文字列のパディング (穴埋め) をスペース (空白文字) で行う。
-
(ダッシュ) 数値の結果文字列に対するパディングを行わない。
0
変換指定文字がデフォルトではスペースでパディングを行う場合でも、 数値の結果文字列へのパディングを 0 で行う。
^
結果文字列中のアルファベット文字を大文字に変換する。
#
結果文字列の大文字・小文字を入れ替える (このフラグは特定の変換指定文字でしか機能しない。その中でも 本当に有用なのは %Z の場合だけである)。

オプションの10進数の幅指定子はフラグの後ろに置くことができる (フラグはなくてもよい)。フィールドの本来の大きさが指定された幅よりも 小さい場合、結果文字列の左側は指定された幅までパディングされる。

バグ

出力文字列が max バイトを超えてしまう場合、 errno は設定「されない」。 このため、このエラーを、 format 文字列がきちんと処理されて長さ 0 の出力文字列が生成される場合を区別することができない。 POSIX.1-2001 では strftime() で errno に設定する値について一切規定して「いない」。

gcc(1) のいくつかのバージョンにはおかしなところがあり、 %c の使用法について以下のような警告を出す: warning: `%c' yields only last 2 digits of year in some locales (警告:いくつかのロケールでは`%c'は年の下2桁しか出力しない)。 もちろんプログラマが %c を使うのはお薦めできることである。 %c を使うと適切な日付と時刻の表記を得ることができるからである。 gcc(1) のこの問題を回避しようとすると、何かすっきりしない気分になるだろう。 比較的きれいな解決方法は以下のような中間関数を追加することである。

size_t
my_strftime(char *s, size_t max, const char *fmt,
            const struct tm *tm)
{
    return strftime(s, max, fmt, tm);
}

現在では、 gcc(1) はこの警告を抑えるための -Wno-format-y2k オプションを 提供しており、上記の回避策はもはや必要ない。

RFC 2822 準拠の日付形式 (%a と %b は英語ロケール)

"%a, %d %b %Y %T %z"

RFC 822 準拠の日付形式 (%a と %b は英語ロケール)

"%a, %d %b %y %T %z"

サンプルプログラム

以下のプログラムを使うと strftime() の実験ができる。

以下に、 strftime() の glibc 実装が生成する結果の例をいくつか示す:

$ ./a.out '%m'
Result string is "11"
$ ./a.out '%5m'
Result string is "00011"
$ ./a.out '%_5m'
Result string is "   11"

プログラムのソース

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
    char outstr[200];
    time_t t;
    struct tm *tmp;
    t = time(NULL);
    tmp = localtime(&t);
    if (tmp == NULL) {
        perror("localtime");
        exit(EXIT_FAILURE);
    }
    if (strftime(outstr, sizeof(outstr), argv[1], tmp) == 0) {
        fprintf(stderr, "strftime returned 0");
        exit(EXIT_FAILURE);
    }
    printf("Result string is \"%s\"\n", outstr);
    exit(EXIT_SUCCESS);
}

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。