25

I want to format a date/time to a string using boost.

Starting with the current date/time:

ptime now = second_clock::universal_time();

and ending up with a wstring containing the date/time in this format:

%Y%m%d_%H%M%S

Can you show me the code to achieve this? Thanks.

mackenir
  • 10,801
  • 16
  • 68
  • 100

2 Answers2

35

For whatever it is worth, here is the function that I wrote to do this:

#include "boost/date_time/posix_time/posix_time.hpp"
#include <iostream>
#include <sstream>

std::wstring FormatTime(boost::posix_time::ptime now)
{
  using namespace boost::posix_time;
  static std::locale loc(std::wcout.getloc(),
                         new wtime_facet(L"%Y%m%d_%H%M%S"));

  std::basic_stringstream<wchar_t> wss;
  wss.imbue(loc);
  wss << now;
  return wss.str();
}

int main() {
  using namespace boost::posix_time;
  ptime now = second_clock::universal_time();

  std::wstring ws(FormatTime(now));
  std::wcout << ws << std::endl;
  sleep(2);
  now = second_clock::universal_time();
  ws = FormatTime(now);
  std::wcout << ws << std::endl;

}

The output of this program was:

20111130_142732
20111130_142734

I found these links useful:

Community
  • 1
  • 1
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • I'm testing this now - could be the wstringstream needs a wtime_facet and that's where it was silently failing for me. – mackenir Feb 16 '11 at 18:30
  • 1
    That would work but note if you are going to use the same format for multiple dates, do not create the facet every time but create it once and then use it multiple times. The imbue itself is not expensive. – CashCow Feb 24 '11 at 17:09
  • 1
    Note you would do that by storing the locale object. – CashCow Feb 24 '11 at 17:21
  • Thanks, @CashCow. I made the changes you suggested. – Robᵩ Nov 30 '11 at 14:30
  • For using C++98 and C++0x, I've found that using `std::stringstream` is better since the template is different for `std::basic_stringstream`. –  Jun 19 '17 at 17:49
3
// create your date
boost::gregorian::date d(2009, 1, 7); 

// create your formatting
boost::gregorian::date_facet *df = new boost::gregorian::date_facet("%Y%m%d_%H%M%S"); 

// set your formatting
ostringstream is;
is.imbue(std::locale(is.getloc(), df));
is << d << endl;

// get string
cout << "output :" << is.str() << endl;
Validus Oculus
  • 2,756
  • 1
  • 25
  • 34
  • 16
    Guys, seriously. In C# I can write DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") and that's all! What the hell is wrong with C++ these days... – romanz Jan 09 '18 at 21:22
  • 5
    You sounded like my nephew in high school :) I am sure that the function you mentioned does something very similar to what I coded above. If you want better user interface, then you have to build an abstraction layer over the boost. The boost is designed to be flexible. Take a look to Poco C++ Libraries. They have very nice Java style interface which makes it very easy to code. So problem is not about C++ :) – Validus Oculus Feb 10 '18 at 18:36
  • Is there a way to get it into a string variable (i.e. std::string) rather than output it directly to the console? – Steve Smith Jan 15 '19 at 15:47
  • 1
    @romanz, then try using your approach when the user defined format is used instead of `yyyy-MM-dd HH:mm:ss`, and a specific time zone, language/locale, encoding, first day of week and months/day shortenings are to be applied. And you get the hell of formats supported by `DateTime`, which do not cover all the cases. – Aleksey F. Oct 05 '21 at 16:57
  • 1
    @SteveSmith `is.str()` returns a `std::string` – ThreeStarProgrammer57 Jul 26 '23 at 18:29