[英]Convert Windows Filetime to second in Unix/Linux
I have a trace file that each transaction time represented in Windows filetime format.我有一个跟踪文件,每个事务时间以 Windows 文件时间格式表示。 These time numbers are something like this:
这些时间数字是这样的:
Would you please let me know if there are any C/C++ library in Unix/Linux to extract actual time (specially second) from these numbers?请让我知道 Unix/Linux 中是否有任何 C/C++ 库可以从这些数字中提取实际时间(特别是秒)? May I write my own extraction function?
我可以写我自己的提取 function 吗?
it's quite simple: the windows epoch starts 1601-01-01T00:00:00Z.这很简单:windows 纪元从 1601-01-01T00:00:00Z 开始。 It's 11644473600 seconds before the UNIX/Linux epoch (1970-01-01T00:00:00Z).
它比 UNIX/Linux 纪元 (1970-01-01T00:00:00Z) 早 11644473600 秒。 The Windows ticks are in 100 nanoseconds.
Windows 滴答声以 100 纳秒为单位。 Thus, a function to get seconds from the UNIX epoch will be as follows:
因此,从 UNIX 时期获得秒数的 function 将如下所示:
#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 type is is the number 100 ns increments since January 1 1601. FILETIME 类型是自 1601 年 1 月 1 日以来 100 ns 增量的数字。
To convert this into a unix time_t you can use the following.要将其转换为 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;
}
you may then use the ctime functions to manipulate it.然后,您可以使用 ctime 函数来操作它。
(I discovered I can't enter readable code in a comment, so...) (我发现我无法在评论中输入可读代码,所以......)
Note that Windows can represent times outside the range of POSIX epoch times, and thus a conversion routine should return an "out-of-range" indication as appropriate.请注意,Windows 可以表示超出 POSIX 纪元时间范围的时间,因此转换例程应酌情返回“超出范围”指示。 The simplest method is:
最简单的方法是:
... (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;
New answer for old question.老问题的新答案。
Using C++11's <chrono>
plus this free, open-source library:使用 C++11 的
<chrono>
加上这个免费的开源库:
https://github.com/HowardHinnant/date https://github.com/HowardHinnant/date
One can very easily convert these timestamps to std::chrono::system_clock::time_point
, and also convert these timestamps to human-readable format in the Gregorian calendar:可以很容易地将这些时间戳转换为
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';
}
For me this outputs:对我来说,这输出:
2007-02-22 17:00:00.306162
2007-02-22 17:00:01.638215
2007-02-22 17:00:02.638224
On Windows, you can actually skip the floor
, and get that last decimal digit of precision:在 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
With optimizations on, the sub-expression (sys_days{1970_y/jan/1} - sys_days{1601_y/jan/1})
will translate at compile time to days{134774}
which will further compile-time-convert to whatever units the full-expression requires (seconds, 100-nanoseconds, whatever).启用优化后,子表达式
(sys_days{1970_y/jan/1} - sys_days{1601_y/jan/1})
将在编译时转换为days{134774}
,这将进一步在编译时转换为完整的任何单位-expression 需要(秒、100 纳秒等)。 Bottom line: This is both very readable and very efficient.底线:这既可读又高效。
The solution that divides and adds will not work correctly with daylight savings.除法和加法的解决方案将无法在夏令时正常工作。
Here is a snippet that works, but it is for windows.这是一个有效的片段,但它适用于 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;
}
Here's essentially the same solution except this one encodes negative numbers from Ldap properly and lops off the last 7 digits before conversion.这里基本上是相同的解决方案,除了这个解决方案正确编码来自 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);
}
Assuming you are asking about the FILETIME Structure, then FileTimeToSystemTime does what you want, you can get the seconds from the SYSTEMTIME structure it produces.假设您要询问FILETIME结构,然后FileTimeToSystemTime执行您想要的操作,您可以从它产生的SYSTEMTIME结构中获取秒数。
Also here's a pure C#ian way to do it.这也是一种纯粹的 C#ian 方式。
(Int32)(DateTime.FromFileTimeUtc(129477880901875000).Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
Here's the result of both methods in my immediate window:这是我的即时 window 中两种方法的结果:
(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
If somebody need convert it in MySQL如果有人需要将其转换为 MySQL
SELECT timestamp,
FROM_UNIXTIME(ROUND((((timestamp) / CAST(10000000 AS UNSIGNED INTEGER)))
- CAST(11644473600 AS UNSIGNED INTEGER),0))
AS Converted FROM events LIMIT 100
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.