最近更新したページ
2013-10-20
2013-09-29
2013-09-23
2012-01-07
2011-11-09
2011-10-23
2011-10-09
2011-10-01
2011-09-29
2011-09-03
2011-08-07
2011-08-02
2011-07-29
2011-07-10
2011-05-05
2011-05-04
2011-04-24
2011-04-13
2011-04-05
2011-03-26
2011-02-18
2011-02-15
2010-12-26
2010-12-07
2010-12-05
2010-11-23
2010-09-28
2010-09-23
2010-08-26
2010-08-22
2010-07-16
2010-01-17
2010-01-11
2009-10-04
2009-08-21
2009-08-13
2009-06-18
2009-06-01
2009-04-29
2009-02-16
2009-02-11
2009-02-03
2008-07-22
2008-07-21
2008-07-15
2008-07-14
2008-07-13
2008-07-12
2008-07-08
2008-07-05
2008-06-28
2008-06-17
2008-06-05
2008-06-02
2008-06-01
2008-05-29
2008-05-26
2008-05-21
2008-05-19
2008-05-18
2007-10-31
2007-10-27
2007-09-28
2007-09-23
2007-09-17
2007-09-16
2007-09-14
2007-09-11
2007-06-18
2007-04-15
2006-12-21
2006-11-30
2006-11-22
2006-08-17
2006-03-29
2006-03-28
2006-03-27

C/C++ 日付と時刻


C/C++ 日付と時刻


「日付・時刻」の取り扱い準備


 C言語 と C++ では、「時付・時刻」の関数が若干異なるようで、C言語用関数を cpp で #include <iostream> で使用すると、実行出来ない訳ではないが warning err が発生する。

※localtime(), gmtime() で発生。time() では発生しない。

 例えば localtime_s() とする場合でも、変数の使用方法(宣言)や、パラメータが異なるなどなんとも厄介。
 取り合えず、C言語の「日付・時刻」関数に慣れてから、C++ の関数を見て行こうと思う。

※MS の説明ではかなり関数が増殖しているようである。.NET/MS独自拡張?の区別も現状把握していない。
※MS では、localtime_s() 推奨のようであるが、linux 等では localtime_r() などというのも有るらしく 何が標準なのやら・・・。
※C言語仕様では、構造体 tm 変数利用上のセキュリティ的な問題があるらしい。

▲上へ

「日付・時刻」関数

※要 #include <time.h>
※cpp で iostream をインクルードすると Warning C4996: が出て localtime_s 等、_s 拡張関数使用指示が出るが、実行は可能。stdio.h なら cpp でも Warning 出ず。
※注:_s 付き関数は、MS拡張?のため移植性が無い。

  • 現在の日時を取得
    • time ・・・ システムの日時を取得
      • time_t=time(*time_t); // cpp worning 無し。
    • clock ・・・ システムタイムを取得
      • clock_t=clock(void); // cpp Warning 無し。
  • 取得日時を tm(構造体) へ代入
    • gmtime ・・・ time_tを GMT 変換し 構造体(tm)へ代入
      • tm=gmtime(*time_t); // warning C4996:
    • localtime ・・・ time_tを構造体(tm)へ代入
      • tm=localtime(*time_t); // warning C4996:
  • tm(構造体)データを time_t型へ変換
    • mktime ・・・ 構造体(tm)データを time_t型へ変換する
      • time_t=mktime(*tm) // cpp Warning 無し。
  • 取得日時を文字列へ変換
    • asctime ・・・ 構造体(tm)を定型フォーマットの文字列へ変換
      • s=asctime(*tm); // warning C4996:
    • ctime ・・・ time_t を定型フォーマットの文字列へ変換
      • s=ctime(*time_t); // warning C4996:
    • strftime ・・・ 指定書式文字列へ変換する
      • size_t=strftime(*s, size_t, *fm, *tm); // cpp Warning 無し。
  • 時刻の差分を求める
    • difftime ・・・ 時刻の差を秒で得る
      • double=difftime(time_t2, time_t1); // cpp Warning 無し。

※注:かなりてきと〜。

▲上へ [ 編集 ]

