diff --git a/packages/nodes-base/nodes/DateTime/V2/DateTimeV2.node.ts b/packages/nodes-base/nodes/DateTime/V2/DateTimeV2.node.ts index 74bb1e9ee7..adc8b44483 100644 --- a/packages/nodes-base/nodes/DateTime/V2/DateTimeV2.node.ts +++ b/packages/nodes-base/nodes/DateTime/V2/DateTimeV2.node.ts @@ -9,8 +9,6 @@ import type { } from 'n8n-workflow'; import { deepCopy, NodeOperationError } from 'n8n-workflow'; -import set from 'lodash.set'; - import moment from 'moment-timezone'; function parseDateByFormat(this: IExecuteFunctions, value: string, fromFormat: string) { @@ -58,322 +56,41 @@ export class DateTimeV2 implements INodeType { inputs: ['main'], outputs: ['main'], properties: [ - { - displayName: - "More powerful date functionality is available in expressions,
e.g. {{ $now.plus(1, 'week') }}", - name: 'noticeDateTime', - type: 'notice', - default: '', - }, { displayName: 'Action', name: 'action', type: 'options', options: [ { - name: 'Calculate a Date', - description: 'Add or subtract time from a date', - value: 'calculate', - action: 'Add or subtract time from a date', + name: 'Add to a Date', + value: 'addToDate', + }, + { + name: 'Extract Part of a Date', + value: 'extractDate', }, { name: 'Format a Date', - description: 'Convert a date to a different format', - value: 'format', - action: 'Convert a date to a different format', - }, - ], - default: 'format', - }, - { - displayName: 'Value', - name: 'value', - displayOptions: { - show: { - action: ['format'], - }, - }, - type: 'string', - default: '', - description: 'The value that should be converted', - required: true, - }, - { - displayName: 'Property Name', - name: 'dataPropertyName', - type: 'string', - default: 'data', - required: true, - displayOptions: { - show: { - action: ['format'], - }, - }, - description: 'Name of the property to which to write the converted date', - }, - { - displayName: 'Custom Format', - name: 'custom', - displayOptions: { - show: { - action: ['format'], - }, - }, - type: 'boolean', - default: false, - description: 'Whether a predefined format should be selected or custom format entered', - }, - { - displayName: 'To Format', - name: 'toFormat', - displayOptions: { - show: { - action: ['format'], - custom: [true], - }, - }, - type: 'string', - default: '', - placeholder: 'YYYY-MM-DD', - description: 'The format to convert the date to', - }, - { - displayName: 'To Format', - name: 'toFormat', - type: 'options', - displayOptions: { - show: { - action: ['format'], - custom: [false], - }, - }, - // eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items - options: [ - { - name: 'MM/DD/YYYY', - value: 'MM/DD/YYYY', - description: 'Example: 09/04/1986', - }, - { - name: 'YYYY/MM/DD', - value: 'YYYY/MM/DD', - description: 'Example: 1986/04/09', - }, - { - name: 'MMMM DD YYYY', - value: 'MMMM DD YYYY', - description: 'Example: April 09 1986', - }, - { - name: 'MM-DD-YYYY', - value: 'MM-DD-YYYY', - description: 'Example: 09-04-1986', - }, - { - name: 'YYYY-MM-DD', - value: 'YYYY-MM-DD', - description: 'Example: 1986-04-09', - }, - { - name: 'Unix Timestamp', - value: 'X', - description: 'Example: 513388800.879', - }, - { - name: 'Unix Ms Timestamp', - value: 'x', - description: 'Example: 513388800', - }, - ], - default: 'MM/DD/YYYY', - description: 'The format to convert the date to', - }, - { - displayName: 'Options', - name: 'options', - displayOptions: { - show: { - action: ['format'], - }, - }, - type: 'collection', - placeholder: 'Add Option', - default: {}, - options: [ - { - displayName: 'From Format', - name: 'fromFormat', - type: 'string', - default: '', - description: 'In case the input format is not recognized you can provide the format', - }, - { - displayName: 'From Timezone Name or ID', - name: 'fromTimezone', - type: 'options', - typeOptions: { - loadOptionsMethod: 'getTimezones', - }, - default: 'UTC', - description: - 'The timezone to convert from. Choose from the list, or specify an ID using an expression.', - }, - { - displayName: 'To Timezone Name or ID', - name: 'toTimezone', - type: 'options', - typeOptions: { - loadOptionsMethod: 'getTimezones', - }, - default: 'UTC', - description: - 'The timezone to convert to. Choose from the list, or specify an ID using an expression.', - }, - ], - }, - { - displayName: 'Date Value', - name: 'value', - displayOptions: { - show: { - action: ['calculate'], - }, - }, - type: 'string', - default: '', - description: 'The date string or timestamp from which you want to add/subtract time', - required: true, - }, - { - displayName: 'Operation', - name: 'operation', - displayOptions: { - show: { - action: ['calculate'], - }, - }, - type: 'options', - noDataExpression: true, - options: [ - { - name: 'Add', - value: 'add', - description: 'Add time to Date Value', - action: 'Add time to Date Value', - }, - { - name: 'Subtract', - value: 'subtract', - description: 'Subtract time from Date Value', - action: 'Subtract time from Date Value', - }, - ], - default: 'add', - required: true, - }, - { - displayName: 'Duration', - name: 'duration', - displayOptions: { - show: { - action: ['calculate'], - }, - }, - type: 'number', - typeOptions: { - minValue: 0, - }, - default: 0, - required: true, - description: - 'E.g. enter “10” then select “Days” if you want to add 10 days to Date Value.', - }, - { - displayName: 'Time Unit', - name: 'timeUnit', - description: 'Time unit for Duration parameter above', - displayOptions: { - show: { - action: ['calculate'], - }, - }, - type: 'options', - // eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items - options: [ - { - name: 'Quarters', - value: 'quarters', - }, - { - name: 'Years', - value: 'years', - }, - { - name: 'Months', - value: 'months', - }, - { - name: 'Weeks', - value: 'weeks', - }, - { - name: 'Days', - value: 'days', - }, - { - name: 'Hours', - value: 'hours', - }, - { - name: 'Minutes', - value: 'minutes', - }, - { - name: 'Seconds', - value: 'seconds', - }, - { - name: 'Milliseconds', - value: 'milliseconds', - }, - ], - default: 'days', - required: true, - }, - { - displayName: 'Property Name', - name: 'dataPropertyName', - type: 'string', - default: 'data', - required: true, - displayOptions: { - show: { - action: ['calculate'], - }, - }, - description: 'Name of the output property to which to write the converted date', - }, - { - displayName: 'Options', - name: 'options', - type: 'collection', - placeholder: 'Add Option', - default: {}, - displayOptions: { - show: { - action: ['calculate'], - }, - }, - options: [ - { - displayName: 'From Format', - name: 'fromFormat', - type: 'string', - default: '', - description: - 'Format for parsing the value as a date. If unrecognized, specify the format for the value.', + value: 'formatDate', + }, + { + name: 'Get Current Date', + value: 'getCurrentDate', + }, + { + name: 'Get Time Between Dates', + value: 'getTimeBetweenDates', + }, + { + name: 'Round a Date', + value: 'roundDate', + }, + { + name: 'Subtract From a Date', + value: 'subtractFromDate', }, ], + default: 'getCurrentDate', }, ], }; @@ -398,159 +115,5 @@ export class DateTimeV2 implements INodeType { }, }; - async execute(this: IExecuteFunctions): Promise { - const items = this.getInputData(); - const length = items.length; - const returnData: INodeExecutionData[] = []; - - const workflowTimezone = this.getTimezone(); - let item: INodeExecutionData; - - for (let i = 0; i < length; i++) { - try { - const action = this.getNodeParameter('action', 0) as string; - item = items[i]; - - if (action === 'format') { - const currentDate = this.getNodeParameter('value', i) as string; - const dataPropertyName = this.getNodeParameter('dataPropertyName', i); - const toFormat = this.getNodeParameter('toFormat', i) as string; - const options = this.getNodeParameter('options', i); - let newDate; - - if (currentDate === undefined) { - continue; - } - if ( - options.fromFormat === undefined && - !moment(currentDate as string | number).isValid() - ) { - throw new NodeOperationError( - this.getNode(), - 'The date input format could not be recognized. Please set the "From Format" field', - { itemIndex: i }, - ); - } - - if (Number.isInteger(currentDate as unknown as number)) { - newDate = moment.unix(currentDate as unknown as number); - } else { - if (options.fromTimezone || options.toTimezone) { - const fromTimezone = options.fromTimezone || workflowTimezone; - if (options.fromFormat) { - newDate = moment.tz( - currentDate, - options.fromFormat as string, - fromTimezone as string, - ); - } else { - newDate = moment.tz(currentDate, fromTimezone as string); - } - } else { - if (options.fromFormat) { - newDate = moment(currentDate, options.fromFormat as string); - } else { - newDate = moment(currentDate); - } - } - } - - if (options.toTimezone || options.fromTimezone) { - // If either a source or a target timezone got defined the - // timezone of the date has to be changed. If a target-timezone - // is set use it else fall back to workflow timezone. - newDate = newDate.tz((options.toTimezone as string) || workflowTimezone); - } - - newDate = newDate.format(toFormat); - - let newItem: INodeExecutionData; - if (dataPropertyName.includes('.')) { - // Uses dot notation so copy all data - newItem = { - json: deepCopy(item.json), - pairedItem: { - item: i, - }, - }; - } else { - // Does not use dot notation so shallow copy is enough - newItem = { - json: { ...item.json }, - pairedItem: { - item: i, - }, - }; - } - - if (item.binary !== undefined) { - newItem.binary = item.binary; - } - - set(newItem, `json.${dataPropertyName}`, newDate); - - returnData.push(newItem); - } - - if (action === 'calculate') { - const dateValue = this.getNodeParameter('value', i) as string; - const operation = this.getNodeParameter('operation', i) as 'add' | 'subtract'; - const duration = this.getNodeParameter('duration', i) as number; - const timeUnit = this.getNodeParameter('timeUnit', i) as moment.DurationInputArg2; - const { fromFormat } = this.getNodeParameter('options', i) as { fromFormat?: string }; - const dataPropertyName = this.getNodeParameter('dataPropertyName', i); - - const newDate = fromFormat - ? parseDateByFormat.call(this, dateValue, fromFormat) - : parseDateByDefault.call(this, dateValue); - - operation === 'add' - ? newDate.add(duration, timeUnit).utc().format() - : newDate.subtract(duration, timeUnit).utc().format(); - - let newItem: INodeExecutionData; - if (dataPropertyName.includes('.')) { - // Uses dot notation so copy all data - newItem = { - json: deepCopy(item.json), - pairedItem: { - item: i, - }, - }; - } else { - // Does not use dot notation so shallow copy is enough - newItem = { - json: { ...item.json }, - pairedItem: { - item: i, - }, - }; - } - - if (item.binary !== undefined) { - newItem.binary = item.binary; - } - - set(newItem, `json.${dataPropertyName}`, newDate.toISOString()); - - returnData.push(newItem); - } - } catch (error) { - if (this.continueOnFail()) { - returnData.push({ - json: { - error: error.message, - }, - pairedItem: { - item: i, - }, - }); - continue; - } - throw error; - } - } - - return this.prepareOutputData(returnData); - } + async execute(this: IExecuteFunctions): Promise {} }