diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index bebdd6a5e2..59492887ed 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -333,6 +333,7 @@ "Windows Filetime to UNIX Timestamp", "UNIX Timestamp to Windows Filetime", "DateTime Delta", + "Time Difference", "Extract dates", "Get Time", "Sleep" diff --git a/src/core/lib/Delim.mjs b/src/core/lib/Delim.mjs index c8cc637b5c..08be9d4f06 100644 --- a/src/core/lib/Delim.mjs +++ b/src/core/lib/Delim.mjs @@ -46,6 +46,12 @@ export const HASH_DELIM_OPTIONS = ["Line feed", "CRLF", "Space", "Comma"]; */ export const IP_DELIM_OPTIONS = ["Line feed", "CRLF", "Space", "Comma", "Semi-colon"]; +/** + * Date delimiters + */ +export const DATE_DELIM_OPTIONS = ["Line feed", "CRLF", "Comma", "Semi-colon"]; + + /** * Split delimiters. */ diff --git a/src/core/operations/TimeDifference.mjs b/src/core/operations/TimeDifference.mjs new file mode 100644 index 0000000000..f8efd8ad3c --- /dev/null +++ b/src/core/operations/TimeDifference.mjs @@ -0,0 +1,76 @@ +/** + * @author tomgond [tom.gonda@gmail.com] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import moment from "moment-timezone"; +import Utils from "../Utils.mjs"; +import {DATETIME_FORMATS} from "../lib/DateTime.mjs"; +import {DATE_DELIM_OPTIONS} from "../lib/Delim.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Calculate Time Difference operation + */ +class TimeDifference extends Operation { + + /** + * TimeDifference Constructor + */ + constructor() { + super(); + + this.name = "Time Difference"; + this.module = "DateTime"; + this.description = "Calculates the difference between two datetime values based on the provided format."; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Built in formats", + "type": "populateOption", + "value": DATETIME_FORMATS, + "target": 1 + }, + { + "name": "Input format string", + "type": "binaryString", + "value": "DD/MM/YYYY HH:mm:ss" + }, + { + "name": "Delimiter", + "type": "option", + "value": DATE_DELIM_OPTIONS, + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const dateFormat = args[1]; + const delimiter = Utils.charRep(args[2]); + input = input.replace(/[\r\n]+$/, ""); + const dates = input.split(delimiter); + if (dates.length !== 2) { + throw new OperationError("Error: Input should contain exactly two datetime values separated by a delimiter."); + } + + const date1 = moment(dates[0], dateFormat); + const date2 = moment(dates[1], dateFormat); + + if (!date1.isValid() || !date2.isValid()) { + throw new OperationError("Error: One of the provided dates is invalid."); + } + + const diff = moment.duration(date2.diff(date1)); + return `Years:${diff.years()} Months:${diff.months()} Days:${diff.days()} Hours:${diff.hours()} Minutes:${diff.minutes()} Seconds:${diff.seconds()}`; + } +} + +export default TimeDifference; diff --git a/tests/operations/tests/DateTime.mjs b/tests/operations/tests/DateTime.mjs index 16848bcc4a..480b1d178a 100644 --- a/tests/operations/tests/DateTime.mjs +++ b/tests/operations/tests/DateTime.mjs @@ -53,4 +53,26 @@ TestRegister.addTests([ }, ], }, + { + name: "Time Difference Positive", + input: "03/05/2024 13:03:22;03/06/2025 13:14:50", + expectedOutput: "Years:1 Months:1 Days:0 Hours:0 Minutes:11 Seconds:28", + recipeConfig: [ + { + op: "Time Difference", + args: ["Standard date and time", "DD/MM/YYYY HH:mm:ss", "Semi-colon"], + }, + ], + }, + { + name: "Time Difference Negative", + input: "03/05/2024 13:03:22,03/05/2024 11:30:15", + expectedOutput: "Years:0 Months:0 Days:0 Hours:-1 Minutes:-33 Seconds:-7", + recipeConfig: [ + { + op: "Time Difference", + args: ["Standard date and time", "DD/MM/YYYY HH:mm:ss", "Comma"], + }, + ], + }, ]);