※参考
function comment
標準lib char *asctime(const struct tm *tsp); 定型文字列変換
- errno_t asctime_s(char* s, size_t mel, const struct tm *tsp) ms拡張
- char *asctime_r(const struct tm *tsp, char *s); linux拡張?
※構造体渡し、戻値:文字列ポインタ
標準lib char *ctime(const time_t *ttp); 定型文字列変換
- errno_t ctime_s(char* s, size_t mel, const time_t *ttp); ms拡張
- char *ctime_r(const time_t *ttp, char *s); linux拡張?
※time_t型渡し、戻値:文字列ポインタ
標準lib struct tm *gmtime(const time_t *ttp); GMT変換、tm代入
- gmtime_s()??MSDN 無い?が動く(爆) msdn -> _gmtime_s()有り。 ms拡張
- struct tm *gmtime_r(const time_t *ttp, struct tm *tsp); linux拡張?
※構造体渡し、戻値:構造体ポインタ
標準lib struct tm *localtime(const time_t *ttp); tm代入
- errno_t localtime_s(struct tm *tsp, const time_t *ttp); MS拡張
- struct tm *localtime_r(const time_t *ttp, struct tm *tsp); linux拡張?
※構造体渡し、戻値:構造体ポインタ
標準lib clock_t clock(void); プロセッサ time
標準lib time_t time(time_t *ttp); システム日時
※精度に違い有り
標準lib double difftime(time_t time2, time_t time1); time2 - time1
標準lib time_t mktime(struct tm *tsp); tm ---> time_t
標準lib size_t strftime(char *s, size_t mln, const char *fm, struct tm *tsp);整形出力
※時刻の差 ※構造体->time_t変換 ※指定フォーマット整形出力
※GMT=グリニッジ標準時 ※***_r -> linux 拡張の模様 ※***_s -> MS拡張? ※*ttp -> time_t value ※*tsp -> struct tm ※*fm -> format ※mel -> numberOfElements
※MS拡張? としている部分は、MSDN で ANSI準拠とあるが・・・(先行実装?)内容非保証。
※***_s() MSDN より引用。一部表記が異なる。

strftime(), wcsftime() 整形子
format 整形子 表示内容 表示形式と値
%y, %Y 年(year) 0-99 or 0-9999
%b, %B 月[省略,完全] Jan~, January 1-12, 1月-12月
%m 月(month) 1-12(注:VC?0-11)
%d 日(day) 1-31
%H, %I 時(hour) 24(0-23) / 12(1-12)
%M 分(minute) 0-59
%S 秒(second) 0-59
%p 午前・午後 AM / PM 午前 / 午後
%a, %A 曜日[省略,完全] Mon~, Monday~ 月~ , 月曜日~
%w 曜日の通番 0-6 (Sun=0 ~)
%c 日付と時刻 DD/YY/ HH:MM:SS
%x 標準日付表記 MM/DD/YY YYYY/MM/DD
%X 標準時間表記 HH:MM:SS
%j 1/1->経過日数 1-366
%U, %W 週の通番(注) 0-53
%Z time zone 「・・・東京・・・」とか
%% パーセント表示 %
※整形子と呼ぶか不明。

▲上へ [ 編集 ]

構造体 tm と構造体メンバ
構造体 tm は time.h で宣言され、以下の構造体メンバを持つ。
struct tm {
   // --- 時刻関連メンバ --------------------------------
   int tm_sec;   // 秒 0-60(閏秒考慮)
   int tm_min;   // 分 0-59
   int tm_hour;  // 時 0-23
   // --- 日付関連メンバ --------------------------------
   int tm_mday;  // 日 1-31
   int tm_mon;   // 月 0-11(注:1月からの通算月数)
   int tm_year;  // 年 1900年から通算年数(0なら1900年)
   // --- その他のメンバ --------------------------------
   int tm_wday;  // 日曜〜土曜まで 0-6
   int tm_yday;  // 1/1 からの通算日数
   int tm_isdst; // サマータイム有効>0、無効=0,それ以外は意味無し
};
※tm_mon tm_year の扱い注意。

▲上へ [ 編集 ]

「日付・時刻」取得、計算(サンプル)

