c++ - library - strptime() equivalente en Windows?
time functions in c (5)
¿Hay una buena implementación equivalente de strptime()
disponible para Windows? Lamentablemente, esta función POSIX no parece estar disponible.
Open Group description of strptime - summary: convierte una cadena de texto como "MM-DD-YYYY HH:MM:SS"
en una tm struct
, lo opuesto a strftime()
.
Esto hace el trabajo:
#include "stdafx.h"
#include "boost/date_time/posix_time/posix_time.hpp"
using namespace boost::posix_time;
int _tmain(int argc, _TCHAR* argv[])
{
std::string ts("2002-01-20 23:59:59.000");
ptime t(time_from_string(ts));
tm pt_tm = to_tm( t );
Observe, sin embargo, que la cadena de entrada es AAAA-MM-DD
Si no desea portar ningún código o condenar su proyecto para aumentar, puede hacer esto:
- analizar la fecha usando
sscanf
- luego copie los enteros en una
struct tm
(reste 1 del mes y 1900 del año - los meses son 0-11 y los años comienzan en 1900) - finalmente, use
mktime
para obtener un entero de época UTC
Solo recuerde establecer el miembro isdst
de struct tm
en -1, de lo contrario tendrá problemas de ahorro de luz diurna.
Suponiendo que está usando Visual Studio 2015 o superior, puede usar esto como un reemplazo directo para strptime:
#include <time.h>
#include <iomanip>
#include <sstream>
extern "C" char* strptime(const char* s,
const char* f,
struct tm* tm) {
// Isn''t the C++ standard lib nice? std::get_time is defined such that its
// format parameters are the exact same as strptime. Of course, we have to
// create a string stream first, and imbue it with the current C locale, and
// we also have to make sure we return the right things if it fails, or
// if it succeeds, but this is still far simpler an implementation than any
// of the versions in any of the C standard libraries.
std::istringstream input(s);
input.imbue(std::locale(setlocale(LC_ALL, nullptr)));
input >> std::get_time(tm, f);
if (input.fail()) {
return nullptr;
}
return (char*)(s + input.tellg());
}
Solo tenga en cuenta que para las aplicaciones multiplataforma, std::get_time
no se implementó hasta GCC 5.1, por lo que cambiar a la llamada a std::get_time
directamente puede no ser una opción.
Una alternativa es usar GetSystemTime
y enviar la información de tiempo a una función que lo analiza de acuerdo con su formato usando vsnprintf_s
. En el siguiente ejemplo, hay una función que crea una cadena de tiempo con mili de precisión. A continuación, envía la cadena a una función que lo formatea de acuerdo con el formato deseado:
#include <string>
#include <cstdio>
#include <cstdarg>
#include <atlstr.h>
std::string FormatToISO8601 (const std::string FmtS, ...) {
CStringA BufferString;
try {
va_list VaList;
va_start (VaList, FmtS);
BufferString.FormatV (FmtS.c_str(), VaList);
} catch (...) {}
return std::string (BufferString);
}
void CreateISO8601String () {
SYSTEMTIME st;
GetSystemTime(&st);
std::string MyISO8601String = FormatToISO8601 ("%4u-%02u-%02uT%02u:%02u:%02u.%03u", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
}