Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create current_time function #53

Merged
merged 9 commits into from
Nov 23, 2024
Merged
81 changes: 76 additions & 5 deletions parser/mpFuncCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -703,11 +703,6 @@ MUP_NAMESPACE_START
return new FunAddDays(*this);
}

//------------------------------------------------------------------------------
//
// class FunTimeDiff
//
//------------------------------------------------------------------------------

//FunTimeDiff::FunTimeDiff()
// :ICallback(cmFUNC, _T("timediff"), -1)
Expand Down Expand Up @@ -808,6 +803,30 @@ MUP_NAMESPACE_START
// |
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// |
// Time auxiliar functions! |
// |
//------------------------------------------------------------------------------

int calculate_hour_offset(int original_hour, int gmt_offset) {
return ((original_hour + gmt_offset) % 24 + 24) % 24;
}

string_type format_time (struct tm time, int gmt_offset) {
char buffer[9];
int hours = calculate_hour_offset(time.tm_hour, gmt_offset);
snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d", hours, time.tm_min, time.tm_sec);

return std::string(buffer);
}

//------------------------------------------------------------------------------
//
// class FunTimeDiff
//
//------------------------------------------------------------------------------

FunTimeDiff::FunTimeDiff()
:ICallback(cmFUNC, _T("timediff"), -1)
{}
Expand Down Expand Up @@ -856,6 +875,58 @@ MUP_NAMESPACE_START
return new FunTimeDiff(*this);
}

//------------------------------------------------------------------------------
// |
// class FunCurrentTime |
// Usage: current_time() |
// Optional offset: current_time(-2) |
// |
//------------------------------------------------------------------------------

FunCurrentTime::FunCurrentTime()
:ICallback(cmFUNC, _T("current_time"), -1)
{}

void FunCurrentTime::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
int gmt_offset = 0;
if (a_iArgc > 1) {
throw ParserError(ErrorContext(ecTOO_MANY_PARAMS, GetExprPos(), GetIdent()));
} else if (a_iArgc == 1) {
switch(a_pArg[0]->GetType())
{
case 'i': gmt_offset = a_pArg[0]->GetInteger(); break;
default:
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT_FUN;
err.Arg = 1;
err.Type1 = a_pArg[0]->GetType();
err.Type2 = 'i';
err.Ident = GetIdent();
throw ParserError(err);
}
}
}

std::time_t t = std::time(0);
std::tm now = *std::gmtime(&t);

*ret = format_time(now, gmt_offset);
}

////---------------------------------------------------------------------------------------------------------
const char_type* FunCurrentTime::GetDesc() const
{
return _T("current_time(offset) - Returns the current time in the HH:MM:SS format, applying the offset.");
}

////---------------------------------------------------------------------------------------------------------
IToken* FunCurrentTime::Clone() const
{
return new FunCurrentTime(*this);
}

//------------------------------------------------------------------------------
// |
// Functions for regex matching |
Expand Down
13 changes: 13 additions & 0 deletions parser/mpFuncCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,19 @@ MUP_NAMESPACE_START
virtual IToken* Clone() const override;
}; // class FunTimeDiff

//------------------------------------------------------------------------------
/** \brief Returns the current time in the HH:MM:SS format.
\ingroup functions
*/
class FunCurrentTime : public ICallback
{
public:
FunCurrentTime();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class FunCurrentTime

//------------------------------------------------------------------------------
/** \brief Return the capture group of a regular expression.
\ingroup functions
Expand Down
1 change: 1 addition & 0 deletions parser/mpPackageCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ void PackageCommon::AddToParser(ParserXBase *pParser)

// Time functions
pParser->DefineFun(new FunTimeDiff());
pParser->DefineFun(new FunCurrentTime());

// misc
pParser->DefineFun(new FunParserID);
Expand Down
24 changes: 24 additions & 0 deletions tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ exit" | ./example | grep -E "(ans =|Can't evaluate function/operator \".*\":)")
esac
}

function match_regex() {
input="$1"
regex="$2"

output=$(echo "$input
exit" | ./example | grep -E "(ans =|Can't evaluate function/operator \".*\":)")

if echo "$output" | egrep -q "$regex"; then
printf "\e[32mTest passed for input $input\e[0m\n"
else
printf "\e[31mTest failed for input $input: regex did not match\e[0m\n"
exit 1
fi
}

# Arithmetic tests
test_eval "2 + 2" "4"
test_eval "55 * 33" "1815"
Expand Down Expand Up @@ -184,6 +199,8 @@ test_eval 'timediff("02:00:00", "03:30:00")' '1.5'
test_eval 'timediff("03:30:00", "02:00:00")' '22.5'
test_eval 'timediff("02:00:00", "02:00:30")' '0.01'

test_eval 'current_time("2")' "Argument 1 of function/operator \"current_time\" is of type 's' whereas type 'i' was expected."

# Mask tests
test_eval 'mask("000-000", 123456)' '"123-456"'
test_eval 'mask("00000", 14)' '"00014"'
Expand Down Expand Up @@ -326,5 +343,12 @@ test_eval 'weekday("2019-03-21", "invalidlocale")' 'The chosen locale is not sup
test_eval 'weekday("2024-32-21")' 'Invalid format on the parameter(s). Please use two "yyyy-mm-dd" for dates OR two "yyyy-mm-ddTHH:MM" for date_times.'
test_eval 'weekday("2024-09-17", "en", "one too many params")' 'Too many parameters passed to function "weekday".'

# Regex match test
match_regex 'current_time(5)' '\b([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\b'
match_regex 'current_time()' '\b([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\b'
match_regex 'current_time(-3)' '\b([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\b'
match_regex 'current_time(-200)' '\b([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\b'


echo "All tests passed!"