PortableTimeFunctions

提供:やる気向上作戦
移動: 案内, 検索

WindowsLinuxPortability


gmtime, ctime等のスレッドセーフティ

Visual C++では、マルチスレッド版Cランタイムをリンクすると、gmtime, localtime等がスレッドセーフになる。 ただし、スレッド作成・終了に_beginthread(), _endthread()を使わなければ、メモリリークが発生する。CreateThread()はだめ。

gmtime()が常に同じアドレスを返すような環境では、やや迂遠だが、こんな感じで可能。

struct tm* gmtime_r(__time64_t t, struct tm* result)
{
FILETIME ft;
SYSTEMTIME st;
unsigned __int64 originoffset;
unsigned __int64 adjustedtime;
 
// time_t の紀元(1970年1月1日)をFILETIMEに変換
memset(&st, 0, sizeof(st));
st.wYear = 1970;
st.wMonth = 1;
st.wDay = 1;
 
SystemTimeToFileTime(&st, &ft);
memcpy(&originoffset, &ft, sizeof(ft));
// FILETIMEは100ns単位なので、10^7で割って秒に直す
originoffset /= 10000000;
 
// t に originoffset値を足したものを、再度FILETIMEに上書き
adjustedtime = (unsigned __int64)(t + originoffset) * 10000000;
memcpy(&ft, &adjustedtime, sizeof(ft));
 
// さらにSYSTEMTIMEに変換
FileTimeToSystemTime(&ft, &st);
 
// tmに入れる
memset(result, 0, sizeof(struct tm));
result->tm_sec = (int)(st.wSecond);
result->tm_min = (int)(st.wMinute);
result->tm_hour = (int)(st.wHour);
result->tm_mday = (int)(st.wDay);
result->tm_mon = (int)(st.wMonth - 1); // SYSTEMTIMEの月は1から始まる
result->tm_year = (int)(st.wYear - 1900); // SYSTEMTIMEの年は西暦そのもの
result->tm_wday = (int)(st.wDayOfWeek);
result->tm_yday = 0; // 適当
result->tm_isdst = -1; // 適当
 
return result;
}
個人用ツール