WSL/SLF GitLab Repository

Commit 3f45c394 authored by Mathias Bavay's avatar Mathias Bavay
Browse files

In order to try to be closer to the spirit of the STL, now the empty...

In order to try to be closer to the spirit of the STL, now the empty strings/vectors/lists are tested with .empty(), the first/last elements of vectors accessed with front()/back(), the empty strings are not contructed with string("") but with string(), etc This makes a benchmark based on meteo_reading ~4% faster and this makes the code suprisingly easier to read. 

Some extra constification took place as well as some minor code cleanup (optimizing the comparison between two vectors in order to perform less tests, etc).

The Date class can now properly generate and parse full ISO timestamps, including time zone information. The full specification is now supported by convertString() with a helper method in the Date class. Ouputing an ISO string with its time zone is done by requesting the ISO_TZ format.

parent c3995663
......@@ -65,7 +65,7 @@ void BufferedIOHandler::bufferGrid(const Grid2DObject& in_grid2Dobj, const std::
void BufferedIOHandler::read2DGrid(Grid2DObject& in_grid2Dobj, const std::string& in_filename)
{
if(max_grids>0) {
const std::map<std::string, Grid2DObject>::iterator it = mapBufferedGrids.find(in_filename);
const std::map<std::string, Grid2DObject>::const_iterator it = mapBufferedGrids.find(in_filename);
if (it != mapBufferedGrids.end()) { //already in map
in_grid2Dobj = (*it).second;
return;
......@@ -84,7 +84,7 @@ void BufferedIOHandler::read2DGrid(Grid2DObject& grid_out, const MeteoGrids::Par
{
if(max_grids>0) {
const string buffer_name = date.toString(Date::ISO)+"::"+MeteoGrids::getParameterName(parameter);
const std::map<std::string, Grid2DObject>::iterator it = mapBufferedGrids.find(buffer_name);
const std::map<std::string, Grid2DObject>::const_iterator it = mapBufferedGrids.find(buffer_name);
if (it != mapBufferedGrids.end()) { //already in map
grid_out = (*it).second;
return;
......@@ -102,7 +102,7 @@ void BufferedIOHandler::read2DGrid(Grid2DObject& grid_out, const MeteoGrids::Par
void BufferedIOHandler::readDEM(DEMObject& in_grid2Dobj)
{
if(max_grids>0) {
const std::map<std::string, Grid2DObject>::iterator it = mapBufferedGrids.find("/:DEM");
const std::map<std::string, Grid2DObject>::const_iterator it = mapBufferedGrids.find("/:DEM");
if (it != mapBufferedGrids.end()) {
//already in map. If the update properties have changed,
//we copy the ones given in input and force the update of the object
......@@ -130,7 +130,7 @@ void BufferedIOHandler::readDEM(DEMObject& in_grid2Dobj)
void BufferedIOHandler::readLanduse(Grid2DObject& in_grid2Dobj)
{
if(max_grids>0) {
const std::map<std::string, Grid2DObject>::iterator it = mapBufferedGrids.find("/:LANDUSE");
const std::map<std::string, Grid2DObject>::const_iterator it = mapBufferedGrids.find("/:LANDUSE");
if (it != mapBufferedGrids.end()) { //already in map
in_grid2Dobj = (*it).second;
return;
......@@ -149,7 +149,7 @@ void BufferedIOHandler::readLanduse(Grid2DObject& in_grid2Dobj)
void BufferedIOHandler::readAssimilationData(const Date& in_date, Grid2DObject& in_grid2Dobj)
{
if(max_grids>0) {
const std::map<std::string, Grid2DObject>::iterator it = mapBufferedGrids.find("/:ASSIMILATIONDATA" + in_date.toString(Date::FULL));
const std::map<std::string, Grid2DObject>::const_iterator it = mapBufferedGrids.find("/:ASSIMILATIONDATA" + in_date.toString(Date::FULL));
if (it != mapBufferedGrids.end()) { //already in map
in_grid2Dobj = (*it).second;
return;
......@@ -236,20 +236,20 @@ void BufferedIOHandler::setMinBufferRequirements(const double& i_chunk_size, con
double BufferedIOHandler::getAvgSamplingRate()
{
const size_t nr_stations = vec_buffer_meteo.size();
if (nr_stations > 0){
if (!vec_buffer_meteo.empty()){
double sum = 0;
for (size_t ii=0; ii<nr_stations; ii++){ //loop over all stations
const size_t nr_data_pts = vec_buffer_meteo[ii].size();
if(nr_data_pts>1) {
if(!vec_buffer_meteo[ii].empty()) {
const size_t nr_data_pts = vec_buffer_meteo[ii].size();
const std::vector<MeteoData>& curr_station = vec_buffer_meteo[ii];
const double days = curr_station[nr_data_pts-1].date.getJulian() - curr_station[0].date.getJulian();
const double days = curr_station.back().date.getJulian() - curr_station.front().date.getJulian();
//add the average sampling rate for this station
if(days>0.) sum += (double)(nr_data_pts-1) / days; //the interval story: 2 points define 1 interval!
}
}
if (sum > 0.){
return ((double)sum / ((double)nr_stations*24*3600)); //in points per seconds, ie Hz
return ((double)sum / (double)(nr_stations*24*3600)); //in points per seconds, ie Hz
}
}
......@@ -305,11 +305,9 @@ void BufferedIOHandler::readMeteoData(const Date& date_start, const Date& date_e
//Loop through stations and append data
for (size_t ii=0; ii<buffer_size; ii++){ //loop through stations
const size_t station_size = vec_buffer_meteo[ii].size();
if ((station_size > 0) && (tmp_meteo_buffer[ii].size() > 0)){
if ((!vec_buffer_meteo[ii].empty()) && (!tmp_meteo_buffer[ii].empty())){
//check if the last element equals the first one
if (vec_buffer_meteo[ii][station_size-1].date >= tmp_meteo_buffer[ii][0].date)
if (vec_buffer_meteo[ii].back().date >= tmp_meteo_buffer[ii].front().date)
vec_buffer_meteo[ii].pop_back(); //delete the element with the same date
}
......@@ -326,7 +324,7 @@ void BufferedIOHandler::readMeteoData(const Date& date_start, const Date& date_e
for (size_t ii=0; ii<buffer_size; ii++){ //loop through stations
vecMeteo.push_back(vector<MeteoData>()); //insert one empty vector of MeteoData
if (vec_buffer_meteo[ii].size() == 0) continue; //no data in buffer for this station
if (vec_buffer_meteo[ii].empty()) continue; //no data in buffer for this station
size_t pos_start = IOUtils::seek(date_start, vec_buffer_meteo[ii], false);
if (pos_start == IOUtils::npos) pos_start = 0;
......@@ -404,10 +402,10 @@ std::ostream& operator<<(std::ostream& os, const BufferedIOHandler& data)
<< data.mapBufferedGrids.size() << " grids):\n";
for(size_t ii=0; ii<data.vec_buffer_meteo.size(); ii++) {
if (data.vec_buffer_meteo[ii].size() > 0){
os << std::setw(10) << data.vec_buffer_meteo[ii][0].meta.stationID << " = "
<< data.vec_buffer_meteo[ii][0].date.toString(Date::ISO) << " - "
<< data.vec_buffer_meteo[ii][data.vec_buffer_meteo[ii].size()-1].date.toString(Date::ISO) << ", "
if (!data.vec_buffer_meteo[ii].empty()){
os << std::setw(10) << data.vec_buffer_meteo[ii].front().meta.stationID << " = "
<< data.vec_buffer_meteo[ii].front().date.toString(Date::ISO) << " - "
<< data.vec_buffer_meteo[ii].back().date.toString(Date::ISO) << ", "
<< data.vec_buffer_meteo[ii].size() << " timesteps" << endl;
}
}
......
......@@ -87,8 +87,7 @@ bool Config::keyExists(const std::string& key, const std::string& section) const
std::ostream& operator<<(std::ostream &os, const Config& cfg)
{
os << "<Config>\n";
map<string,string>::const_iterator it;
for (it=cfg.properties.begin(); it != cfg.properties.end(); ++it){
for (map<string,string>::const_iterator it = cfg.properties.begin(); it != cfg.properties.end(); ++it){
os << (*it).first << " -> " << (*it).second << "\n";
}
os << "</Config>\n";
......@@ -121,7 +120,7 @@ void Config::parseFile(const std::string& filename)
throw FileAccessException(filename, AT);
}
std::string line="", section=defaultSection;
std::string line, section=defaultSection;
const char eoln = IOUtils::getEoln(fin); //get the end of line character for the file
unsigned int linenr = 0;
......@@ -143,9 +142,8 @@ void Config::parseLine(const unsigned int& linenr, std::string& line, std::strin
{
//First thing cut away any possible comments (may start with "#" or ";")
IOUtils::stripComments(line);
IOUtils::trim(line); //delete leading and trailing whitespace characters
if (line.length() == 0) //ignore empty lines
if (line.empty()) //ignore empty lines
return;
stringstream tmp; //stringstream to convert the unsigned int linenr into a string
......@@ -179,7 +177,7 @@ size_t Config::findKeys(std::vector<std::string>& vecResult, const std::string&
{
vecResult.clear();
if (section.length() == 0) //enforce the default section if user tries to give empty section string
if (section.empty()) //enforce the default section if user tries to give empty section string
section = defaultSection;
const string tmp_keystart = IOUtils::strToUpper(section) + "::" + IOUtils::strToUpper(keystart);
......
......@@ -207,7 +207,7 @@ void Coords::merge(const Coords& coord2) {
if(distance_algo==IOUtils::nodata) distance_algo=coord2.distance_algo;
//in LOCAL projection, the check for the existence of the ref point will be done in the projection functions
if(coordsystem=="LOCAL" && coordparam!="") {
if(coordsystem=="LOCAL" && !coordparam.empty()) {
parseLatLon(coordparam, ref_latitude, ref_longitude);
}
if(latitude!=IOUtils::nodata && coordsystem!="NULL") {
......@@ -284,7 +284,7 @@ Coords::Coords(const double& in_lat_ref, const double& in_long_ref) :
altitude(IOUtils::nodata), latitude(IOUtils::nodata), longitude(IOUtils::nodata),
easting(IOUtils::nodata), northing(IOUtils::nodata),
grid_i(IOUtils::inodata), grid_j(IOUtils::inodata), grid_k(IOUtils::inodata),
coordsystem("LOCAL"), coordparam(""), distance_algo(GEO_COSINE)
coordsystem("LOCAL"), coordparam(), distance_algo(GEO_COSINE)
{
//setDefaultValues();
setLocalRef(in_lat_ref, in_long_ref);
......@@ -515,13 +515,13 @@ void Coords::setProj(const std::string& in_coordinatesystem, const std::string&
convert_to_WGS84(easting, northing, latitude, longitude);
}
if(in_coordinatesystem == "") {
if(in_coordinatesystem.empty()) {
coordsystem = std::string("NULL");
} else {
coordsystem = in_coordinatesystem;
}
coordparam = in_parameters;
if(coordsystem=="LOCAL" && coordparam!="") {
if(coordsystem=="LOCAL" && !coordparam.empty()) {
parseLatLon(coordparam, ref_latitude, ref_longitude);
}
......
......@@ -17,6 +17,7 @@
*/
#include <meteoio/Date.h>
#include <meteoio/IOUtils.h>
#include <meteoio/MathOptim.h>
#include <cmath>
using namespace std;
......@@ -771,6 +772,62 @@ std::ostream& operator<<(std::ostream &os, const Date &date) {
return os;
}
/**
* @brief Parse an ISO 8601 formatted time zone specification.
* Time zones MUST be specified right after a date/time/combined representation
* according to the following formats:
* - 'Z' like in 2013-02-13T19:43Z, meaning GMT
* - '+01' like in 2013-02-13T20:43+01 meaning GMT+1
* - '+0130' like in 2013-02-13T21:13+0130 meaning GMT+1.5
* - '-0515' like in 2013-02-13T15:28-0515 meaning GMT-5.25
* See https://en.wikipedia.org/wiki/ISO_8601 for more information
* @param timezone_iso time zone string
* @return time zone/shift in hours
*/
double Date::parseTimeZone(const std::string& timezone_iso)
{
if(timezone_iso=="Z") { //time as Z
return 0.;
} else if(timezone_iso[0]=='+' || timezone_iso[0]=='-') {
const char *c_str = timezone_iso.c_str();
const size_t str_size = timezone_iso.size();
switch(str_size) {
case 6: { //timezone as +01:00
int tz_h, tz_min;
if( sscanf(c_str, "%d:%d", &tz_h, &tz_min) == 2 ) {
//if there is a "-", apply it to the minutes
if(tz_h>=0.)
return (double)tz_h + (double)tz_min/60.;
else
return (double)tz_h - (double)tz_min/60.;
} else {
return IOUtils::nodata;
}
}
case 5: { //timezone as +0100
int tz_tmp;
if( sscanf(c_str, "%d", &tz_tmp) == 1 ) {
const int tz_h = tz_tmp/100;
const int tz_min = tz_tmp-100*tz_h;
return (double)tz_h + (double)tz_min/60.;
} else {
return IOUtils::nodata;
}
}
case 3: { //timezone as -01
int tz_h;
if( sscanf(c_str, "%d", &tz_h) == 1 )
return (double)tz_h;
else
return IOUtils::nodata;
}
}
return IOUtils::nodata;
} else {
return IOUtils::nodata;
}
}
/**
* @brief Return a nicely formated string.
* @param type select the formating to apply (see the definition of Date::FORMATS)
......@@ -798,21 +855,39 @@ const string Date::toString(FORMATS type, const bool& gmt) const
}
stringstream tmpstr;
if(type==ISO) {
switch(type) {
case(ISO_TZ):
case(ISO):
tmpstr
<< setw(4) << setfill('0') << year_out << "-"
<< setw(2) << setfill('0') << month_out << "-"
<< setw(2) << setfill('0') << day_out << "T"
<< setw(2) << setfill('0') << hour_out << ":"
<< setw(2) << setfill('0') << minute_out;
} else if(type==NUM) {
if(type==ISO_TZ) {
int tz_h, tz_min;
if(timezone>=0.) {
tz_h = static_cast<int>(timezone);
tz_min = static_cast<int>( (timezone - (double)tz_h)*60. + .5 ); //round to closest
tmpstr << "+";
} else {
tz_h = -static_cast<int>(timezone);
tz_min = -static_cast<int>( (timezone + (double)tz_h)*60. + .5 ); //round to closest
tmpstr << "-";
}
tmpstr << setw(2) << setfill('0') << tz_h << ":"
<< setw(2) << setfill('0') << tz_min;
}
break;
case(NUM):
tmpstr
<< setw(4) << setfill('0') << year_out
<< setw(2) << setfill('0') << month_out
<< setw(2) << setfill('0') << day_out
<< setw(2) << setfill('0') << hour_out
<< setw(2) << setfill('0') << minute_out ;
} else if(type==FULL) {
break;
case(FULL):
tmpstr
<< setw(4) << setfill('0') << year_out << "-"
<< setw(2) << setfill('0') << month_out << "-"
......@@ -821,15 +896,17 @@ const string Date::toString(FORMATS type, const bool& gmt) const
<< setw(2) << setfill('0') << minute_out << " ("
<< setprecision(10) << julian_out << ") GMT"
<< setw(2) << setfill('0') << showpos << timezone << noshowpos;
} else if(type==DIN) {
break;
case(DIN):
tmpstr
<< setw(2) << setfill('0') << day_out << "."
<< setw(2) << setfill('0') << month_out << "."
<< setw(4) << setfill('0') << year_out << " "
<< setw(2) << setfill('0') << hour_out << ":"
<< setw(2) << setfill('0') << minute_out;
} else {
throw InvalidArgumentException("Wrong date conversion format requested", AT);
break;
default:
throw InvalidArgumentException("Wrong date conversion format requested", AT);
}
return tmpstr.str();
......
......@@ -73,6 +73,7 @@ class Date {
///Keywords for selecting the date formats
typedef enum {
ISO, ///< ISO 8601 extended format combined date: YYYY-MM-DDTHH:mm:SS (fields might be dropped, in the least to the most significant order)
ISO_TZ, ///< ISO 8601 format (same as ISO) but with tie zone specification
FULL, ///< ISO 8601 followed by the julian date (in parenthesis)
NUM, ///< ISO 8601 basic format date: YYYYMMDDHHmmSS (fields might be dropped, in the least to the most significant order)
DIN ///<DIN5008 format: DD.MM.YYYY HH:MM
......@@ -132,6 +133,7 @@ class Date {
void rnd(const double& precision, const RND& type=CLOSEST);
static const Date rnd(const Date& indate, const double& precision, const RND& type=CLOSEST);
static double parseTimeZone(const std::string& timezone_iso);
const std::string toString(FORMATS type, const bool& gmt=false) const;
......
......@@ -285,8 +285,8 @@ void IOHandler::readMeteoData(const Date& date, METEO_TIMESERIE& vecMeteo)
size_t emptycounter = 0;
for (size_t ii=0; ii<meteoTmpBuffer.size(); ii++){//stations
if (meteoTmpBuffer[ii].size() > 0){
vecMeteo.push_back(meteoTmpBuffer[ii][0]);
if (!meteoTmpBuffer[ii].empty()){
vecMeteo.push_back(meteoTmpBuffer[ii].front());
} else {
emptycounter++;
}
......
......@@ -159,7 +159,7 @@ bool IOManager::read_filtered_cache(const Date& start_date, const Date& end_date
for (size_t ii=0; ii<filtered_cache.size(); ii++){ //loop over stations
size_t startpos = IOUtils::seek(start_date, filtered_cache[ii], false);
if (startpos == IOUtils::npos){
if (filtered_cache[ii].size() > 0){
if (!filtered_cache[ii].empty()){
if (filtered_cache[ii][0].date <= end_date){
startpos = 0;
}
......@@ -168,11 +168,10 @@ bool IOManager::read_filtered_cache(const Date& start_date, const Date& end_date
if (startpos != IOUtils::npos){
vec_meteo.push_back(vector<MeteoData>());
const size_t index = vec_meteo.size()-1;
for (size_t jj=startpos; jj<filtered_cache[ii].size(); jj++){
const MeteoData& md = filtered_cache[ii][jj];
if (md.date <= end_date){
vec_meteo[index].push_back(md);
vec_meteo.back().push_back(md);
} else {
break;
}
......@@ -189,9 +188,8 @@ bool IOManager::read_filtered_cache(const Date& start_date, const Date& end_date
void IOManager::add_to_cache(const Date& i_date, const METEO_TIMESERIE& vecMeteo)
{
//Check cache size, delete oldest elements if necessary
if (point_cache.size() > 200){
if (point_cache.size() > 2000){
point_cache.clear();
//point_cache.erase(point_cache.begin(), point_cache.begin()+50);
}
point_cache[i_date] = vecMeteo;
......@@ -219,7 +217,7 @@ size_t IOManager::getMeteoData(const Date& i_date, METEO_TIMESERIE& vecMeteo)
//2. Check which data point is available, buffered locally
map<Date, vector<MeteoData> >::const_iterator it = point_cache.find(i_date);
const map<Date, vector<MeteoData> >::const_iterator it = point_cache.find(i_date);
if (it != point_cache.end()){
vecMeteo = it->second;
return vecMeteo.size();
......@@ -506,10 +504,10 @@ std::string IOManager::toString() const {
//display filtered_cache
os << "Filteredcache content (" << filtered_cache.size() << " stations)\n";
for(size_t ii=0; ii<filtered_cache.size(); ii++) {
if (filtered_cache[ii].size() > 0){
os << std::setw(10) << filtered_cache[ii][0].meta.stationID << " = "
<< filtered_cache[ii][0].date.toString(Date::ISO) << " - "
<< filtered_cache[ii][filtered_cache[ii].size()-1].date.toString(Date::ISO) << ", "
if (!filtered_cache[ii].empty()){
os << std::setw(10) << filtered_cache[ii].front().meta.stationID << " = "
<< filtered_cache[ii].front().date.toString(Date::ISO) << " - "
<< filtered_cache[ii].back().date.toString(Date::ISO) << ", "
<< filtered_cache[ii].size() << " timesteps" << endl;
}
}
......
......@@ -136,12 +136,12 @@ std::string cleanPath(const std::string& in_path) {
std::string getExtension(const std::string& filename)
{
const std::string whitespaces(" \t\f\v\n\r");
const size_t start_basename = filename.find_last_of("/\\"); //we will skip the path
const size_t startpos = filename.find_last_of('.');
if( startpos==std::string::npos ) return std::string("");
if( start_basename!=std::string::npos && startpos<start_basename ) return std::string("");
if( startpos==std::string::npos ) return std::string();
if( start_basename!=std::string::npos && startpos<start_basename ) return std::string();
const std::string whitespaces(" \t\f\v\n\r");
const size_t endpos = filename.find_last_not_of(whitespaces); // Find the first character position from reverse af
return filename.substr(startpos+1, endpos-startpos);
......@@ -165,7 +165,8 @@ void trim(std::string& str)
// if all spaces or empty return an empty string
if(startpos!=std::string::npos && endpos!=std::string::npos) {
str = str.substr( startpos, endpos-startpos+1 );
str.erase(endpos+1); //right trim
str.erase(0, startpos); //left trim
} else {
str.clear();
}
......@@ -214,7 +215,7 @@ bool isNumeric(std::string str, const unsigned int& nBase)
bool readKeyValuePair(const std::string& in_line, const std::string& delimiter,
std::map<std::string,std::string>& out_map, const std::string& keyprefix, const bool& setToUpperCase)
{
size_t pos = std::string::npos;
size_t pos;
if ((delimiter==" ") || (delimiter=="\t")) {
pos = in_line.find_first_of(" \t", 0);
} else {
......@@ -229,7 +230,7 @@ bool readKeyValuePair(const std::string& in_line, const std::string& delimiter,
trim(key);
trim(value);
if ((key == "") || (value=="")) {
if (key.empty() || value.empty()) {
return false;
}
......@@ -263,9 +264,6 @@ bool fileExists(const std::string& filename)
void readDirectory(const std::string& path, std::list<std::string>& dirlist, const std::string& pattern)
{
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
const size_t path_length = path.length();
if (path_length > (MAX_PATH - 3)) {
std::cerr << "Path " << path << "is too long (" << path_length << " characters)" << std::endl;
......@@ -273,7 +271,8 @@ void readDirectory(const std::string& path, std::list<std::string>& dirlist, con
}
const std::string filepath = path+"\\"+pattern;
hFind = FindFirstFile(filepath.c_str(), &ffd);
WIN32_FIND_DATA ffd;
const HANDLE hFind = FindFirstFile(filepath.c_str(), &ffd);
if (INVALID_HANDLE_VALUE == hFind) {
throw FileAccessException("Error opening directory " + path, AT);
}
......@@ -309,17 +308,16 @@ bool fileExists(const std::string& filename)
void readDirectory(const std::string& path, std::list<std::string>& dirlist, const std::string& pattern)
{
DIR *dp;
struct dirent *dirp;
if((dp = opendir(path.c_str())) == NULL) {
DIR *dp = opendir(path.c_str());
if(dp == NULL) {
throw FileAccessException("Error opening directory " + path, AT);
}
struct dirent *dirp;
while ((dirp = readdir(dp)) != NULL) {
const std::string tmp(dirp->d_name);
if( tmp.compare(".")!=0 && tmp.compare("..")!=0 ) { //skip "." and ".."
if (pattern=="") {
if (pattern.empty()) {
dirlist.push_back(tmp);
} else {
const size_t pos = tmp.find(pattern);
......@@ -480,10 +478,8 @@ const char NUM[] = "0123456789";
template<> bool convertString<std::string>(std::string& t, const std::string& str, std::ios_base& (*f)(std::ios_base&))
{
(void)f;
std::string s(str);
trim(s); //delete trailing and leading whitespaces and tabs
t = s;
t = str;
trim(t); //delete trailing and leading whitespaces and tabs
return true;
}
......@@ -552,61 +548,107 @@ bool convertString(Date& t, const std::string& str, const double& time_zone, std
(void)f;
int year;
unsigned int month, day, hour, minute, second;
unsigned int month, day, hour, minute;
double second;
char rest[32] = "";
//HACK: we read the seconds, but we ignore them...
if (sscanf(s.c_str(), "%d-%u-%u %u:%u:%u%31s", &year, &month, &day, &hour, &minute, &second, rest) >= 6) {
t.setDate(year, month, day, hour, minute, time_zone);
} else if (sscanf(s.c_str(), "%d-%u-%uT%u:%u:%u%31s", &year, &month, &day, &hour, &minute, &second, rest) >= 6) {
t.setDate(year, month, day, hour, minute, time_zone);
} else if (sscanf(s.c_str(), "%d-%u-%u %u:%u%31s", &year, &month, &day, &hour, &minute, rest) >= 5) {
t.setDate(year, month, day, hour, minute, time_zone);
} else if (sscanf(s.c_str(), "%d-%u-%uT%u:%u%31s", &year, &month, &day, &hour, &minute, rest) >= 5) {
t.setDate(year, month, day, hour, minute, time_zone);
} else if (sscanf(s.c_str(), "%d-%u-%u%31s", &year, &month, &day, rest) >= 3) {
t.setDate(year, month, day, (unsigned)0, (unsigned)0, time_zone);
} else if (sscanf(s.c_str(), "%u:%u%31s", &hour, &minute, rest) >= 2) {
t.setDate( ((double)hour)/24. + ((double)minute)/24./60. , time_zone);
const char *c_str = s.c_str();
if (sscanf(c_str, "%d-%u-%u %u:%u:%lg%31s", &year, &month, &day, &hour, &minute, &second, rest) >= 6) {
std::string timezone_iso(rest);
stripComments(timezone_iso);
const double tz = (timezone_iso.empty())? time_zone : Date::parseTimeZone(timezone_iso);
if(tz==nodata) return false;
t.setDate(year, month, day, hour, minute, tz);
return true;
} else if (sscanf(c_str, "%d-%u-%uT%u:%u:%lg%31s", &year, &month, &day, &hour, &minute, &second, rest) >= 6) { //ISO
std::string timezone_iso(rest);
stripComments(timezone_iso);
const double tz = (timezone_iso.empty())? time_zone : Date::parseTimeZone(timezone_iso);
if(tz==nodata) return false;
t.setDate(year, month, day, hour, minute, tz);
return true;
} else if (sscanf(c_str, "%d-%u-%u %u:%u%31s", &year, &month, &day, &hour, &minute, rest) >= 5) {
std::string timezone_iso(rest);
stripComments(timezone_iso);
const double tz = (timezone_iso.empty())? time_zone : Date::parseTimeZone(timezone_iso);
if(tz==nodata) return false;
t.setDate(year, month, day, hour, minute, tz);
return true;
} else if (sscanf(c_str, "%d-%u-%uT%u:%u%31s", &year, &month, &day, &hour, &minute, rest) >= 5) {
std::string timezone_iso(rest);
stripComments(timezone_iso);
const double tz = (timezone_iso.empty())? time_zone : Date::parseTimeZone(timezone_iso);
if(tz==nodata) return false;
t.setDate(year, month, day, hour, minute, tz);
return true;
} else if (sscanf(c_str, "%d-%u-%u%31s", &year, &month, &day, rest) >= 3) {
std::string timezone_iso(rest);
stripComments(timezone_iso);
const double tz = (timezone_iso.empty())? time_zone : Date::parseTimeZone(timezone_iso);
if(tz==nodata) return false;
t.setDate(year, month, day, (unsigned)0, (unsigned)0, tz);
return true;
} else if (sscanf(c_str, "%u:%u%31s", &hour, &minute, rest) >= 2) {
std::string timezone_iso(rest);
stripComments(timezone_iso);
const double tz = (timezone_iso.empty())? time_zone : Date::parseTimeZone(timezone_iso);
if(tz==nodata) return false;
t.setDate( ((double)hour)/24. + ((double)minute)/24./60. , tz);
return true;
} else {
//try to read purely numerical date, potentially surrounded by other chars
const size_t in_len = str.length();
const size_t beg = str.find_first_of(NUM);
if(beg==npos || beg==in_len) return false;
size_t end = str.find_first_not_of(NUM, beg+1);
if(end==npos) end = in_len;
const std::string datum = str.substr(beg, end-beg);
const size_t d_len = datum.length();
if(d_len<10 || d_len>14) return false;
if( convertString(year,datum.substr(0,4))==false ) return false;
if( convertString(month,datum.substr(4,2))==false ) return false;
if( convertString(day,datum.substr(6,2))==false ) return false;
if( convertString(hour,datum.substr(8,2))==false ) return false;
if(d_len==10)
//and potentially containing an ISO time zone string
const size_t in_len = s.length();
//extract date/time