STRFTIME(3) | Linux Programmer's Manual | STRFTIME(3) |
strftime - 日付および時刻の文字列への変換
#include <time.h>
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
strftime() 関数 は、要素別の時刻 tm の内容を format で指定された書式指定にしたがって変換し、長さ max の文字列 s に書き込む。要素別の時刻構造体 tm は <time.h> で定義されている。 ctime(3) も参照。
書式指定はヌル終端された文字列であり、「変換指定 (conversion specification)」と呼ばれる特別な文字列を含めることができる。各々の変換指定は '%' 文字で始まり、「変換指定文字 (conversion specifier character)」と呼ばれる何らか他の文字で終端される。上記以外の全ての文字列は「通常の文字列 (ordinary character sequence)」となる。
(NULL バイトも含む) 通常の文字列内の文字は、そのまま format から s にコピーされる。一方、変換指定の文字は以下のリストに示すように置換される。このリストでは、 tm 構造体のフィールドが参照される場合、その情報も記載している。
いくつかの変換指定では、変換指定文字の前に E や O 「修飾子」を置くことによって別書式を使用するように指定することができる。 現在のロケールにおいて別書式が存在しない場合には、 通常の変換指定が使用されたかのように動作する (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 修飾子を使った場合のデータ表現に適用されるルールは、 nl_langinfo(3) の引数に ERA を指定することで取得できる。このような別表現の例としては ja_JP glibc ロケールでの日本の年号 (「昭和」「平成」など) によるカレンダー表記がある。
終端のヌルバイトを含めた結果の文字列の長さが max バイトを超えなかった場合、 strftime() 関数は配列 s に格納されたバイト数を返す (このバイト数に終端のヌルバイトは含まれない)。 終端のヌルバイトを含めた結果の文字列の長さが max バイトを超える場合には、 strftime() は 0 を返し、配列の内容は不定となる。
返り値 0 は必ずしもエラーを意味している訳ではないので注意すること。例えば、多くのロケールでは %p は空文字列を返す。同様に、空の format 文字列は空文字列を返す。
環境変数 TZ と LC_TIME が使用される。 (訳注: LC_ALL が設定されている場合には LC_TIME よりもそちらが優先される。 LC_TIME も LC_ALL も設定されていない場合には LANG が使用される。)
この節で使用されている用語の説明については、 attributes(7) を参照。
インターフェース | 属性 | 値 |
strftime() | Thread safety | MT-Safe env locale |
SVr4, C89, C99. 個々の変換が厳密にどの規格に含まれるかをマークで示している。「マークなし」は ANSI C、「SU」は統一 UNIX 規格を、「TZ」は Olson の timezone パッケージ、「GNU」は glibc を示す。 glibc2 では %+ はサポートされていないが、 いくつかの拡張が行われている。POSIX.1 では ANSI C のみを参照している。 POSIX.2 の date(1) のところに記述されている幾つかの拡張は strftime() にも適用できるだろう。 %F 変換は C99 と POSIX.1-2001 にある。
SUSv2 では、 %S は 00 から 61 の範囲をとると規定されている。 これは、1 分間のうち閏秒が 2 つ入る可能性が理論的にはあることを考慮してのものである (実際には、このような状況はこれまで一度も 起こっていない)。
%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 日の月曜日から始まる。同様に、 2011 年 1 月の最初の 2 日は 2010 年の週 52 の一部とみなされる。
glibc では変換指定にいくつか拡張を行っている (これらの拡張は POSIX.1-2001 には規定されていないが、 他のいくつかのシステムで同様の機能が提供されている)。 '%' 文字と変換指定文字の間に、オプションとして フラグ とフィールドの 幅 を指定できる (これらを指定する場合には E や O 修飾子の前に置く)。
以下のフラグ文字が使用できる。
オプションの 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); }
date(1), time(2), ctime(3), nl_langinfo(3), setlocale(3), sprintf(3), strptime(3)
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。
2020-08-13 | GNU |