using DevLab.JmesPath.Functions;
using DevLab.JmesPath.Utils;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
namespace afd_2._0.webapi.example.JMESPathCustomFunctions
{
///
/// This class provides JMESPath Custom Function ageAtReferenceDate, for a YYY-MM-DD formattted date string.
///
public class AgeAtReferenceDateFunction : JmesPathFunction
{
///
/// JMESPath custom function Name
///
const string cFunctionName = "ageAtReferenceDate";
///
/// JMESPath custom function number of arguments
///
const int cNumberOfArguments = 2;
///
/// regex to validate the subjectDateString argument
///
const string cDateRegex = @"^(?[0-9]+)[-](?[0-9]+)[-](?[0-9]+)$";
///
/// Define Custom Function
///
public AgeAtReferenceDateFunction()
: base(cFunctionName, cNumberOfArguments)
{
}
///
/// Validate this custom function arguments
///
///
///
public override void Validate(params JmesPathFunctionArgument[] arguments)
{
base.Validate(arguments);
if (arguments.Length != cNumberOfArguments)
{
throw new Exception($"Error: invalid-arity, JmesPath Custom Function '{nameof(AgeAtReferenceDateFunction)}' expects {cNumberOfArguments} argument(s), but gets {arguments.Length} arguments.");
}
var subjectDateString = arguments[0];
var dateRegex = new Regex(cDateRegex);
if (arguments[0].Token.GetTokenType() != "string")
{
throw new Exception($"Error: invalid-value, JmesPath Custom Function '{nameof(AgeAtReferenceDateFunction)}' expects the subjectDate to be a string.");
}
var referenceDateString = arguments[1];
if (arguments[1].Token.GetTokenType() != "string")
{
throw new Exception($"Error: invalid-value, JmesPath Custom Function '{nameof(AgeAtReferenceDateFunction)}' expects the referenceDate to be a string.");
}
var subjectDateValue = subjectDateString.Token.Value() ?? string.Empty;
var referenceDateValue = referenceDateString.Token.Value() ?? string.Empty;
if (!dateRegex.Match(subjectDateValue).Success)
{
throw new Exception($"Error: invalid-value, JmesPath Custom Function '{nameof(AgeAtReferenceDateFunction)}' expects the subjectDate '{subjectDateValue}' to be formatted as 'yyyy-dd-mm'.");
};
if (!dateRegex.Match(referenceDateValue).Success)
{
throw new Exception($"Error: invalid-value, JmesPath Custom Function '{nameof(AgeAtReferenceDateFunction)}' expects the referenceDate '{referenceDateValue}' to be formatted as 'yyyy-dd-mm'.");
};
if (!DateOnly.TryParse(subjectDateValue, out var subjectDate))
{
throw new Exception($"Error: invalid-value, JmesPath Custom Function '{nameof(AgeAtReferenceDateFunction)}' found an invalid subjectDate '{subjectDateValue}'.");
}
if (!DateOnly.TryParse(referenceDateValue, out var referenceDate))
{
throw new Exception($"Error: invalid-value, JmesPath Custom Function '{nameof(AgeAtReferenceDateFunction)}' found an invalid referenceDate '{referenceDateValue}'.");
}
if (referenceDate < subjectDate)
{
throw new Exception($"Error: invalid-values, JmesPath Custom Function '{nameof(AgeAtReferenceDateFunction)}' referenceDate must be >= subjectdate '{referenceDateValue}'.");
}
}
///
/// Calculate subject age in years at reference date.
///
///
/// arguments[0] subjectDate in "YYYY-MM-DD" format.
/// arguments[1] referenceDate in "YYYY-MM-DD" format.
///
/// Subject age in full years at reference date.
///
public override JToken Execute(params JmesPathFunctionArgument[] arguments)
{
var regex = new Regex(cDateRegex);
// Determine subject date parts
var subjectDateString = arguments[0].Token.Value() ?? string.Empty;
var subjectMatch = regex.Match(subjectDateString);
var subjectYears = int.Parse(subjectMatch.Groups["years"].Value);
var subjectMonths = int.Parse(subjectMatch.Groups["months"].Value);
var subjectDays = int.Parse(subjectMatch.Groups["days"].Value);
// Determine reference date parts
var referenceDateString = arguments[1].Token.Value() ?? string.Empty;
var referenceMatch = regex.Match(referenceDateString);
var referenceYears = int.Parse(referenceMatch.Groups["years"].Value);
var referenceMonths = int.Parse(referenceMatch.Groups["months"].Value);
var referenceDays = int.Parse(referenceMatch.Groups["days"].Value);
// Calculate subject date and reference date values
var subjectDateValue = 100 * (100 * subjectYears + subjectMonths) + subjectDays;
var referenceDateValue = 100 * (100 * referenceYears + referenceMonths) + referenceDays;
// Calculate subject date in years at reference date.
var ageInYears = (referenceDateValue - subjectDateValue) / 10000;
return new JValue(ageInYears);
}
}
}