是否有针对GCC< 5的std :: put_time的内置替代方案?

时间:2016-05-24 18:57:28

标签: c++ time formatting gcc4

我暂时停留在GCC4.8上。我想把当前时间打印成秒之外的东西。如果put_time有效,我的代码就会很简单,就像这样:

std::cout << std::setw(24) << std::put_time(c_time, "[%T%z %F] ");

如果没有put_time,我必须手动访问c_time的元素并手动执行所有格式化,这对a **来说是一种痛苦,而且我更喜欢尽可能避免。请注意, 意味着我从不想以任何方式与C进行交互,即使是间接的 - 我只是想尽可能避免直接使用C编码。

但是,除std::put_time之外,我找不到strftime的替代方法,我希望避免使用std::put_time,因为它需要几乎两倍的代码行并且更难阅读, 至少对于我来说。另外,这是C ++,而不是C,所以我想尽可能避开C函数。

我错过了什么吗?是否有std::string的内置替代方案可以在GCC 4.8下运行?

请注意,它不必以完全相同的方式工作 - 例如,如果它直接将其打印到输出,而不是作为流操作器,那也将完全正常,就像一个函数一样返回了包含格式化时间的new Array(105119296)

我已经做了很多谷歌搜索并找到<chrono>,但这不起作用,因为它没有任何自动格式化时间的东西。我仍然必须手动完成,我很确定它会更多工作,因为我必须解析自纪元以来的秒数到一年,一月,一天等等。

3 个答案:

答案 0 :(得分:8)

除了put_time之外,chronoiomanip库中提供的时间输出没有其他功能。

ctime库确实提供了:strftimectimeasctime

由于http://stackoverflow.com不允许有关找到3个 rd 派对图书馆的问题,我猜你只是要求有人指导你使用{{} 1}? strftime可以采用以下格式编写:

std::put_time(c_time, "[%T%z %F] ")

答案 1 :(得分:5)

  

此外,这是C ++,而不是C,所以我希望尽可能避免使用C函数。

这是一种非常愚蠢的心态。 put_time在引擎盖下使用std::strftime

ext.manip#10

  

返回:未指定类型的对象...其中函数f定义为:

template <class charT, class traits>
void f(basic_ios<charT, traits>& str, const struct tm* tmb, const charT* fmt) {
  /* ... */
  typedef time_put<charT, Iter> TimePut;

  /* ... */
}

time_put的定义位于locale.time.put.virtuals#1

  

效果:将参数t的内容格式化为输出序列s上的字符。格式化由   参数格式和修饰符,解释为格式相同   标准库函数的字符串参数中的说明符   strftime() ...

答案 2 :(得分:0)

另一种解决方案是从更高版本的GCC标头中剥离std::put_time的定义,因为基础设施std::time_put仍存在于GCC 4.8中,并且定义不是很复杂。这是从GCC 7.4的<iomanip>复制并为清楚起见进行编辑的:

#if __GNUC__ && __GNUC__ < 5
#include <ostream>  // std::basic_ostream
#include <ios>      // std::ios_base
#include <locale>   // std::use_facet, std::time_put
#include <iterator> // std::ostreambuf_iterator

template<typename CharT>
struct _put_time                   
{                                                                     
  const std::tm* time;
  const char *fmt;
};
    
template<typename CharT>
inline _put_time<CharT>
put_time(const std::tm* time, const CharT* fmt)
{ return { time, fmt }; }
  
template<typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits> &os, _put_time<CharT> f)
{   
  typedef typename std::ostreambuf_iterator<CharT, Traits> Iter;
  typedef std::time_put<CharT, Iter> TimePut;
      
  const CharT* const fmt_end = f.fmt + Traits::length(f.fmt);
  const TimePut& mp = std::use_facet<TimePut>(os.getloc());
    
  std::ios_base::iostate err = std::ios_base::goodbit;
  try {
    if (mp.put(Iter(os.rdbuf()), os, os.fill(), f.time, f.fmt, fmt_end).failed())
      err |= std::ios_base::badbit;
  }
  catch (...) {
    err |= std::ios_base::badbit;
  }  
   
  if (err)
    os.setstate(err);

  return os;
} 

#endif