Difference between revisions of "Boost local date time"

From DarkWiki
Jump to: navigation, search
(Created page with "Category:C++ Category:Boost Category:Example code This page demonstrates how to manipulate dates, times and time-zones in C++ using Boost. <syntaxhighlight lang="...")
 
(No difference)

Latest revision as of 06:50, 12 April 2016

This page demonstrates how to manipulate dates, times and time-zones in C++ using Boost.

#include <iostream>
#include "boost/date_time/local_time/local_time.hpp"

/*
	I've included this 'use' section to keep things clean. Normally, you shouldn't include
	the 'std' namespace like this - as it's huge. If you want to discover what's where, then
	just uncomment one of these at a time and the compilation errors will identify the
	locations of the classes & functions involved.
*/

using namespace std;
using namespace boost::gregorian;
using namespace boost::local_time;
using namespace boost::posix_time;

/*
	This will set the time component of the date to 00:00:00.
*/

local_date_time startOfDay(const local_date_time ldt) {
	local_date_time out( ldt.date() , hours( 0 ) + minutes( 0 ) , ldt.zone(), local_date_time::NOT_DATE_TIME_ON_ERROR );
	return out;
}

/*
	This will set the time component of the date to 23:59:59.
*/

local_date_time endOfDay(const local_date_time ldt) {
	local_date_time out( ldt.date() , hours( 23 ) + minutes( 59 ) + seconds( 59 ) , ldt.zone(), local_date_time::NOT_DATE_TIME_ON_ERROR );
	return out;
}

/*
	This is a simple formatting method that will output the date in a format fit for SOAP. The SOAP standards say that
	the timezone should always be UTC (as indicated by the 'Z'). You may note a little magical powder here: the core
	routines do not yet provide milliseconds, so we use the total milliseconds and then the modulo remainder.
*/

string formatSoap(const local_date_time ldt) {
	char buffer[ 25 ];
	ptime zulu = ldt.utc_time();
	sprintf( buffer , "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ" , (int) zulu.date().year() , (int) zulu.date().month() , (int) zulu.date().day(), (int) zulu.time_of_day().hours() , (int) zulu.time_of_day().minutes() , (int) zulu.time_of_day().seconds() , (int) ( ( (int) zulu.time_of_day().total_milliseconds() ) % 1000 ) );
	return buffer;
}

/*
	This demonstrates some common usage scenarios for the 'local_date_time' utility. While it is usual to store
	dates & times in UTC (or when mashalling/serialising them), arithmetic often requires the proper handling
	of time-zones. If you find yourself having to manually add/subtract TZ offsets, you've probably gone wrong.
*/

int main(int argc,char *argv[]) {

	/*
		Load the time-zone definitions.
	*/

	tz_database tz_db;
	tz_db.load_from_file( "date_time_zonespec.csv" );

	/*
		We will use two different time-zones. We look these up in the database we've just loaded. I've deliberately
		chosen two time-zones that are clearly not close to UTC (or GMT etc.).
	*/

	time_zone_ptr origin_tz = tz_db.time_zone_from_region("Australia/Sydney");
	time_zone_ptr destination_tz = tz_db.time_zone_from_region("America/New_York");
	time_zone_ptr utc_tz = tz_db.time_zone_from_region("UTC");

	/*
		We're going to walk forward through time using the 'analysis_date'. This will be
		initialised to the current time (i.e. now) in the 'origin time zone'. We will stop
		once we've moved more than 2 days into the future.

		Also note that I'm using the 'local_microsec_clock' clock to get the current time.
		This is because I want the milliseconds to be identfied.
	*/

	local_date_time analysis_date( local_microsec_clock::local_time( origin_tz ) );
	local_date_time analysis_date_end = analysis_date + days( 2 );

	/*
		We will keep looping until the analysis date goes past the end date.
	*/

	while( analysis_date < analysis_date_end ) {

		/*
			Given a date & time, we will display it in both time-zones. You may notice that the 'analysis_date' is already
			in the 'origin_tz'. When it is important that the date is presented in a particular time-zone, you should always
			be explicit and not rely on its default.
		*/

		cout << "DEMO 1 " << analysis_date.local_time_in( origin_tz ) << " (" << analysis_date.local_time_in( destination_tz ) << ")" << endl;

		/*
			This demonstrates setting the time in the time-zone of the date specified. A common mistake is to just set the
			time and use a 'ptime'
		*/

		cout << "DEMO 2 " << startOfDay( analysis_date ) << " - " << endOfDay( analysis_date ) << endl;

		/*
			This demonstrates setting the times as if the date were in particular time zone.
		*/

		cout << "DEMO 3 " << startOfDay( analysis_date.local_time_in( origin_tz ) ) << " - " << endOfDay( analysis_date.local_time_in( origin_tz ) ) << endl;
		cout << "DEMO 4 " << startOfDay( analysis_date.local_time_in( destination_tz ) ) << " - " << endOfDay( analysis_date.local_time_in( destination_tz ) ) << endl;

		/*
			Here, we take the analysis date, move to the 'origin' time-zone, set the time, and finally convert that result into its UTC equivalent.
		*/

		cout << "DEMO 5 " << startOfDay( analysis_date.local_time_in( origin_tz ) ).local_time_in( utc_tz ) << " - " << endOfDay( analysis_date.local_time_in( origin_tz ) ).local_time_in( utc_tz ) << endl;

		/*
			We will now output how long we have remaining. There is a bunch of ways a 'duration' can be presented, so here I show the default
			(which is of the form 00:00:00, in this case) and then how to obtain the number of seconds.
		*/

		time_duration left = analysis_date_end - analysis_date;
		cout << "DEMO 6 " << left << " remaining" << endl;
		cout << "DEMO 6 " << left.total_seconds() << " seconds remaining" << endl;

		/*
			We will now advance our analysis date by one hour and six minutes.
		*/

		analysis_date = analysis_date + hours( 1 ) + minutes( 6 );
	}

	cout << formatSoap( analysis_date.local_time_in( utc_tz ) ) << endl;

	return 0;
}

Formatting date times for output

string formatSoap(const local_date_time ldt) {
        char buffer[ 25 ];
        ptime zulu = ldt.utc_time();
        sprintf( buffer , "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ" , (int) zulu.date().year() , (int) zulu.date().month() , (int) zulu.date().day(), (int) zulu.time_of_day().hours() , (int) zulu.time_of_day().minutes() , (int) zulu.time_of_day().seconds() , (int) ( ( (int) zulu.time_of_day().total_milliseconds() ) % 1000 ) );
        return buffer;
}
string formatDateTime(const local_date_time ldt) {
        char buffer[ 35 ];
        int h = ldt.zone()->base_utc_offset().hours();
        int m = ldt.zone()->base_utc_offset().minutes();
        sprintf( buffer , "%04d-%02d-%02dT%02d:%02d:%02d.%03d%0+3d:%02d" , (int) ldt.date().year() , (int) ldt.date().month() , (int) ldt.date().day(), (int) ldt.time_of_day().hours() , (int) ldt.time_of_day().minutes() , (int) ldt.time_of_day().seconds() , (int) ( ( (int) ldt.time_of_day().total_milliseconds() ) % 1000 ) , h , m );
        return buffer;
}