#5162 Support reading of LAS-file dates without separators

This commit is contained in:
Gaute Lindkvist 2020-01-21 15:14:17 +01:00
parent 5e68adc099
commit 024f3d020a
4 changed files with 263 additions and 12 deletions

View File

@ -39,10 +39,20 @@ QDateTime RiaDateStringParser::parseDateString( const QString& dateString )
//--------------------------------------------------------------------------------------------------
QDateTime RiaDateStringParser::parseDateString( const std::string& dateString )
{
int year, month, day;
bool parsedOk = tryParseYearFirst( dateString, year, month, day ) ||
tryParseDayFirst( dateString, year, month, day ) ||
tryParseMonthFirst( dateString, year, month, day );
int year = -1, month = -1, day = -1;
bool parsedOk = false;
if ( hasSeparators( dateString ) )
{
parsedOk = tryParseYearFirst( dateString, year, month, day ) ||
tryParseDayFirst( dateString, year, month, day ) ||
tryParseMonthFirst( dateString, year, month, day );
}
else if ( !RiaStdStringTools::containsAlphabetic( dateString ) )
{
parsedOk = tryParseYearFirstNoSeparators( dateString, year, month, day ) ||
tryParseDayFirstNoSeparators( dateString, year, month, day ) ||
tryParseMonthFirstNoSeparators( dateString, year, month, day );
}
QDateTime dt;
dt.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
@ -60,13 +70,12 @@ QDateTime RiaDateStringParser::parseDateString( const std::string& dateString )
/// 'yyyy-mm-dd'
/// 'yyyy-MMM-dd'
/// 'yyyy.MMM.dd'
/// 'yyyy.MMM.dd'
/// MMM is month name (shortened)
//--------------------------------------------------------------------------------------------------
bool RiaDateStringParser::tryParseYearFirst( const std::string& s, int& year, int& month, int& day )
{
auto firstSep = s.find_first_of( " -_." );
auto lastSep = s.find_first_of( " -_.", firstSep + 1 );
auto firstSep = s.find_first_of( separators() );
auto lastSep = s.find_first_of( separators(), firstSep + 1 );
if ( firstSep == std::string::npos || lastSep == std::string::npos ) return false;
@ -91,8 +100,8 @@ bool RiaDateStringParser::tryParseYearFirst( const std::string& s, int& year, in
//--------------------------------------------------------------------------------------------------
bool RiaDateStringParser::tryParseDayFirst( const std::string& s, int& year, int& month, int& day )
{
auto firstSep = s.find_first_of( " -_." );
auto lastSep = s.find_first_of( " -_.", firstSep + 1 );
auto firstSep = s.find_first_of( separators() );
auto lastSep = s.find_first_of( separators(), firstSep + 1 );
if ( firstSep == std::string::npos || lastSep == std::string::npos ) return false;
@ -108,8 +117,8 @@ bool RiaDateStringParser::tryParseDayFirst( const std::string& s, int& year, int
//--------------------------------------------------------------------------------------------------
bool RiaDateStringParser::tryParseMonthFirst( const std::string& s, int& year, int& month, int& day )
{
auto firstSep = s.find_first_of( " -_." );
auto lastSep = s.find_first_of( " -_.", firstSep + 1 );
auto firstSep = s.find_first_of( separators() );
auto lastSep = s.find_first_of( separators(), firstSep + 1 );
if ( firstSep == std::string::npos || lastSep == std::string::npos ) return false;
@ -120,6 +129,83 @@ bool RiaDateStringParser::tryParseMonthFirst( const std::string& s, int& year, i
return tryParseYear( sYear, year ) && tryParseMonth( sMonth, month ) && tryParseDay( sDay, day );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaDateStringParser::tryParseYearFirstNoSeparators( const std::string& s, int& year, int& month, int& day )
{
if ( s.length() == 8 )
{
// Four digit year
auto sYear = s.substr( 0, 4 );
auto sMonth = s.substr( 4, 2 );
auto sDay = s.substr( 6, 2 );
return tryParseYear( sYear, year ) && tryParseMonth( sMonth, month ) && tryParseDay( sDay, day );
}
else if ( s.length() == 6 )
{
// Two digit year
auto sYear = s.substr( 0, 2 );
auto sMonth = s.substr( 2, 2 );
auto sDay = s.substr( 4, 2 );
return tryParseYear( sYear, year ) && tryParseMonth( sMonth, month ) && tryParseDay( sDay, day );
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaDateStringParser::tryParseDayFirstNoSeparators( const std::string& s, int& year, int& month, int& day )
{
if ( s.length() == 8 )
{
// Four digit year
auto sDay = s.substr( 0, 2 );
auto sMonth = s.substr( 2, 2 );
auto sYear = s.substr( 4, 4 );
return tryParseYear( sYear, year ) && tryParseMonth( sMonth, month ) && tryParseDay( sDay, day );
}
else if ( s.length() == 6 )
{
// Two digit year
auto sDay = s.substr( 0, 2 );
auto sMonth = s.substr( 2, 2 );
auto sYear = s.substr( 4, 2 );
return tryParseYear( sYear, year ) && tryParseMonth( sMonth, month ) && tryParseDay( sDay, day );
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaDateStringParser::tryParseMonthFirstNoSeparators( const std::string& s, int& year, int& month, int& day )
{
if ( s.length() == 8 )
{
// Four digit year
auto sMonth = s.substr( 0, 2 );
auto sDay = s.substr( 2, 2 );
auto sYear = s.substr( 4, 4 );
return tryParseYear( sYear, year ) && tryParseMonth( sMonth, month ) && tryParseDay( sDay, day );
}
else if ( s.length() == 6 )
{
// Two digit year
auto sMonth = s.substr( 0, 2 );
auto sDay = s.substr( 2, 2 );
auto sYear = s.substr( 4, 2 );
return tryParseYear( sYear, year ) && tryParseMonth( sMonth, month ) && tryParseDay( sDay, day );
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -129,7 +215,15 @@ bool RiaDateStringParser::tryParseYear( const std::string& s, int& year )
auto today = QDate::currentDate();
int y = RiaStdStringTools::toInt( s );
if ( y > 1970 && y <= today.year() )
if ( y < 100 )
{
if ( y > 70 )
y += 1900;
else
y += 2000;
}
if ( y > 1970 && y <= today.year() + 50 ) // Support dates 50 years into the future.
{
year = y;
@ -193,6 +287,23 @@ bool RiaDateStringParser::tryParseDay( const std::string& s, int& day )
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RiaDateStringParser::separators()
{
return " -_.";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaDateStringParser::hasSeparators( const std::string& s )
{
auto firstSep = s.find_first_of( separators() );
return firstSep != std::string::npos;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -38,9 +38,15 @@ private:
static bool tryParseDayFirst( const std::string& s, int& year, int& month, int& day );
static bool tryParseMonthFirst( const std::string& s, int& year, int& month, int& day );
static bool tryParseYearFirstNoSeparators( const std::string& s, int& year, int& month, int& day );
static bool tryParseDayFirstNoSeparators( const std::string& s, int& year, int& month, int& day );
static bool tryParseMonthFirstNoSeparators( const std::string& s, int& year, int& month, int& day );
static bool tryParseYear( const std::string& s, int& year );
static bool tryParseMonth( const std::string& s, int& month );
static bool tryParseDay( const std::string& s, int& day );
static std::string separators();
static bool hasSeparators( const std::string& s );
static std::string trimString( const std::string& s );
};

View File

@ -62,6 +62,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAnalyzer-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaStdStringTools-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifWellMeasurementReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaDateStringParser-Test.cpp
)
if (RESINSIGHT_ENABLE_GRPC)

View File

@ -0,0 +1,133 @@
#include "gtest/gtest.h"
#include "RiaDateStringParser.h"
#include "RiaQDateTimeTools.h"
#include <QDate>
#include <QDateTime>
#include <map>
#include <string>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaDateStringParserTest, ParseYearFirstWithSeparators )
{
QDateTime may2ndDT = QDateTime( QDate( 2011, 05, 02 ) );
may2ndDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
std::vector<std::string> may2ndStrings = {"2011 05 02",
"2011 May 02",
"2011_05_02",
"2011_May_02",
"2011_may_02",
"2011-05-02",
"2011-May-02",
"2011-may-02",
"2011.05.02",
"2011.May.02"};
for ( auto may2ndString : may2ndStrings )
{
QDateTime parsedDate = RiaDateStringParser::parseDateString( may2ndString );
EXPECT_TRUE( may2ndDT == parsedDate );
}
QDateTime nov24thDT = QDateTime( QDate( 1992, 11, 24 ) );
nov24thDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
std::vector<std::string> nov24thStrings = {"1992-11-24", "1992-Nov-24", "1992-nov-24", "1992.11.24"};
for ( auto nov24thString : nov24thStrings )
{
EXPECT_TRUE( nov24thDT == RiaDateStringParser::parseDateString( nov24thString ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaDateStringParserTest, ParseDayFirstWithSeparators )
{
QDateTime may2ndDT = QDateTime( QDate( 2011, 05, 02 ) );
may2ndDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
std::vector<std::string> may2ndStrings = {"02 05 2011",
"02 May 2011",
"02_05_2011",
"02_May_2011",
"02_may_2011",
"02-05-2011",
"02-May-2011",
"02-may-2011",
"02.05.2011"};
for ( auto may2ndString : may2ndStrings )
{
QDateTime parsedDate = RiaDateStringParser::parseDateString( may2ndString );
EXPECT_TRUE( may2ndDT == parsedDate );
}
QDateTime nov24thDT = QDateTime( QDate( 1992, 11, 24 ) );
nov24thDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
std::vector<std::string> nov24thStrings = {"24-11-1992", "24-Nov-1992", "24.Nov 1992", "24.11.1992"};
for ( auto nov24thString : nov24thStrings )
{
EXPECT_TRUE( nov24thDT == RiaDateStringParser::parseDateString( nov24thString ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaDateStringParserTest, ParseMonthFirstWithSeparators )
{
QDateTime may2ndDT = QDateTime( QDate( 2011, 05, 02 ) );
may2ndDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
std::vector<std::string> may2ndStrings = {"May 02 2011", "may 02 2011", "May_02_2011", "May.02.2011", "May 02. 2011"};
for ( auto may2ndString : may2ndStrings )
{
QDateTime parsedDate = RiaDateStringParser::parseDateString( may2ndString );
EXPECT_TRUE( may2ndDT == parsedDate );
}
QDateTime nov24thDT = QDateTime( QDate( 1992, 11, 24 ) );
nov24thDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
std::vector<std::string> nov24thStrings = {"11-24-1992", "Nov-24-1992", "Nov 24. 1992", "11.24.1992", "11 24 1992"};
for ( auto nov24thString : nov24thStrings )
{
EXPECT_TRUE( nov24thDT == RiaDateStringParser::parseDateString( nov24thString ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaDateStringParserTest, ParseWithoutSeparators )
{
QDateTime may2ndDT = QDateTime( QDate( 2011, 05, 02 ) );
QDateTime feb5thDT = QDateTime( QDate( 2011, 02, 05 ) );
may2ndDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
feb5thDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
std::vector<std::string> may2ndStrings = {"20110502", "02052011"};
for ( auto may2ndString : may2ndStrings )
{
QDateTime parsedDate = RiaDateStringParser::parseDateString( may2ndString );
EXPECT_TRUE( may2ndDT == parsedDate );
}
// This is ambiguous and we prefer day first ahead of month first.
std::string may2ndMonthFirstString( "05022011" );
EXPECT_FALSE( may2ndDT == RiaDateStringParser::parseDateString( may2ndMonthFirstString ) );
EXPECT_TRUE( feb5thDT == RiaDateStringParser::parseDateString( may2ndMonthFirstString ) );
QDateTime nov24thDT = QDateTime( QDate( 1992, 11, 24 ) );
nov24thDT.setTimeSpec( RiaQDateTimeTools::currentTimeSpec() );
std::vector<std::string> nov24thStrings = {"19921124", "24111992", "921124", "241192", "11241992", "112492"};
for ( auto nov24thString : nov24thStrings )
{
EXPECT_TRUE( nov24thDT == RiaDateStringParser::parseDateString( nov24thString ) );
}
}