在Unix / Linux中将Windows Filetime转换为第二个

我有一个跟踪文件,每个交易时间以Windows文件时间格式表示。 这些时间的数字是这样的:

  • 128166372003061629
  • 128166372016382155
  • 128166372026382245

如果在Unix / Linux中有任何C / C ++库来从这些数字中提取实际时间(特别是第二个),请告诉我一下吗? 我可以写我自己的提取function吗?

这很简单:窗口时代开始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); } 

FILETIMEtypes是自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函数来操纵它。

(我发现我不能在评论中input可读的代码,所以…)

请注意,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 ,并获得精度的最后十进制数字:

  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 

通过优化,子expression式(sys_days{1970_y/jan/1} - sys_days{1601_y/jan/1})将在编译时翻译为days{134774} ,这将进一步编译时转换为任何单元满expression需要(秒,100纳秒,无论)。 底线:这是非常可读和非常有效的。

假设你问的是FILETIME结构,那么FileTimeToSystemTime就是你想要的,你可以从它产生的SYSTEMTIME结构中获得秒数。

夏时制的解决scheme将无法正常工作。

这是一个可以工作的代码片段,但它是用于Windows的。

 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; } 

这里基本上是相同的解决scheme,除了这个从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); } 

这里还有一个纯C#的方法来做到这一点。

 (Int32)(DateTime.FromFileTimeUtc(129477880901875000).Subtract(new DateTime(1970, 1, 1))).TotalSeconds; 

下面是我的直接窗口中的两种方法的结果:

 (Int32)(DateTime.FromFileTimeUtc(long.Parse(strValue)).Subtract(new DateTime(1970, 1, 1))).TotalSeconds; 1303314490 (int)(long.Parse(strValue.Substring(0, strValue.Length - 7)) - 11644473600) 1303314490 DateTime.FromFileTimeUtc(long.Parse(strValue)) {2011-04-20 3:48:10 PM} Date: {2011-04-20 12:00:00 AM} Day: 20 DayOfWeek: Wednesday DayOfYear: 110 Hour: 15 InternalKind: 4611686018427387904 InternalTicks: 634389112901875000 Kind: Utc Millisecond: 187 Minute: 48 Month: 4 Second: 10 Ticks: 634389112901875000 TimeOfDay: {System.TimeSpan} Year: 2011 dateData: 5246075131329262904 

如果有人需要在MySQL中进行转换

 SELECT timestamp, FROM_UNIXTIME(ROUND((((timestamp) / CAST(10000000 AS UNSIGNED INTEGER))) - CAST(11644473600 AS UNSIGNED INTEGER),0)) AS Converted FROM events LIMIT 100