Converting a SYSTEMTIME to a std::string in C++

A short recipe outlining how to output a SYSTEMTIME value as a std::string.

The example format will be “YYYY-MM-DD HH:MM:SS.MMM”

I specifically wanted to include milliseconds.

In this example I employ three possible techniques:

1. MFC CString
2. std::ostringstream
3. sprintf

Example code listing shown:

#include <windows.h>
#include <atlstr.h>
#include <iostream>
#include <sstream>
#include <iomanip>

int main()
{
	SYSTEMTIME st, lt;
    
    GetSystemTime(&st);
    std::string strMessage;

	// Output a given SYSTEMTIME in the format "
    
	// 1. Using CString
	CString cstrMessage;
	
	cstrMessage.Format( "%d-%02d-%02d %02d:%02d:%02d.%03d", 
					    st.wYear,
		                st.wMonth, 
					    st.wDay, 					   
					    st.wHour, 
					    st.wMinute, 
					    st.wSecond,
					    st.wMilliseconds );

	strMessage = cstrMessage;
	std::cout << "System time = " << strMessage << std::endl;

	// 2. Formating using ostringstream
	std::ostringstream ossMessage;

	ossMessage << st.wYear   << "-"
		       << std::setw( 2 ) << std::setfill( '0' ) << st.wMonth  << "-"
			   << std::setw( 2 ) << std::setfill( '0' ) << st.wDay    << " "					   
			   << std::setw( 2 ) << std::setfill( '0' ) << st.wHour   << ":"
			   << std::setw( 2 ) << std::setfill( '0' ) << st.wMinute << ":" 
			   << std::setw( 2 ) << std::setfill( '0' ) << st.wSecond << "." 
			   << std::setw( 3 ) << std::setfill( '0' ) << st.wMilliseconds;

	strMessage = ossMessage.str();
	std::cout << "System time = " << strMessage << std::endl;

	// 3. sprintf
	char buffer[ 256 ];
	sprintf( buffer,
		     "%d-%02d-%02d %02d:%02d:%02d.%03d", 
			 st.wYear,
			 st.wMonth, 
			 st.wDay, 					   
			 st.wHour, 
			 st.wMinute, 
			 st.wSecond,
			 st.wMilliseconds );

	strMessage = buffer;
	std::cout << "System time = " << strMessage << std::endl;

	return 0;
}

All three techniques giving exactly the same output as shown:

SystemTime

Here is another example whereby I take a SYSTEMTIME as input and output it to a stream in a given date/time format such as “Mon Oct 13 22:21:12 2014”. I create a class called TimeFormat which is constructed from the format string and SYSTEMTIME, and outputs the desired output time format via an overloaded insertion () operator that can recognize an ostream object on the left and a TimeFormat object on the right. The overloaded TimeFormat so it can access the private data within the TimeFormatobject:

friend std::ostream& operator <<( std::ostream&, TimeFormat const & );

Full code listing as follows:

#include <iostream>
#include <iterator>
#include <string>
#include <ctime>
#include <locale>
#include <Windows.h>

const std::string TIME_PATTERN = "%a %b %d %H:%M:%S %Y";

class TimeFormat
{
public:

    TimeFormat(const std::string& strFormat, const SYSTEMTIME& stSystemDate) :
         m_strFormat( strFormat ),
         m_stSystemDate( stSystemDate ) {}

    friend std::ostream& operator <<( std::ostream&, TimeFormat const & );

private:
    std::string m_strFormat;
	SYSTEMTIME m_stSystemDate;
};

std::ostream& operator <<( std::ostream& os, TimeFormat const& format )
{
	std::ostream::sentry s(os);

    if ( s )
    {
		std::tm tmSystemDate;     
		tmSystemDate.tm_sec  = format.m_stSystemDate.wSecond;
		tmSystemDate.tm_min  = format.m_stSystemDate.wMinute;
		tmSystemDate.tm_hour = format.m_stSystemDate.wHour;
		tmSystemDate.tm_mday = format.m_stSystemDate.wDay;
		tmSystemDate.tm_mon  = format.m_stSystemDate.wMonth - 1;
		tmSystemDate.tm_year = format.m_stSystemDate.wYear - 1900;
		tmSystemDate.tm_isdst = -1;

		std::time_t t = std::mktime( &tmSystemDate );    
        std::tm const* tm = std::localtime(&t);
        std::ostreambuf_iterator<char> output( os );
        std::use_facet<std::time_put<char>>(os.getloc()).put( output,
														      os,
															  os.fill(),
															  tm,
															  &format.m_strFormat[0],
															  &format.m_strFormat[0] + format.m_strFormat.size() );

    }

    os.width( 0 );
    return os;
}

int main()
{
	SYSTEMTIME stSystemDate;
	GetSystemTime( &stSystemDate );
	std::cout << TimeFormat( TIME_PATTERN, stSystemDate );
}

Which will give the following output:

systemtime2

Leave a Reply