各トランザクション時間がWindowsファイル時間形式で表されるトレースファイルがあります。これらの時間数は次のようなものです。
Unix/Linuxにこれらの数値から実際の時間(特に秒)を抽出するC/C++ライブラリがあるかどうかを教えてください。独自の抽出関数を作成できますか?
それは非常に簡単です:Windows Epochは1601-01-01T00:00:00Zから始まります。 UNIX/Linuxエポック(1970-01-01T00:00:00Z)の11644473600秒前です。 Windowsのティックは100ナノ秒です。したがって、UNIXエポックから秒を取得する関数は次のようになります。
#define WINDOWS_TICK 10000000
#define SEC_TO_UNIX_Epoch 11644473600LL
unsigned WindowsTickToUnixSeconds(long long windowsTicks)
{
return (unsigned)(windowsTicks / WINDOWS_TICK - SEC_TO_UNIX_Epoch);
}
FILETIMEタイプは、1601年1月1日以降の100 nsの増分値です。
これをunix time_tに変換するには、次を使用できます。
#define TICKS_PER_SECOND 10000000
#define Epoch_DIFFERENCE 11644473600LL
time_t convertWindowsTimeToUnixTime(long long int input){
long long int temp;
temp = input / TICKS_PER_SECOND; //convert from 100ns intervals to seconds;
temp = temp - Epoch_DIFFERENCE; //subtract number of seconds between epochs
return (time_t) temp;
}
その後、ctime関数を使用して操作できます。
(読みやすいコードをコメントに入力できないことがわかったので...)
WindowsはPOSIXエポック時間の範囲外の時間を表すことができるため、変換ルーチンは必要に応じて「範囲外」の指示を返す必要があることに注意してください。最も簡単な方法は次のとおりです。
... (as above)
long long secs;
time_t t;
secs = (windowsTicks / WINDOWS_TICK - SEC_TO_UNIX_Epoch);
t = (time_t) secs;
if (secs != (long long) t) // checks for truncation/overflow/underflow
return (time_t) -1; // value not representable as a POSIX time
return t;
古い質問に対する新しい回答。
C++ 11の<chrono>
に加えて、この無料のオープンソースライブラリを使用すると:
https://github.com/HowardHinnant/date
これらのタイムスタンプをstd::chrono::system_clock::time_point
に非常に簡単に変換できます。また、これらのタイムスタンプをグレゴリオ暦の人間が読める形式に変換できます。
#include "date.h"
#include <iostream>
std::chrono::system_clock::time_point
from_windows_filetime(long long t)
{
using namespace std::chrono;
using namespace date;
using wfs = duration<long long, std::ratio<1, 10'000'000>>;
return system_clock::time_point{floor<system_clock::duration>(wfs{t} -
(sys_days{1970_y/jan/1} - sys_days{1601_y/jan/1}))};
}
int
main()
{
using namespace date;
std::cout << from_windows_filetime(128166372003061629) << '\n';
std::cout << from_windows_filetime(128166372016382155) << '\n';
std::cout << from_windows_filetime(128166372026382245) << '\n';
}
私にとってこの出力:
2007-02-22 17:00:00.306162
2007-02-22 17:00:01.638215
2007-02-22 17:00:02.638224
Windowsでは、実際にfloor
をスキップして、精度の最後の10進数を取得できます。
return system_clock::time_point{wfs{t} -
(sys_days{1970_y/jan/1} - sys_days{1601_y/jan/1})};
2007-02-22 17:00:00.3061629
2007-02-22 17:00:01.6382155
2007-02-22 17:00:02.6382245
最適化をオンにすると、サブ式(sys_days{1970_y/jan/1} - sys_days{1601_y/jan/1})
はコンパイル時にdays{134774}
に変換され、完全な式が必要とする単位(秒、100ナノ秒など)にさらにコンパイル時に変換されます。結論:これは非常に読みやすく、非常に効率的です。
分割して追加するソリューションは、夏時間では正しく機能しません。
動作するスニペットを次に示しますが、これはウィンドウ用です。
time_t FileTime_to_POSIX(FILETIME ft)
{
FILETIME localFileTime;
FileTimeToLocalFileTime(&ft,&localFileTime);
SYSTEMTIME sysTime;
FileTimeToSystemTime(&localFileTime,&sysTime);
struct tm tmtime = {0};
tmtime.tm_year = sysTime.wYear - 1900;
tmtime.tm_mon = sysTime.wMonth - 1;
tmtime.tm_mday = sysTime.wDay;
tmtime.tm_hour = sysTime.wHour;
tmtime.tm_min = sysTime.wMinute;
tmtime.tm_sec = sysTime.wSecond;
tmtime.tm_wday = 0;
tmtime.tm_yday = 0;
tmtime.tm_isdst = -1;
time_t ret = mktime(&tmtime);
return ret;
}
これは、これがLdapからの負の数を適切にエンコードし、変換前に最後の7桁を切り捨てる以外は、本質的に同じソリューションです。
public static int LdapValueAsUnixTimestamp(SearchResult searchResult, string fieldName)
{
var strValue = LdapValue(searchResult, fieldName);
if (strValue == "0") return 0;
if (strValue == "9223372036854775807") return -1;
return (int)(long.Parse(strValue.Substring(0, strValue.Length - 7)) - 11644473600);
}
[〜#〜] filetime [〜#〜] 構造について尋ねていると仮定すると、 FileTimeToSystemTime はあなたが望むことをします、あなたは [〜#〜] systemtime [〜#〜] 構造体から秒を得ることができます生成します。