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|