visual studio compile c++ c time

c++ - studio - visual c ubuntu



Convertir Windows Filetime a segundo en Unix/Linux (9)

Tengo un archivo de rastreo que cada tiempo de transacción representa en formato de tiempo de archivo de Windows. Estos números de tiempo son algo como esto:

  • 128166372003061629
  • 128166372016382155
  • 128166372026382245

¿Podría por favor avisarme si hay alguna biblioteca C / C ++ en Unix / Linux para extraer el tiempo real (especialmente el segundo) de estos números? ¿Puedo escribir mi propia función de extracción?


(Descubrí que no puedo ingresar un código legible en un comentario, así que ...)

Tenga en cuenta que Windows puede representar tiempos fuera del rango de los tiempos de época de POSIX y, por lo tanto, una rutina de conversión debería devolver una indicación de "fuera de rango" según corresponda. El método más simple es:

... (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;


Básicamente, esta es la misma solución, excepto que esta codifica correctamente los números negativos de Ldap y corta los últimos 7 dígitos antes de la conversión.

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


El tipo de FILETIME es el número de incrementos de 100 ns desde enero 1 1601.

Para convertir esto en un tiempo unix puede usar lo siguiente.

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

luego puede usar las funciones ctime para manipularlo.


La solución que divide y agrega no funcionará correctamente con el horario de verano.

Aquí hay un fragmento que funciona, pero es para 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; }


Nueva respuesta para la vieja pregunta.

Usando <chrono> C ++ 11 más esta biblioteca gratuita de código abierto:

https://github.com/HowardHinnant/date

Uno puede convertir fácilmente estas marcas de tiempo a std::chrono::system_clock::time_point , y también puede convertir estas marcas de tiempo a un formato legible por humanos en el calendario gregoriano:

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

Para mí esto da como resultado:

2007-02-22 17:00:00.306162 2007-02-22 17:00:01.638215 2007-02-22 17:00:02.638224

En Windows, puede omitir el floor y obtener el último dígito decimal de precisión:

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

Con las optimizaciones (sys_days{1970_y/jan/1} - sys_days{1601_y/jan/1}) se traducirá en el tiempo de compilación a los days{134774} que se convertirá en tiempo de compilación a cualquier unidad que sea. -expresión requiere (segundos, 100 nanosegundos, lo que sea). En pocas palabras: esto es muy legible y muy eficiente.


Si alguien necesita convertirlo en MySQL.

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



También aquí hay una manera pura de hacerlo.

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

Aquí está el resultado de ambos métodos en mi ventana inmediata:

(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


es bastante simple: la época de las ventanas comienza 1601-01-01T00: 00: 00Z. Son 11644473600 segundos antes de la época de UNIX / Linux (1970-01-01T00: 00: 00Z). Las marcas de Windows están en 100 nanosegundos. Por lo tanto, una función para obtener segundos de la época de UNIX será la siguiente:

#define WINDOWS_TICK 10000000 #define SEC_TO_UNIX_EPOCH 11644473600LL unsigned WindowsTickToUnixSeconds(long long windowsTicks) { return (unsigned)(windowsTicks / WINDOWS_TICK - SEC_TO_UNIX_EPOCH); }