※結論:_s は、MS 独自拡張。移植性皆無。
※結論2:worning は表示されても標準関数、又は C++ の代替関数を利用する。
※参考:_s は、「日付・日時」以外も多岐に渡り、30以上の MS独自関数が存在する。セキュリティ的に向上するが、標準化されている訳でなく、更にソース記述も大幅に異なる物と思われ移植性が困難と予想される。
※注:_s の使用は、使う側の判断である。

 C++ では、バッファオーバーラン関連の簸弱製関連(CRT?) のセキュリティ強化版?関数として MS では「_s」版、linux等では「_r」版関数があるらしく、特に「_s」付き関数仕様では、大きくソースが異なってしまうようである。

 これは「日付・時刻」に限ったことでなく、30以上の各種関数に修正バージョンがある模様。

 MS 専用コードを書きたくない、又は、デバッグ時の worning 大量発生で困る場合・・・
// warning C4996: のメッセージを強制的に無効化。
#pragma warning (disable:4996)    // (注:これも移植性ない)
 ・・・又は、
// 一般的に推奨されている記述。#pragma とどう違うかは不明。
#define _CRT_SECURE_NO_DEPRECATE  // sorce 先頭挿入(1 を指定する場合もあり)
 ・・・を入れると Worning が表示されない。

 一般的に #pragma は、コンパイラ固有の指示となる場合が多く、VC のみならず移植性を困難にする場合が多い。他に代替できない場合を除き、極力使用を控えたい記述である。

C++ での日付と時刻を取得する


C++ sample ***_s() への修正版
※asctime() ctime() gmtime() localtime() -> ***_s()
#include <iostream>
#include <time.h>     // 日付・時刻関連
using namespace std;

void main() {
   errno_t   err_t;                    // (追加)
   time_t    now, gmt_t, jp_t;
   struct tm gmtTime;                  // struct tm *gmtTime; (修正)
   struct tm jpTime;                   // struct tm *jpTime;  (修正)

   time(&now);

   // ■グリニッジ標準時:セキュリティ強化版 gmtime_s() 使用
   err_t = gmtime_s(&gmtTime, &now);   // gmtTime = gmtime(&now);   (修正)
   gmt_t = mktime(&gmtTime);           // gmt_t   = mktime(gmtTime);(修正)
   cout << "GMT = " << gmt_t << endl;

   // ■日本時間:セキュリティ強化版 localtime_s() 使用
   err_t = localtime_s(&jpTime, &now); // jpTime = localtime(&now); (修正)
   jp_t  = mktime(&jpTime);            // jp_t   = mktime(jpTime);  (修正)
   cout << "jp  = " << jp_t << endl;

   printf("GMT-JP 時間差(秒):%-12.2f \n", float(difftime(gmt_t, jp_t)));
}
※セキュリティ強化版使用は、(これほど)ソース全体の修正が必要になる。
※***_s() の記述は ANSI準拠?らしいが、VC++ 以外見受けられず、移植性に甚だ疑問。

▲上へ [ 編集 ]

C言語の場合


sample 時刻差を計算する
※グリニッジ標準時と日本時間の差を求める。
#include <iostream>
//#include <stdio.h>
#include <time.h>
using namespace std;

void main() {
   time_t    nowDateTime, gmt_t, jp_t;
   struct tm *gmtTime;
   struct tm *localTime;

   time(&nowDateTime);                  // 現在の日付と時刻を取得する

   gmtTime   = gmtime(&nowDateTime);    // グリニッジ標準時(GMT)
   gmt_t = mktime(gmtTime);
   cout << "GMT = " << gmt_t << endl;
   localTime = localtime(&nowDateTime); // 日本時間
   jp_t  = mktime(localTime);
   cout << "jp  = " << jp_t << endl;

   printf("GMT-JP 時間差(秒):%-12.2f \n", float(difftime(gmt_t, jp_t)));
}
※面倒なので cpp でテスト。difftime() は Wornint 出ず。
sample 実行結果
GMT = 1213595259
jp  = 1213627659
GMT-JP 時間差(秒):-32400.00   // = 9時間差
続行するには何かキーを押してください . . .

[ 編集 ]

▲上へ

