Unix/Linux에서 Windows 파일 시간을 두 번째로 변환
각 트랜잭션 시간이 Windows 파일 시간 형식으로 표시된 추적 파일이 있습니다.다음 시간 숫자는 다음과 같습니다.
- 128166372003061629
- 128166372016382155
- 128166372026382245
이 숫자들에서 실제 시간(특히 두 번째)을 추출할 수 있는 C/C++ 라이브러리가 유닉스/리눅스에 있는지 알려주시겠습니까?제가 직접 추출 기능을 써도 될까요?
매우 간단합니다. Windows 시대는 1601-01-01T00:00Z로 시작합니다.UNIX/Linux 시대(1970-01-01T00:00:00Z)보다 1,64473600초 전입니다.Windows 눈금은 100나노초입니다.따라서 UNIX epoch에서 초를 가져오는 함수는 다음과 같습니다.
#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월 11일 이후로 증가한 100ns 수입니다.
이를 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 epoch time 범위 밖의 시간을 나타낼 수 있으므로 변환 루틴은 적절한 "범위 외" 표시를 반환해야 합니다.가장 간단한 방법은 다음과 같습니다.
... (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
최적화가 설정된 경우 하위 표현식(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;
}
FILETIME Structure에 대해 질문한다고 가정하면 FileTime은SystemTime은 원하는 작업을 수행하기 위해 생성되는 SYSTEMTIME 구조에서 초를 얻을 수 있습니다.
여기에 기본적으로 동일한 솔루션이 있습니다. 단, 이 솔루션은 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);
}
MySQL에서 변환이 필요한 경우
SELECT timestamp,
FROM_UNIXTIME(ROUND((((timestamp) / CAST(10000000 AS UNSIGNED INTEGER)))
- CAST(11644473600 AS UNSIGNED INTEGER),0))
AS Converted FROM events LIMIT 100
또한 여기에 순수한 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
언급URL : https://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux
'programing' 카테고리의 다른 글
Firebase Auth를 사용할 때 앱이 충돌합니다. 이유: '기본 앱이 이미 구성되었습니다.' (0) | 2023.06.13 |
---|---|
Routing resources for Rails에서 :id 매개변수의 이름 변경 (0) | 2023.06.13 |
선택하면 UITableViewCell에서 높이 변경을 애니메이션화할 수 있습니까? (0) | 2023.06.13 |
Translate API를 사용하는 Python App Engine 앱에서 ImportError: No module name piclient.discovery라는 오류가 발생하는 이유는 무엇입니까? (0) | 2023.06.13 |
필드를 게으른 것으로 선언 (0) | 2023.06.13 |