New answer to old question. This answer traffics through the C++11/14 <chrono>
library instead of C's tm
or boost::date_time
. Otherwise it is very similar to the existing answers. It requires this free, open-source library for the parsing and formatting.
#include "tz.h"
#include <iostream>
#include <locale>
#include <sstream>
int
main()
{
auto date1 = 20111201;
std::stringstream stream;
stream.exceptions(std::ios::failbit);
stream << date1;
std::chrono::system_clock::time_point tp;
date::parse(stream, "%Y%m%d", tp);
auto str = date::format("%d%b%Y", tp);
auto& ct = std::use_facet<std::ctype<char>>(std::locale::classic());
ct.toupper(&str.front(), &str.back()+1);
std::cout << str << '\n';
}
I've included stream.exceptions(std::ios::failbit);
to noisily detect invalid "integer dates". And I've included old C++98 code to convert the string to uppercase (the locale
dance at the end).
01DEC2011
One of the advantages of using a modern C++ date/time library is the ease with which changes can be made. For example, what if now you need to parse the timestamp not with day-precision, but with millisecond precision? Here is how that might be done:
auto date1 = 20111201093357.275L;
std::stringstream stream;
stream.exceptions(std::ios::failbit);
stream << std::fixed << date1;
std::chrono::system_clock::time_point tp;
date::parse(stream, "%Y%m%d%H%M%S", tp);
auto str = date::format("%d%b%Y %T", tp);
auto& ct = std::use_facet<std::ctype<char>>(std::locale::classic());
ct.toupper(&str.front(), &str.back()+1);
std::cout << str << '\n';
which outputs:
01DEC2011 09:33:57.275000
Or perhaps these timestamps are known to originate from Chatham Island off the coast of New Zealand and you need them in UTC. Just add one line after the parse
:
tp = date::locate_zone("Pacific/Chatham")->to_sys(tp);
And now the output is:
30NOV2011 19:48:57.275000
Taking into account arbitrary timezones and subsecond precision is currently beyond the capabilities of all other C++ libraries.