sample 書式付き文字列へ変換
#include <iostream>
//#include <stdio.h>
#include <time.h>
#include <locale.h>  // 何故かなくても...
#define MAX_LEN 25

void main() {
   // setlocale(LC_ALL, "japanese"); // 何故か "ja" 不可。""=system(ja)
   char s_date[MAX_LEN], s_time[MAX_LEN];
   time_t    nowDateTime;
   struct tm *localTime;
   time(&nowDateTime);
   localTime = localtime(&nowDateTime);
   // 書式設定
   strftime(s_date,MAX_LEN,"%y.%B.%d (%a) ", localTime);
   strftime(s_time,MAX_LEN,"%H:%M:%S",       localTime);
   printf("%s %s \n", s_date, s_time);
}
※iostream なら locale.h なくても動くようである。stdio.h -> locale.h 必須。(この場合でも何故か"ja"不可)

▲上へ

sample 定型文字列へ変換
※asctime(), ctime(), mktime(), localtime() 使用
//#include <iostream>
#include <stdio.h>
#include <time.h>

void main() {
   time_t nowDateTime;
   struct tm *localTime;
   // 日時の取得と構造体への代入
   time(&nowDateTime);
   localTime = localtime(&nowDateTime);
   // 定型書式文字列へ変換
   printf("1)asctime = %s", asctime(localTime));  // 1),2),3) ともに
   printf("2)ctime   = %s", ctime(&nowDateTime)); // 実行した・・・
   printf("nowDateTime = %ld \n",nowDateTime);
   bk = mktime(localTime);                        // 構造体->time_t型
   printf("bk          = %ld \n",bk);
   printf("3)ctime2  = %s", ctime(&bk));          // 結果は同じ
}
※cpp iostream -> worning. asctime_s, ctime_s, localtime_s 推奨表示. mktime -> worning 出ず。
sample 実行結果表示
1)asctime = Mon Jun 16 18:27:52 2008 // (\n)
2)ctime   = Mon Jun 16 18:27:52 2008 // (\n)
nowDateTime = 1213608472
bk          = 1213608472
3)ctime2  = Mon Jun 16 18:27:52 2008 // (\n)
続行するには何かキーを押してください . . .

[ 編集 ]

▲上へ

sample 処理時間の計測
※clock() 使用
//#include <iostream>
#include <stdio.h>
#include <time.h>

void main() {
   clock_t  start, end;
   start = clock(); // <------------ 計測開始
   for(int i=0; i<65535 ;i++) {
      printf("i=%d \n",i);
   }
   end = clock();   // <------------ 計測終了
   printf("処理時間(秒):%-12.4f \n", (float(end-start)/CLOCKS_PER_SEC));
}
※cpp iostream でも worning 出ず。
※cast の仕方に注意。

▲上へ

sample GMT/jp 時間表示
※localtime(), gmtime(), time() 使用。
//#include <iostream>
#include <stdio.h>
#include <time.h>

void prnDateTime(struct tm* local) {
   char *weekday[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
   // または、 char weekday[][4] = { "Sun", ・・・ ,"Sat" }; でも可
   printf("%02d:%02d:%02d "
               , local->tm_hour          // hour
               , local->tm_min           // min
               , local->tm_sec           // sec
   );
   printf("%4d/%02d/%02d (%s) \n"
               , local->tm_year + 1900   // year + 1900
               , local->tm_mon  + 1      // mon  + 1
               , local->tm_mday          // day
               , weekday[local->tm_wday] // week
   );
}

void main() {
   time_t    nowDateTime;
   struct tm *gmtTime;
   struct tm *localTime;

   time(&nowDateTime);                  // 現在の日付と時刻を取得する

   gmtTime   = gmtime(&nowDateTime);    // グリニッジ標準時(GMT)
   prnDateTime(gmtTime);                // GMT 表示
   localTime = localtime(&nowDateTime); // 日本時間
   prnDateTime(localTime);              // jp 表示
}
※cpp #include <iostream> では、gmtime localtime -> worning

▲上へ

リンク


内部リンク


外部リンク


  • 現在ありません

▲上へ
2008年06月17日(火) 11:02:55 Modified by cafeboy1




スマートフォン版で見る