Commit 1dacb529 authored by Axel Auweter's avatar Axel Auweter
Browse files

Add support for time input/output in local timezone (#31)

parent 9d874e82
...@@ -67,6 +67,16 @@ public: ...@@ -67,6 +67,16 @@ public:
*/ */
void setNow(void); void setNow(void);
/**
* @brief Convert from local time to UTC
*/
void convertFromLocal(void);
/**
* @brief Convert from UTC to local time
*/
void convertToLocal(void);
/** /**
* @brief Returns the raw time stamp value. * @brief Returns the raw time stamp value.
* @return The object's value as uint64_t. * @return The object's value as uint64_t.
......
...@@ -9,9 +9,13 @@ ...@@ -9,9 +9,13 @@
#include <cinttypes> #include <cinttypes>
#include "boost/date_time/posix_time/posix_time.hpp" #include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/date_time/local_time/local_time.hpp"
#include "boost/date_time/c_local_time_adjustor.hpp"
#include "timestamp.h" #include "timestamp.h"
/* Use this as our local to utc adjustor */
typedef boost::date_time::c_local_adjustor<boost::posix_time::ptime> local_adj;
/** /**
* This function parses a string and tries to do a best guess at the contained * This function parses a string and tries to do a best guess at the contained
...@@ -90,6 +94,49 @@ void DCDBTimeStamp::setNow(void) ...@@ -90,6 +94,49 @@ void DCDBTimeStamp::setNow(void)
raw = diff.total_nanoseconds(); raw = diff.total_nanoseconds();
} }
/**
*
*/
void DCDBTimeStamp::convertFromLocal()
{
/*
* Unfortunately BOOST c_local_adjustor doesn't support local-to-utc conversion.
* Therfore, we first check the offset of "raw" during utc-to-local conversion
* and then apply this offset in the other direction.
*/
/* Construct ptime object t from raw */
boost::posix_time::ptime t(boost::gregorian::date(1970,1,1));
t += boost::posix_time::nanoseconds(raw);
/* Convert t to UTC */
boost::posix_time::ptime t2 = local_adj::utc_to_local(t);
/* Check the difference of the two times */
boost::posix_time::time_duration diff = t - t2;
/* Write back adjusted value to raw */
raw += diff.total_nanoseconds();
}
/**
*
*/
void DCDBTimeStamp::convertToLocal()
{
/* Construct ptime object t from raw */
boost::posix_time::ptime t(boost::gregorian::date(1970,1,1));
t += boost::posix_time::nanoseconds(raw);
/* Convert t to Local */
t = local_adj::utc_to_local(t);
/* Write back to raw */
boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
boost::posix_time::time_duration diff = t - epoch;
raw = diff.total_nanoseconds();
}
/** /**
* *
*/ */
......
...@@ -21,7 +21,7 @@ void usage(void) ...@@ -21,7 +21,7 @@ void usage(void)
{ {
/* 0---------1---------2---------3---------4---------5---------6---------7--------- */ /* 0---------1---------2---------3---------4---------5---------6---------7--------- */
std::cout << "Usage:" << std::endl std::cout << "Usage:" << std::endl
<< "dcdbquery [-h <hostname>] [-r] <Sensor 1> [<Sensor 2> ...] <Start> <End>" << std::endl << "dcdbquery [-h <hostname>] [-r] [-l] <Sensor 1> [<Sensor 2> ...] <Start> <End>" << std::endl
<< "where" << std::endl << "where" << std::endl
<< " <hostname> - the name of the DB server" << std::endl << " <hostname> - the name of the DB server" << std::endl
<< " <Sensor n> - a public sensor name" << std::endl << " <Sensor n> - a public sensor name" << std::endl
...@@ -31,7 +31,9 @@ void usage(void) ...@@ -31,7 +31,9 @@ void usage(void)
<< "<Start> and <End> times should be supplied as 'yyyy-mm-dd hh:mm:ss' or unix" << std::endl << "<Start> and <End> times should be supplied as 'yyyy-mm-dd hh:mm:ss' or unix" << std::endl
<< "timestamps." << std::endl << "timestamps." << std::endl
<< "When the -r option is specified, timestamps will be reported in internal (raw)" << std::endl << "When the -r option is specified, timestamps will be reported in internal (raw)" << std::endl
<< "format (nanoseconds since epoch) insted of ISO human readable form." << std::endl; << "format (nanoseconds since epoch) insted of ISO human readable form." << std::endl
<< "When the -l option is specified, times for <Start>, <End>, and in the generated" << std::endl
<< "output will be interpreted / printed in the local time zone." << std::endl;
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
...@@ -46,7 +48,8 @@ int main(int argc, char* argv[]) ...@@ -46,7 +48,8 @@ int main(int argc, char* argv[])
int ret; int ret;
const char *host = "localhost"; const char *host = "localhost";
bool raw = false; bool raw = false;
while ((ret=getopt(argc, argv, "+h:r"))!=-1) { bool localtime = false;
while ((ret=getopt(argc, argv, "+h:rl"))!=-1) {
switch(ret) { switch(ret) {
case 'h': case 'h':
host = optarg; host = optarg;
...@@ -54,6 +57,9 @@ int main(int argc, char* argv[]) ...@@ -54,6 +57,9 @@ int main(int argc, char* argv[])
case 'r': case 'r':
raw = true; raw = true;
break; break;
case 'l':
localtime = true;
break;
default: default:
usage(); usage();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -65,6 +71,10 @@ int main(int argc, char* argv[]) ...@@ -65,6 +71,10 @@ int main(int argc, char* argv[])
try { try {
start = DCDBTimeStamp(argv[argc-2]); start = DCDBTimeStamp(argv[argc-2]);
end = DCDBTimeStamp(argv[argc-1]); end = DCDBTimeStamp(argv[argc-1]);
if (localtime) {
start.convertFromLocal();
end.convertFromLocal();
}
} }
catch (std::exception& e) { catch (std::exception& e) {
std::cout << "Wrong time format." << std::endl; std::cout << "Wrong time format." << std::endl;
...@@ -83,7 +93,7 @@ int main(int argc, char* argv[]) ...@@ -83,7 +93,7 @@ int main(int argc, char* argv[])
sensors.push_back(argv[arg]); sensors.push_back(argv[arg]);
} }
DCDBQuery::doQuery(host, sensors, start, end, raw); DCDBQuery::doQuery(host, sensors, start, end, raw, localtime);
return 0; return 0;
} }
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "casshelper.h" #include "casshelper.h"
/* Lovely spaghetti code coming up next. Be aware... */ /* Lovely spaghetti code coming up next. Be aware... */
void DCDBQuery::doQuery(const char* hostname, std::list<std::string> sensors, DCDBTimeStamp start, DCDBTimeStamp end, bool raw) void DCDBQuery::doQuery(const char* hostname, std::list<std::string> sensors, DCDBTimeStamp start, DCDBTimeStamp end, bool raw, bool localtime)
{ {
/* Connect to db */ /* Connect to db */
CassCluster *cluster = CassHelper::create_cluster(hostname); CassCluster *cluster = CassHelper::create_cluster(hostname);
...@@ -54,7 +54,7 @@ void DCDBQuery::doQuery(const char* hostname, std::list<std::string> sensors, DC ...@@ -54,7 +54,7 @@ void DCDBQuery::doQuery(const char* hostname, std::list<std::string> sensors, DC
} }
#endif #endif
querySensorsCSV(session, *it, sidList, start, end, raw); querySensorsCSV(session, *it, sidList, start, end, raw, localtime);
} }
/* Clean up */ /* Clean up */
...@@ -279,7 +279,7 @@ bool DCDBQuery::sidPatternMatch(SensorId& sid, std::string pattern) ...@@ -279,7 +279,7 @@ bool DCDBQuery::sidPatternMatch(SensorId& sid, std::string pattern)
return true; return true;
} }
void DCDBQuery::querySensorsCSV(CassSession* session, std::string sensorName, std::list<SensorId>& sidList, DCDBTimeStamp& start, DCDBTimeStamp& end, bool raw) void DCDBQuery::querySensorsCSV(CassSession* session, std::string sensorName, std::list<SensorId>& sidList, DCDBTimeStamp& start, DCDBTimeStamp& end, bool raw, bool localtime)
{ {
/* Since everything has been mangled until here, we assume parameter safety and do a non-prepared statement... Oh oh... */ /* Since everything has been mangled until here, we assume parameter safety and do a non-prepared statement... Oh oh... */
std::stringstream query; std::stringstream query;
...@@ -313,11 +313,14 @@ void DCDBQuery::querySensorsCSV(CassSession* session, std::string sensorName, st ...@@ -313,11 +313,14 @@ void DCDBQuery::querySensorsCSV(CassSession* session, std::string sensorName, st
cass_value_get_int64(cass_row_get_column_by_name(row, "ts"), &ts); cass_value_get_int64(cass_row_get_column_by_name(row, "ts"), &ts);
cass_value_get_int64(cass_row_get_column_by_name(row, "value"), &value); cass_value_get_int64(cass_row_get_column_by_name(row, "value"), &value);
DCDBTimeStamp t((uint64_t)ts);
if (localtime) {
t.convertToLocal();
}
if (raw) { if (raw) {
std::cout << sensorName << "," << std::dec << ts << "," << std::dec << value << std::endl; std::cout << sensorName << "," << std::dec << t.getRaw() << "," << std::dec << value << std::endl;
} }
else { else {
DCDBTimeStamp t((uint64_t)ts);
std::cout << sensorName << "," << t.getString() << "," << std::dec << value << std::endl; std::cout << sensorName << "," << t.getString() << "," << std::dec << value << std::endl;
} }
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
class DCDBQuery class DCDBQuery
{ {
public: public:
static void doQuery(const char* hostname, std::list<std::string> sensors, DCDBTimeStamp start, DCDBTimeStamp end, bool raw); static void doQuery(const char* hostname, std::list<std::string> sensors, DCDBTimeStamp start, DCDBTimeStamp end, bool raw, bool localtime);
protected: protected:
static void lookupPublishedSensorPattern(CassSession* session, std::string name, std::string& pattern); static void lookupPublishedSensorPattern(CassSession* session, std::string name, std::string& pattern);
...@@ -28,7 +28,7 @@ protected: ...@@ -28,7 +28,7 @@ protected:
static bool topicToSid(SensorId& sid, std::string topic); static bool topicToSid(SensorId& sid, std::string topic);
static std::string sidConvert(SensorId& sid); static std::string sidConvert(SensorId& sid);
static bool sidPatternMatch(SensorId& sid, std::string pattern); static bool sidPatternMatch(SensorId& sid, std::string pattern);
static void querySensorsCSV(CassSession* session, std::string sensorName, std::list<SensorId>& sidList, DCDBTimeStamp& start, DCDBTimeStamp& end, bool raw); static void querySensorsCSV(CassSession* session, std::string sensorName, std::list<SensorId>& sidList, DCDBTimeStamp& start, DCDBTimeStamp& end, bool raw, bool localtime);
}; };
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment