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); } } }