c++ strptime()在Windows上是否等效?

ubbxdtey  于 2023-10-20  发布在  Windows
关注(0)|答案(8)|浏览(230)

是否有一个很好的strptime()的等效实现可用于Windows?不幸的是,这个POSIX函数似乎不可用。
Open Group description of strptime-摘要:它将文本字符串(如"MM-DD-YYYY HH:MM:SS")转换为tm struct,与strftime()相反。

sqougxex

sqougxex1#

如果你不想移植任何代码或谴责你的项目,你可以这样做:
1.使用sscanf解析日期
1.然后将整数复制到struct tm中(从月减去1,从年减去1900--月是0-11,年从1900开始)
1.最后,使用mktime获取UTC历元整数
只需记住将struct tmisdst成员设置为-1,否则您将遇到夏令时问题。

vuktfyat

vuktfyat2#

假设你使用的是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可能不是一个选择。

yzuktlbb

yzuktlbb3#

strptime()的开源版本(BSD许可证)可以在这里找到: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);
uklbhaso

uklbhaso4#

这样做的工作:

#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

enyaitl3

enyaitl35#

这是一个支持复制粘贴的the answer @amwinter posted的C示例,尽管我没有使用sscanf()-*scanf()函数家族太反常了,无法进行强大的解析:
(标题和错误检查被省略,以保持示例足够短,以防止创建垂直滚动条)

// format will be YYYYmmddHHMMSSZ
    const char *notAfter = getNotAfterStringFromX509Cert( x509 );
    struct tm notAfterTm = { 0 };

#ifdef _WIN32
    char buffer[ 8 ];

    memset( buffer, 0, sizeof( buffer ) );
    strncpy( buffer, notAfter, 4 );
    notAfterTm.tm_year = strtol( buffer, NULL, 10 ) - 1900;

    memset( buffer, 0, sizeof( buffer ) );
    strncpy( buffer, notAfter + 4, 2 );
    notAfterTm.tm_mon = strtol( buffer, NULL, 10 ) - 1;

    memset( buffer, 0, sizeof( buffer ) );
    strncpy( buffer, notAfter + 6, 2 );
    notAfterTm.tm_mday = strtol( buffer, NULL, 10 );

    memset( buffer, 0, sizeof( buffer ) );
    strncpy( buffer, notAfter + 8, 2 );
    notAfterTm.tm_hour = strtol( buffer, NULL, 10 );

    memset( buffer, 0, sizeof( buffer ) );
    strncpy( buffer, notAfter + 10, 2 );
    notAfterTm.tm_min = strtol( buffer, NULL, 10 );

    memset( buffer, 0, sizeof( buffer ) );
    strncpy( buffer, notAfter + 12, 2 );
    notAfterTm.tm_sec = strtol( buffer, NULL, 10 );

    time_t result = mktime( &notAfterTm );

这是一个非常简单的例子,输入字符串的格式是完全已知的,因此非常容易解析。

dwbf0jvd

dwbf0jvd6#

令我惊讶的是,如果不是难以置信的话,经过至少50年的数字数据处理,似乎仍然没有一个可接受的解决方案,为'strptime()'方法是可用的。
以下特性描述了应实现的可接受特性:

  • 时区信息集成
  • 可移植代码(最好使用ANSI C)
  • 线程安全
  • 不依赖其他库

非常有用的附加功能是:

  • 语言支持
  • 用于分析字符串而不需要格式字符串的选项
  • 格式字符串和函数参数与标准C 'strftime'定义兼容(尽可能)

以上提出的解决方案都没有实现前四个特点,尽管我认为它们是合理的。使用标准C++库可能会使'strptime'函数过时,但对我来说,这个库非常混乱,不容易使用。
出于这些原因,我设计了以下两个实现,它们彼此一致,并提供了所有上述功能。

  • LibOb_strftime()
  • LibOb_strptime()

它们发布在github上的一个名为
strptime-for-Windows-Linux
这两个函数都由两个文件(LibOb_strptime.h和LibOb_strptime.c)提供。
唯一的“成本”是传输时区和语言数据的附加指针参数,但如果仅使用常规功能就足够了,则可以将它们全部设置为0。这些函数故意不使用系统的“本地化”,这在文档中有解释。
对于C++程序员来说,cTime类与这个“strptime”实现密切相关,可能会感兴趣。

elcex8rz

elcex8rz7#

一种替代方法是使用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);
}
bihw5rsg

bihw5rsg8#

https://github.com/p-j-miller/date-time上有一个用于windows的strptime()版本。同一个位置包括一个匹配的strftime()函数和一个全面的测试程序。如果您需要创建在两个操作系统上都能工作的代码,这也适用于Linux。

相关问题