Convert Windows Filetime to second in Unix/Linux

2019-01-05 03:51发布

I have a trace file that each transaction time represented in Windows filetime format. These time numbers are something like this:

  • 128166372003061629
  • 128166372016382155
  • 128166372026382245

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 ? May I write my own extraction function ?

标签: c++ c time
9条回答
混吃等死
2楼-- · 2019-01-05 03:57

If somebody need convert it in MySQL

SELECT timestamp, 
       FROM_UNIXTIME(ROUND((((timestamp) / CAST(10000000 AS UNSIGNED INTEGER))) 
         - CAST(11644473600 AS UNSIGNED INTEGER),0)) 
       AS Converted FROM events  LIMIT 100
查看更多
够拽才男人
3楼-- · 2019-01-05 04:06

FILETIME type is is the number 100 ns increments since January 1 1601.

To convert this into a unix time_t you can use the following.

#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.

查看更多
欢心
4楼-- · 2019-01-05 04:07

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.

查看更多
趁早两清
5楼-- · 2019-01-05 04:07

Also here's a pure C#ian way to do it.

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

Here's the result of both methods in my immediate 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
查看更多
Melony?
6楼-- · 2019-01-05 04:09

New answer for old question.

Using C++11's <chrono> plus this free, open-source library:

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:

#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:

    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). Bottom line: This is both very readable and very efficient.

查看更多
Evening l夕情丶
7楼-- · 2019-01-05 04:17

it's quite simple: the windows epoch starts 1601-01-01T00:00:00Z. It's 11644473600 seconds before the UNIX/Linux epoch (1970-01-01T00:00:00Z). The Windows ticks are in 100 nanoseconds. Thus, a function to get seconds from the UNIX epoch will be as follows:

#define WINDOWS_TICK 10000000
#define SEC_TO_UNIX_EPOCH 11644473600LL

unsigned WindowsTickToUnixSeconds(long long windowsTicks)
{
     return (unsigned)(windowsTicks / WINDOWS_TICK - SEC_TO_UNIX_EPOCH);
}
查看更多
登录 后发表回答