diff --git a/src/core/config/scripts/portOperation.mjs b/src/core/config/scripts/portOperation.mjs
index d746be1f..4491d493 100644
--- a/src/core/config/scripts/portOperation.mjs
+++ b/src/core/config/scripts/portOperation.mjs
@@ -167,7 +167,7 @@ export default ${moduleName};
} else {
console.log("\x1b[32m\u2714\x1b[0m The run function was copied across. Double check that it was copied correctly. It may rely on other functions which have not been copied.");
}
- console.log(`\nOpen \x1b[32m${legacyFilename}\x1b[0m and copy any relevant code over. Make sure you check imports, args and highlights. Code required by multiple operations should be stored in /src/core/lib/`);
+ console.log(`\nOpen \x1b[32m${legacyFilename}\x1b[0m and copy any relevant code over. Make sure you check imports, args and highlights. Code required by multiple operations should be stored in /src/core/lib/.\n\nDont't forget to run \x1b[36mgrunt lint\x1b[0m!`);
}
diff --git a/src/core/lib/DateTime.mjs b/src/core/lib/DateTime.mjs
new file mode 100644
index 00000000..89b0e3c6
--- /dev/null
+++ b/src/core/lib/DateTime.mjs
@@ -0,0 +1,313 @@
+/**
+ * DateTime resources.
+ *
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+/**
+ * DateTime units.
+ */
+export const UNITS = ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"];
+
+/**
+ * DateTime formats.
+ */
+export const DATETIME_FORMATS = [
+ {
+ name: "Standard date and time",
+ value: "DD/MM/YYYY HH:mm:ss"
+ },
+ {
+ name: "American-style date and time",
+ value: "MM/DD/YYYY HH:mm:ss"
+ },
+ {
+ name: "International date and time",
+ value: "YYYY-MM-DD HH:mm:ss"
+ },
+ {
+ name: "Verbose date and time",
+ value: "dddd Do MMMM YYYY HH:mm:ss Z z"
+ },
+ {
+ name: "UNIX timestamp (seconds)",
+ value: "X"
+ },
+ {
+ name: "UNIX timestamp offset (milliseconds)",
+ value: "x"
+ },
+ {
+ name: "Automatic",
+ value: ""
+ },
+];
+
+/**
+ * MomentJS DateTime formatting examples.
+ */
+export const FORMAT_EXAMPLES = `Format string tokens:
+
+
+
+ Category |
+ Token |
+ Output |
+
+
+
+
+ Month |
+ M |
+ 1 2 ... 11 12 |
+
+
+ |
+ Mo |
+ 1st 2nd ... 11th 12th |
+
+
+ |
+ MM |
+ 01 02 ... 11 12 |
+
+
+ |
+ MMM |
+ Jan Feb ... Nov Dec |
+
+
+ |
+ MMMM |
+ January February ... November December |
+
+
+ Quarter |
+ Q |
+ 1 2 3 4 |
+
+
+ Day of Month |
+ D |
+ 1 2 ... 30 31 |
+
+
+ |
+ Do |
+ 1st 2nd ... 30th 31st |
+
+
+ |
+ DD |
+ 01 02 ... 30 31 |
+
+
+ Day of Year |
+ DDD |
+ 1 2 ... 364 365 |
+
+
+ |
+ DDDo |
+ 1st 2nd ... 364th 365th |
+
+
+ |
+ DDDD |
+ 001 002 ... 364 365 |
+
+
+ Day of Week |
+ d |
+ 0 1 ... 5 6 |
+
+
+ |
+ do |
+ 0th 1st ... 5th 6th |
+
+
+ |
+ dd |
+ Su Mo ... Fr Sa |
+
+
+ |
+ ddd |
+ Sun Mon ... Fri Sat |
+
+
+ |
+ dddd |
+ Sunday Monday ... Friday Saturday |
+
+
+ Day of Week (Locale) |
+ e |
+ 0 1 ... 5 6 |
+
+
+ Day of Week (ISO) |
+ E |
+ 1 2 ... 6 7 |
+
+
+ Week of Year |
+ w |
+ 1 2 ... 52 53 |
+
+
+ |
+ wo |
+ 1st 2nd ... 52nd 53rd |
+
+
+ |
+ ww |
+ 01 02 ... 52 53 |
+
+
+ Week of Year (ISO) |
+ W |
+ 1 2 ... 52 53 |
+
+
+ |
+ Wo |
+ 1st 2nd ... 52nd 53rd |
+
+
+ |
+ WW |
+ 01 02 ... 52 53 |
+
+
+ Year |
+ YY |
+ 70 71 ... 29 30 |
+
+
+ |
+ YYYY |
+ 1970 1971 ... 2029 2030 |
+
+
+ Week Year |
+ gg |
+ 70 71 ... 29 30 |
+
+
+ |
+ gggg |
+ 1970 1971 ... 2029 2030 |
+
+
+ Week Year (ISO) |
+ GG |
+ 70 71 ... 29 30 |
+
+
+ |
+ GGGG |
+ 1970 1971 ... 2029 2030 |
+
+
+ AM/PM |
+ A |
+ AM PM |
+
+
+ |
+ a |
+ am pm |
+
+
+ Hour |
+ H |
+ 0 1 ... 22 23 |
+
+
+ |
+ HH |
+ 00 01 ... 22 23 |
+
+
+ |
+ h |
+ 1 2 ... 11 12 |
+
+
+ |
+ hh |
+ 01 02 ... 11 12 |
+
+
+ Minute |
+ m |
+ 0 1 ... 58 59 |
+
+
+ |
+ mm |
+ 00 01 ... 58 59 |
+
+
+ Second |
+ s |
+ 0 1 ... 58 59 |
+
+
+ |
+ ss |
+ 00 01 ... 58 59 |
+
+
+ Fractional Second |
+ S |
+ 0 1 ... 8 9 |
+
+
+ |
+ SS |
+ 00 01 ... 98 99 |
+
+
+ |
+ SSS |
+ 000 001 ... 998 999 |
+
+
+ |
+ SSSS ... SSSSSSSSS |
+ 000[0..] 001[0..] ... 998[0..] 999[0..] |
+
+
+ Timezone |
+ z or zz |
+ EST CST ... MST PST |
+
+
+ |
+ Z |
+ -07:00 -06:00 ... +06:00 +07:00 |
+
+
+ |
+ ZZ |
+ -0700 -0600 ... +0600 +0700 |
+
+
+ Unix Timestamp |
+ X |
+ 1360013296 |
+
+
+ Unix Millisecond Timestamp |
+ x |
+ 1360013296123 |
+
+
+
`;
+
diff --git a/src/core/operations/FromUNIXTimestamp.mjs b/src/core/operations/FromUNIXTimestamp.mjs
new file mode 100644
index 00000000..90c7f120
--- /dev/null
+++ b/src/core/operations/FromUNIXTimestamp.mjs
@@ -0,0 +1,66 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import moment from "moment-timezone";
+import {UNITS} from "../lib/DateTime";
+
+/**
+ * From UNIX Timestamp operation
+ */
+class FromUNIXTimestamp extends Operation {
+
+ /**
+ * FromUNIXTimestamp constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "From UNIX Timestamp";
+ this.module = "Default";
+ this.description = "Converts a UNIX timestamp to a datetime string.
e.g. 978346800
becomes Mon 1 January 2001 11:00:00 UTC
A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).";
+ this.inputType = "number";
+ this.outputType = "string";
+ this.args = [
+ {
+ "name": "Units",
+ "type": "option",
+ "value": UNITS
+ }
+ ];
+ }
+
+ /**
+ * @param {number} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const units = args[0];
+ let d;
+
+ input = parseFloat(input);
+
+ if (units === "Seconds (s)") {
+ d = moment.unix(input);
+ return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss") + " UTC";
+ } else if (units === "Milliseconds (ms)") {
+ d = moment(input);
+ return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
+ } else if (units === "Microseconds (μs)") {
+ d = moment(input / 1000);
+ return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
+ } else if (units === "Nanoseconds (ns)") {
+ d = moment(input / 1000000);
+ return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
+ } else {
+ throw "Unrecognised unit";
+ }
+ }
+
+}
+
+export default FromUNIXTimestamp;
diff --git a/src/core/operations/ParseDateTime.mjs b/src/core/operations/ParseDateTime.mjs
new file mode 100644
index 00000000..c48f848b
--- /dev/null
+++ b/src/core/operations/ParseDateTime.mjs
@@ -0,0 +1,82 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import moment from "moment-timezone";
+import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime";
+
+/**
+ * Parse DateTime operation
+ */
+class ParseDateTime extends Operation {
+
+ /**
+ * ParseDateTime constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Parse DateTime";
+ this.module = "Default";
+ this.description = "Parses a DateTime string in your specified format and displays it in whichever timezone you choose with the following information:- Date
- Time
- Period (AM/PM)
- Timezone
- UTC offset
- Daylight Saving Time
- Leap year
- Days in this month
- Day of year
- Week number
- Quarter
Run with no input to see format string examples if required.";
+ this.inputType = "string";
+ this.outputType = "html";
+ 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": "Input timezone",
+ "type": "option",
+ "value": ["UTC"].concat(moment.tz.names())
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {html}
+ */
+ run(input, args) {
+ const inputFormat = args[1],
+ inputTimezone = args[2];
+ let date,
+ output = "";
+
+ try {
+ date = moment.tz(input, inputFormat, inputTimezone);
+ if (!date || date.format() === "Invalid date") throw Error;
+ } catch (err) {
+ return "Invalid format.\n\n" + FORMAT_EXAMPLES;
+ }
+
+ output += "Date: " + date.format("dddd Do MMMM YYYY") +
+ "\nTime: " + date.format("HH:mm:ss") +
+ "\nPeriod: " + date.format("A") +
+ "\nTimezone: " + date.format("z") +
+ "\nUTC offset: " + date.format("ZZ") +
+ "\n\nDaylight Saving Time: " + date.isDST() +
+ "\nLeap year: " + date.isLeapYear() +
+ "\nDays in this month: " + date.daysInMonth() +
+ "\n\nDay of year: " + date.dayOfYear() +
+ "\nWeek number: " + date.weekYear() +
+ "\nQuarter: " + date.quarter();
+
+ return output;
+ }
+
+}
+
+export default ParseDateTime;
diff --git a/src/core/operations/Sleep.mjs b/src/core/operations/Sleep.mjs
new file mode 100644
index 00000000..4cd71bfe
--- /dev/null
+++ b/src/core/operations/Sleep.mjs
@@ -0,0 +1,47 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+
+/**
+ * Sleep operation
+ */
+class Sleep extends Operation {
+
+ /**
+ * Sleep constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Sleep";
+ this.module = "Default";
+ this.description = "Sleep causes the recipe to wait for a specified number of milliseconds before continuing execution.";
+ this.inputType = "ArrayBuffer";
+ this.outputType = "ArrayBuffer";
+ this.args = [
+ {
+ "name": "Time (ms)",
+ "type": "number",
+ "value": 1000
+ }
+ ];
+ }
+
+ /**
+ * @param {ArrayBuffer} input
+ * @param {Object[]} args
+ * @returns {ArrayBuffer}
+ */
+ async run(input, args) {
+ const ms = args[0];
+ await new Promise(r => setTimeout(r, ms));
+ return input;
+ }
+
+}
+
+export default Sleep;
diff --git a/src/core/operations/ToUNIXTimestamp.mjs b/src/core/operations/ToUNIXTimestamp.mjs
new file mode 100644
index 00000000..1907b5a6
--- /dev/null
+++ b/src/core/operations/ToUNIXTimestamp.mjs
@@ -0,0 +1,74 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import moment from "moment-timezone";
+import {UNITS} from "../lib/DateTime";
+
+/**
+ * To UNIX Timestamp operation
+ */
+class ToUNIXTimestamp extends Operation {
+
+ /**
+ * ToUNIXTimestamp constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "To UNIX Timestamp";
+ this.module = "Default";
+ this.description = "Parses a datetime string in UTC and returns the corresponding UNIX timestamp.
e.g. Mon 1 January 2001 11:00:00
becomes 978346800
A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).";
+ this.inputType = "string";
+ this.outputType = "string";
+ this.args = [
+ {
+ "name": "Units",
+ "type": "option",
+ "value": UNITS
+ },
+ {
+ "name": "Treat as UTC",
+ "type": "boolean",
+ "value": true
+ },
+ {
+ "name": "Show parsed datetime",
+ "type": "boolean",
+ "value": true
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const [units, treatAsUTC, showDateTime] = args,
+ d = treatAsUTC ? moment.utc(input) : moment(input);
+
+ let result = "";
+
+ if (units === "Seconds (s)") {
+ result = d.unix();
+ } else if (units === "Milliseconds (ms)") {
+ result = d.valueOf();
+ } else if (units === "Microseconds (μs)") {
+ result = d.valueOf() * 1000;
+ } else if (units === "Nanoseconds (ns)") {
+ result = d.valueOf() * 1000000;
+ } else {
+ throw "Unrecognised unit";
+ }
+
+ return showDateTime ? `${result} (${d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss")} UTC)` : result.toString();
+ }
+
+}
+
+export default ToUNIXTimestamp;
diff --git a/src/core/operations/TranslateDateTimeFormat.mjs b/src/core/operations/TranslateDateTimeFormat.mjs
new file mode 100644
index 00000000..b3895978
--- /dev/null
+++ b/src/core/operations/TranslateDateTimeFormat.mjs
@@ -0,0 +1,78 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import moment from "moment-timezone";
+import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime";
+
+/**
+ * Translate DateTime Format operation
+ */
+class TranslateDateTimeFormat extends Operation {
+
+ /**
+ * TranslateDateTimeFormat constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Translate DateTime Format";
+ this.module = "Default";
+ this.description = "Parses a datetime string in one format and re-writes it in another.
Run with no input to see the relevant format string examples.";
+ this.inputType = "string";
+ this.outputType = "html";
+ 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": "Input timezone",
+ "type": "option",
+ "value": ["UTC"].concat(moment.tz.names())
+ },
+ {
+ "name": "Output format string",
+ "type": "binaryString",
+ "value": "dddd Do MMMM YYYY HH:mm:ss Z z"
+ },
+ {
+ "name": "Output timezone",
+ "type": "option",
+ "value": ["UTC"].concat(moment.tz.names())
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {html}
+ */
+ run(input, args) {
+ const [inputFormat, inputTimezone, outputFormat, outputTimezone] = args;
+ let date;
+
+ try {
+ date = moment.tz(input, inputFormat, inputTimezone);
+ if (!date || date.format() === "Invalid date") throw Error;
+ } catch (err) {
+ return "Invalid format.\n\n" + FORMAT_EXAMPLES;
+ }
+
+ return date.tz(outputTimezone).format(outputFormat);
+ }
+
+}
+
+export default TranslateDateTimeFormat;