2008-11-26 2 views
32

Есть ли хорошая эквивалентная реализация strptime(), доступная для Windows? К сожалению, эта функция POSIX недоступна.strptime() эквивалент в Windows?

Open Group description of strptime - Резюме: он преобразует текстовую строку, такую ​​как "MM-DD-YYYY HH:MM:SS" в tm struct, противоположное strftime().

+1

Это поможет, если вы добавите описание strptime, поэтому мне не нужно это делать в google :) – JaredPar 2008-11-26 19:21:52

ответ

20

Версия с открытым исходным кодом (BSD лицензии) strptime() можно найти здесь: http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/time/strptime.c?rev=HEAD

Вам нужно добавить следующее заявление, чтобы использовать его:

char *strptime(const char * __restrict, const char * __restrict, struct tm * __restrict); 
14

Это делает работу :

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

Заметим, однако, что входная строка YYYY-MM-DD

+2

+1 для указания кросс-платформенного решения. – stinky472 2010-06-29 03:24:04

28

Если вы не хотите портировать любой кода или осуждаете ваш проект, чтобы повысить, вы можете сделать это:

  1. разобрать дату, используя sscanf
  2. затем скопировать целые числа в struct tm (вычесть 1 из месяц и 1900 от года - месяцы и годы 0-11 начнется в 1900 году)
  3. наконец, использовать mktime, чтобы получить UTC эпохи целое число

Только не забудьте установить isdst член O f struct tm - -1, иначе у вас будут проблемы с летним временем.

+3

Обратите внимание, что `mktime` работает с датами в диапазоне от 1970 до 2038, но вы можете использовать [` _mktime64`] (http://msdn.microsoft.com/en-us/library/d1y53h2a%28v=vs.80 % 29.aspx), который работает с датами в диапазоне 1970 ~ 3000 :) – LihO 2012-12-07 17:15:10

+1

Иногда имеет смысл заполнить `isdst` своим текущим значением, вы можете получить его с помощью` localtime (& current_time) -> tm_isdst; `, где` current_time `Текущее время в формате` time_t`, возвращаемое `time (& current_time)`. – user 2014-10-19 08:46:10

-3

Один из вариантов заключается в использовании GetSystemTime и отправки информации о времени функции, которая анализирует ее в соответствии с вашим форматом, используя vsnprintf_s. В приведенном ниже примере есть одна функция, которая создает временную строку с миллисекундной точностью . Затем он посылает строку в функцию, которая форматирует его в соответствии с требуемым форматом:

#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); 
} 
+0

У вас есть вещи назад. Вопрос заключается в том, чтобы попросить преобразовать ** строковое представление ** в `struct tm`, в то время как вы представили (неудовлетворительную) реализацию [strftime] (https://msdn.microsoft.com/en-us /library/fe06s4ak.aspx). – IInspectable 2015-06-16 14:36:59

11

Предполагая, что вы используете Visual Studio 2015 или выше, вы можете использовать это как капля в замену 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()); 
} 

Просто имейте в виду, что для кросс-платформенных приложений std::get_time не был реализован до GCC 5.1, поэтому переключение на вызов std::get_time напрямую не может быть вариантом.

Смежные вопросы