Timedate.c

[目次 | 関数 | マクロ]

目次

関数一覧

マクロ一覧


   1|/************************************************************************
   2|  1. <<< 時間/日付 (TimeDate) >>> 
   3|【補足】
   4| 2. <<< 標準ライブラリの簡易ヘルプ >>>
   5| 標準ライブラリ time.h には、以下の関数があります。
   6|・time_t  time( time_t* n );  // システムの時刻を n に格納する
   7|・double  difftime( time_t finish, time_t start );  // 時刻差を返す
   8|・struct tm*  localtime( time_t* );  // 日、時などを参照する(構造体から)
   9|・ファイルのタイムスタンプは、FileX_getUpdate 関数から取得できます。
  10|*************************************************************************/
  11|
  12|#include  "mixer_precomp.h"
  13|
  14|#define  STDLIBS_INCLUDE
  15|#define  STDLIBS_INCLUDE_STRING_H
  16|#define  STDLIBS_INCLUDE_STDIO_H
  17|#define  STDLIBS_INCLUDE
  18|#include  <locale.h>
  19|#include  <math.h>
  20|#include  <time.h>
  21|#ifdef  USES_MXP_AUTOINC
  22| #include  <timedate.ah>  /* Auto include header, Look at mixer-... folder */
  23|#endif
  24|
  25|void  TimeDate_setLocaleByOS();
  26|void  TimeDate_wait001_forV830_O1();
  27|
  28|/* 3. <<< [TimeDate_MonthStr] >>> */
  29|char*  TimeDate_MonthStr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  30|                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  31|
  32|
  33| 
  34|/*-------------------------------------------------------------------------*/
  35|/* 4. <<< ◆基本操作 >>> */ 
  36|/*-------------------------------------------------------------------------*/
  37|
  38|
  39| 
  40|/************************************************************************
  41|  5. <<< [TimeDate_set] 日時を m へ設定する >>> 
  42|【引数】
  43|  ・time_t*  m;   設定を格納する変数へのアドレス
  44|  ・int  year;       年(西暦)[1970〜2036]
  45|  ・int  month;      月 [1〜12]
  46|  ・int  day;        日 [1〜31]
  47|  ・int  hour;       時 [0〜23]
  48|  ・int  min;        分 [0〜59]
  49|  ・int  sec;        秒 [0〜59]
  50|  ・int  返り値;     0=正常, 1=範囲外
  51|【補足】
  52|・西暦 1970 年 1 月 1 日 0 時から 2036 年 2 月 5 日 0 時まで設定できます。
  53|・指定した日や時などが範囲外の場合、自動的に計算して正規化します。
  54|*************************************************************************/
  55|int  TimeDate_set( time_t* m, int year, int month, int day,
  56|  int hour, int min, int sec )
  57|{
  58|  struct tm  xmas;
  59|  time_t  holiday;
  60|
  61|  TimeDate_setLocaleByOS();
  62|  xmas.tm_sec = sec;
  63|  xmas.tm_min = min;
  64|  xmas.tm_hour = hour;
  65|  xmas.tm_mday = day;
  66|  xmas.tm_mon = month - 1;
  67|  xmas.tm_year = year - 1900;
  68|  xmas.tm_isdst = -1;
  69|
  70|  holiday = mktime( &xmas );
  71|  if ( holiday == (time_t)-1 )  return  1;
  72|
  73|  *m = holiday;
  74|  return  0;
  75|}
  76|
  77|
  78| 
  79|/************************************************************************
  80|  6. <<< [TimeDate_getOldest] 最も古い日付を取得する >>> 
  81|【補足】
  82|・time_t 型で表現できる最も古い日付の値を取得します。
  83|【内部補足】
  84|・time_t は、約 136年、つまり 2106年まで表現できます。
  85|(Visual C++4.0 のヘルプ・時間管理より)
  86| メ モ   Microsoft C/C++ 7.0 以外のすべての Microsoft C/C++ バージョン
  87| および Microsoft Visual C++ のすべてのバージョンでは、time 関数が返す
  88| 現在時刻は、1970 年 1 月 1 日の午前 0 時 0 分 0 秒から経過した秒数です。
  89| Microsoft C/C++ 7.0 の time 関数は、1899 年 12 月 31 日の午前 0 時 0 分
  90| 0 秒からの経過秒数を現在時刻として返していました。
  91|*************************************************************************/
  92|void  TimeDate_getOldest( time_t* time )
  93|{
  94|  *time = (time_t)0;
  95|}
  96|
  97|
  98| 
  99|/************************************************************************
 100|  7. <<< [TimeDate_cmp] 2つの日付とそれぞれの存在から比較する >>> 
 101|【補足】
 102|・ファイルの存在と更新日時に対する返り値の関係は次の通りです。
 103|   [fNameA] [更新日時] [fNameB] [返り値]  [fNameA]
 104|     存在       ==       存在      0     TimeDate_Equal(同一)
 105|     存在       >        存在      1     TimeDate_Update (更新)
 106|     存在       <        存在     -1     TimeDate_Resume(復旧)
 107|     存在                なし      2     TimeDate_Create(生成)
 108|     なし                存在     -2     TimeDate_Delete(削除)
 109|     なし                なし      0     TimeDate_Equal(同一)
 110|・existA == false の場合、timeA は無視されます。timeB も同様です。
 111|・存在を考慮しない場合、標準ライブラリの difftime 関数を用います。
 112|・引数にファイル名を指定する場合、FileX_cmpTime 関数を用います。
 113|*************************************************************************/
 114|int  TimeDate_cmp( time_t* timeA, bool existA, time_t* timeB, bool existB )
 115|{
 116|  if ( ! existA ) {
 117|    if ( ! existB )  return  0;
 118|    else             return -2;
 119|  }
 120|  else {
 121|    if ( ! existB )  return  2;
 122|    else {
 123|      double  diff = difftime( *timeA, *timeB );
 124|      if ( diff == 0.0 )  return  0;
 125|      else if ( diff > 0.0 )  return  1;
 126|      else  return  -1;
 127|    }
 128|  }
 129|}
 130|
 131|
 132| 
 133|/************************************************************************
 134|  8. <<< [TimeDate_setFromDouble] double 型経過秒数から日時を取得する >>> 
 135|【補足】
 136|・月と年は取得できません。time_t 型または struct tm 型の
 137|  年と月を直接参照して計算してください。
 138|*************************************************************************/
 139|void  TimeDate_setFromDouble( struct tm* t, double diff )
 140|{
 141|  double  diff2;
 142|
 143|  TimeDate_setLocaleByOS();
 144|
 145|  diff2 = floor(diff / 60);  t->tm_sec = (int)(diff - diff2 * 60);
 146|  diff  = floor(diff2/ 60);  t->tm_min = (int)(diff2 - diff * 60);
 147|  diff2 = floor(diff / 24);  t->tm_hour = (int)(diff - diff2 * 24);
 148|  t->tm_mday = (int)diff2;
 149|  t->tm_mon = 0;
 150|  t->tm_year = 0;
 151|  t->tm_isdst = -1;
 152|}
 153|
 154|
 155| 
 156|/*-------------------------------------------------------------------------*/
 157|/* 9. <<< ◆文字列変換 >>> */ 
 158|/*-------------------------------------------------------------------------*/
 159|
 160|
 161| 
 162|/************************************************************************
 163|  10. <<< [TimeDate_getStr] 指定した日時を短い形式で取得する >>> 
 164|【引数】
 165|  ・char* str;        現在の時刻を格納するバッファのアドレス
 166|  ・int str_sizeof;   str のメモリサイズ
 167|【補足】
 168|・OS の地域設定の「短い形式」を取得します。
 169|  例=98/03/23 19:44:02(日本の場合)
 170|*************************************************************************/
 171|char*  TimeDate_getStr( time_t* time, char* str, int str_sizeof )
 172|{
 173|  struct tm* t2;
 174|
 175|  TimeDate_setLocaleByOS();
 176|  t2 = localtime( time );
 177|  #ifdef _CHECKER
 178|    if ( t2 == NULL )  error(); /* time が不正な値 */
 179|  #endif
 180|  strftime( str, str_sizeof, "%c", t2 );
 181|
 182|  return  str;
 183|}
 184|
 185|
 186| 
 187|/************************************************************************
 188|  11. <<< [TimeDate_getStrF] 指定した日時を指定した形式で取得する >>> 
 189|【引数】
 190|  ・const char* fmt;  日時の書式(TimeDate_fmt 書式、後記)
 191|  ・char* str;        現在の時刻を格納するバッファのアドレス
 192|  ・int str_sizeof;   str のメモリサイズ
 193|【補足】
 194|・USES_STRX が定義されていないと、拡張書式を指定できません。
 195|*************************************************************************/
 196|char* TimeDate_getStrF( time_t* time, const char* fmt, char* str,
 197|  int str_sizeof )
 198|{
 199|  struct tm* time2;
 200|  static char  fmtX[256];
 201|
 202|  ASSERT( str_sizeof <= sizeof(fmtX) );
 203|
 204|  TimeDate_setLocaleByOS();
 205|  time2 = localtime( time );
 206|
 207|  #ifdef USES_STRX
 208|    strcpy( fmtX, fmt );
 209|    StrX_rep( fmtX, sizeof(fmtX), "%n",
 210|      TimeDate_MonthStr[time2->tm_mon] );
 211|    strftime( str, str_sizeof, fmtX, time2 );
 212|  #else
 213|    strftime( str, str_sizeof, fmt, time2 );
 214|  #endif
 215|
 216|  return  str;
 217|}
 218|
 219|
 220| 
 221|/************************************************************************
 222|  12. <<< [TimeDate_getNowStr] 現在の日時を短い形式で取得する >>> 
 223|【補足】
 224|・OS の地域設定の「短い形式」を取得します。
 225|  例=98/03/23 19:44:02(日本の場合)
 226|・返される文字列は、変更しないでください。
 227|・ファイルに保存することに使う場合は、TimeDate_saveStr を用います。
 228|*************************************************************************/
 229|char*  TimeDate_getNowStr()
 230|{
 231|  time_t  t;
 232|  struct tm* t2;
 233|  static char  buf[30];  /* 文字列領域を内部に持っています */
 234|
 235|  TimeDate_setLocaleByOS();
 236|  time( &t );
 237|  t2 = localtime( &t );
 238|  strftime( buf, sizeof(buf), "%c", t2 );
 239|
 240|  return  buf;
 241|}
 242|
 243|
 244| 
 245|/************************************************************************
 246|  13. <<< [TimeDate_getNowStrF] 現在の日時を指定した書式で取得する >>> 
 247|【引数】
 248|  ・const char* fmt;  日時の書式(TimeDate_fmt 書式、後記)
 249|【補足】
 250|・返される文字列は、変更しないでください。
 251|*************************************************************************/
 252|char*  TimeDate_getNowStrF( char* fmt )
 253|{
 254|  time_t  t;
 255|  struct tm * t2;
 256|  static char  buf[80];  /* 文字列領域を内部に持っています */
 257|
 258|  TimeDate_setLocaleByOS();
 259|  time( &t );
 260|  t2 = localtime( &t );
 261|  strftime( buf, sizeof(buf), fmt, t2 );
 262|
 263|  return  buf;
 264|}
 265|
 266|
 267| 
 268|/************************************************************************
 269|  14. <<< [TimeDate_getCompileStrF_imp] コンパイルした日時を指定した書式で取得する >>> 
 270|【引数】
 271| ・char* __date__;  __DATE__ 組み込みマクロ
 272|  ・char* __time__;  __TIME__ 組み込みマクロ
 273|  ・char*  fmt;      日時の書式(TimeDate_fmt 書式、後記)
 274|【補足】
 275|・TimeDate_getCompileStrF マクロの実装部です。
 276|*************************************************************************/
 277|char*  TimeDate_getCompileStrF_imp( char* __date__, char* __time__,
 278|  char* fmt )
 279|{
 280|  #define  STR_SIZE  100
 281|  char**   pMonth;
 282|  time_t   tim;
 283|  int  y,m,d,hh,mm,ss;
 284|  static char  str[STR_SIZE];
 285|
 286|  TimeDate_setLocaleByOS();
 287|
 288|  /* __DATE__ を解析する */
 289|  sscanf( __date__, "%s %d %d", str, &d, &y );
 290|  pMonth = TimeDate_MonthStr;
 291|  for ( m = 1; m <= 12; m++ ) {
 292|    if ( strcmp( *pMonth, str ) == 0 )  break;
 293|    pMonth ++;
 294|  }
 295|
 296|  /* __TIME__ を解析する */
 297|  sscanf( __time__, "%d:%d:%d", &hh, &mm, &ss );
 298|
 299|  /* 文字列を作る */
 300|  TimeDate_set( &tim, y, m, d, hh, mm, ss );
 301|  TimeDate_getStrF( &tim, fmt, str, sizeof(str) );
 302|
 303|  return  str;
 304|}
 305|
 306|
 307| 
 308|/************************************************************************
 309|  15. <<< [TimeDate_saveStr] 日時情報をテキスト形式にする >>> 
 310|【機能】
 311|・テキストファイルに保存できる形式の文字列を str に格納します。
 312|【補足】
 313|・str のメモリサイズは TimeDate_loadBuf_size 以上にしてください。
 314|・このテキスト形式は、TimeDate_loadStr で日時情報を取得することができます。
 315|・西暦 1970 年 1 月 1 日 0 時から 2036 年 2 月 5 日 0 時まで設定できます。
 316|  (2000 年問題に対応)
 317|*************************************************************************/
 318|char*  TimeDate_saveStr( time_t* t, char* str )
 319|{
 320|  TimeDate_getStrF( t, "%Y/%m/%d-%H:%M:%S", str, TimeDate_loadBuf_size );
 321|  return  str;
 322|}
 323|
 324|
 325| 
 326|/************************************************************************
 327|  16. <<< [TimeDate_loadStr] 日時情報をテキスト形式から取得する >>> 
 328|【機能】
 329|・テキストファイルに保存できる形式の文字列を str に格納します。
 330|【引数】
 331|  ・int  返り値;     0=正常, 1=範囲外, 2=書式ミス
 332|【補足】
 333|・TimeDate_saveStr で取得したテキスト形式から、日時情報を取得することが
 334|  できます。
 335|・ユーザにテキスト形式を入力させる場合、"%Y/%m/%d-%H:%M:%S" という
 336|  TimeDate_fmt 書式(年は4桁、他は頭に0の付いた2桁または1桁)に従う
 337|  よう、表示してください。区切り文字('/','-',':')は、数字以外なら
 338|  何でも(空白、タブ、改行、コンマ、他でも)構いませんが、1バイトに
 339|  してください。
 340|・西暦 1970 年 1 月 1 日 0 時から 2036 年 2 月 5 日 0 時まで設定できます。
 341|  (2000 年問題に対応)
 342|*************************************************************************/
 343|#ifdef USES_STRX
 344|int  TimeDate_loadStr( time_t* t, const char* str )
 345|{
 346|  int  i;
 347|  static int  n[6];
 348|  const char*  p;
 349|
 350|  for ( i = 0; i < 6; i++ ) {
 351|    p = StrX_scanInt( str, &n[i] );
 352|    if ( p == '\0' )  return  2;
 353|    str = p + 1;
 354|  }
 355|
 356|  return  TimeDate_set( t, n[0], n[1], n[2], n[3], n[4], n[5] );
 357|}
 358|#endif /* USES_STRX */
 359|
 360|
 361| 
 362|/*-------------------------------------------------------------------------*/
 363|/* 17. <<< ◆待ち >>> */ 
 364|/*-------------------------------------------------------------------------*/
 365|
 366|
 367| 
 368|/************************************************************************
 369|  18. <<< [TimeDate_wait] msec ミリ秒経ったらこの関数から抜ける >>> 
 370|*************************************************************************/
 371|void  TimeDate_wait( int msec )
 372|{
 373|  int  i;
 374|  msec /= 10;
 375|  for ( i = 0; i < msec; i++ )
 376|    TimeDate_wait001_forV830_O1();
 377|}
 378|
 379|
 380| 
 381|/*-------------------------------------------------------------------------*/
 382|/* 19. <<< ◆内部用 >>> */ 
 383|/*-------------------------------------------------------------------------*/
 384|
 385|
 386| 
 387|/************************************************************************
 388|  20. <<< [TimeDate_wait001_forV830_O1] 0.01 秒経ったらこの関数から抜ける (for V830) >>> 
 389|  Optimize=-O1
 390|*************************************************************************/
 391|static void  TimeDate_wait001_forV830_O1()
 392|{
 393|  int  i;
 394|  for ( i = 0; i < 4060; i++ )
 395|     { i=i*3; i=i/3; }
 396|}
 397|
 398|
 399| 
 400|/************************************************************************
 401|  21. <<< [TimeDate_setLocaleByOS] 地域設定を OS の設定に合わせる >>> 
 402|*************************************************************************/
 403|static void  TimeDate_setLocaleByOS()
 404|{
 405|  static bool  bFirst = true;
 406|
 407|  if ( bFirst ) {
 408|    setlocale( LC_ALL, "" );
 409|    _tzset();
 410|    bFirst = false;
 411|  }
 412|}
 413|
 414|
 415| 
 416|/*-------------------------------------------------------------------------*/
 417|/* 22. <<< ◆資料 >>> */ 
 418|/*-------------------------------------------------------------------------*/
 419|
 420|
 421| 
 422|/************************************************************************
 423|  23. <<< [TimeDate_fmt] 日時の書式 >>> 
 424|
 425|(Microsoft Developer studio の Info Viewer の strftime 関数より抜粋・修正)
 426| format は、1 以上のコードで構成されます。
 427| printf 関数と同じように、書式コードの前にはパーセント (%) 記号を
 428| 付けます。% 記号が先頭に付かない文字は、変更されずにそのまま string
 429| にコピーされます。strftime 関数の出力書式は現在のロケールの LC_TIME
 430| カテゴリに影響されます。LC_TIME の詳細については、setlocale 関数を
 431| 参照してください。以下に、strftime 関数の書式指定コードを示します。
 432| ただし、strftime に対応していない拡張書式もいっしょに示しています。
 433|
 434| 例:
 435|   ・Jan.1.1998 ... "%n.%#d.%Y"
 436|   ・98.07.04 ...   "%y.%m.%d"
 437|   ・23:09:59 ...   "%H.%M.%S"
 438|
 439| 一覧:
 440| コード 意味                                      必要バイト数
 441| -------------------------------------------------------------------
 442| %c   ロケールに応じた日付と時間の表現
 443|
 444| %x   現在のロケールの日付表示
 445| %Y   10 進数で表す 4 桁の西暦                       4
 446| %y   10 進数で表す西暦の下 2 桁 (00〜99)            2
 447| %m   10 進数で表す月 (01〜12)                       2
 448| %b   月の省略名 (ex:Jan)                            3
 449| %B   月の正式名 (ex:September)                      9
 450| %n   %b の強制英語(%b では地域によって変わる)(拡張書式)
 451| %d   10 進数で表す日付 (01〜31)                     2
 452| %a   曜日の省略名 (ex:Sun)                          3
 453| %A   曜日の正式名 (ex:Wednesday)                    9
 454| %w   10 進数で表す曜日。日曜日を 0 とする (0〜6)。  1
 455|
 456| %X   現在のロケールの時刻表示
 457| %H   24 時間表記の時間 (00〜23)                     2
 458| %I   12 時間表記の時間 (01〜12)                     2
 459| %p   現在のロケールの AM/PM                         2
 460| %z、%Z                                              3
 461|      時間帯の名前またはその省略名。時間帯が
 462|      わからない場合には文字を入れない。(ex:Jst,Dst)
 463| %M   10 進数で表す分 (00〜59)                       2
 464| %S   10 進数で表す秒 (00〜59)                       2
 465|
 466| %j   10 進数で表す年頭からの日数 (001〜366)         3
 467| %U   10 進数で表す週の通し番号                      2
 468|      日曜日を週の最初の日とする (00〜51)。
 469| %W   10 進数で表す週の通し番号                      2
 470|      月曜日を週の最初の日とする (00〜51)。
 471| %%   パーセント記号
 472|
 473|
 474| 24. <<< # フラグ >>>
 475|
 476| printf 関数と同じように、# フラグを書式指定コードの前に付けられます。
 477| その場合、書式指定コードの意味は以下のようになります。
 478|
 479| %#c
 480|   現在のロケールに応じた日付と時刻の長い表現。
 481|   "Tuesday、March 14、1995、12:41:29" など。
 482| %#x
 483|   現在のロケールに応じた長い日付表現。"Tuesday、March 14、1995" など。
 484| %#d、%#H、%#I、%#j、%#m、%#M、%#S、%#U、%#w、%#W、%#y、%#Y
 485|   先行ゼロがあれば削除。
 486|
 487|
 488| 25. <<< 地域設定「ロケール」 >>>
 489|
 490| TimeDate コンポーネントは、OS の設定した地域に、自動的に設定します。
 491| 日時の書式に影響します。
 492|*************************************************************************/
 493| 
 494|