Is there a builtin alternative to std::put_time for GCC <5?
Asked Answered
T

3

14

I'm stuck on GCC4.8 for the time being. I want to print out the current time as something other than seconds. If put_time worked, my code would be something simple, like this:

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

Without put_time, I'd have to access the elements of c_time manually and do all the formatting manually, which would be a pain in the a** and is something I'm much rather avoid if possible. Note that this does not mean that I never want to interact with C in any way, even indirectly -- I'd just like to avoid coding in C directly if possible.

However, I can't find any alternatives to std::put_time, aside from strftime, which I'd like to avoid because it requires almost double the lines of code and is a lot harder to read, at least for me. Also, this is C++, not C, so I'd like to steer clear of C functions whenever possible.

Am I missing something? Is there a builtin alternative to std::put_time which works under GCC 4.8?

Note that it doesn't have to work in exactly the same way -- if it, say, printed it directly to the output, rather than being a stream manipulator, that would be perfectly fine too, as would a function which returned a std::string containing the formatted time.

I've done a good bit of Googling and found <chrono>, but that doesn't work because it doesn't have anything to format the time automatically. I'd still have to do it manually, and I'm pretty sure it would be more work, since I'd have to parse the number of seconds since the epoch into a year, month, day, etc.

Thrippence answered 24/5, 2016 at 18:57 Comment(0)
B
14

There are no functions other than put_time for the outputing of time provided in the chrono or the iomanip library.

The ctime library does provide: strftime, ctime, and asctime.

Since http://stackoverflow.com does not permit questions about finding 3rd party libraries, I'm going to guess that you're just asking for someone to direct you on the use of strftime? std::put_time(c_time, "[%T%z %F] ") could be written in the format:

char foo[24];

if(0 < strftime(foo, sizeof(foo), "[%T%z %F] ", c_time)) cout << foo << endl;
Bareheaded answered 24/5, 2016 at 19:47 Comment(1)
I was asking if there were any built-in libraries to do it, which is on-topic. You've answered that. Also, Stack Overflow allows you to say, "This is a library which solves your problem"; it's only asking specifically for offsite resources that's banned. In other words, if you know of a third-party library, you can mention it; that just wasn't what I was asking for. Thanks for your help!Thrippence
K
6

Also, this is C++, not C, so I'd like to steer clear of C functions whenever possible.

That's a pretty silly mindset. put_time uses std::strftime underneath the hood.

ext.manip#10

Returns: An object of unspecified type ... where the function f is defined as:

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;

  /* ... */
}

And time_put's definition is in locale.time.put.virtuals#1:

Effects: Formats the contents of the parameter t into characters placed on the output sequence s. Formatting is controlled by the parameters format and modifier, interpreted identically as the format specifiers in the string argument to the standard library function strftime() ...

Kingbolt answered 24/5, 2016 at 19:10 Comment(0)
P
1

Another solution is to rip off the definition of std::put_time from a later GCC's header, since the underlying facility std::time_put is still present in GCC 4.8 and the definition is not very complicated. This is copied from GCC 7.4's <iomanip> and edited for clarity:

#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
Plagiary answered 27/8, 2020 at 13:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.