diff --git a/packages/editor-ui/src/components/CodeNodeEditor/completions/luxon.completions.ts b/packages/editor-ui/src/components/CodeNodeEditor/completions/luxon.completions.ts index 920a6234b5f7f..4935f220b34f8 100644 --- a/packages/editor-ui/src/components/CodeNodeEditor/completions/luxon.completions.ts +++ b/packages/editor-ui/src/components/CodeNodeEditor/completions/luxon.completions.ts @@ -1,6 +1,9 @@ import { escape } from '../utils'; import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete'; import { defineComponent } from 'vue'; +import { createInfoBoxRenderer } from '@/plugins/codemirror/completions/infoBoxRenderer'; +import { luxonStaticDocs } from '@/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.static.docs'; +import { luxonInstanceDocs } from '@/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.instance.docs'; export const luxonCompletions = defineComponent({ methods: { @@ -14,27 +17,9 @@ export const luxonCompletions = defineComponent({ if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null; - const options: Completion[] = this.luxonInstanceGetters().map(([getter, description]) => { - return { - label: `${matcher}.${getter}`, - type: 'function', - info: description, - }; - }); - - options.push( - ...this.luxonInstanceMethods().map(([method, description]) => { - return { - label: `${matcher}.${method}()`, - type: 'function', - info: description, - }; - }), - ); - return { from: preCursor.from, - options, + options: this.instanceCompletions(matcher), }; }, @@ -48,27 +33,9 @@ export const luxonCompletions = defineComponent({ if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null; - const options: Completion[] = this.luxonInstanceGetters().map(([getter, description]) => { - return { - label: `${matcher}.${getter}`, - type: 'function', - info: description, - }; - }); - - options.push( - ...this.luxonInstanceMethods().map(([method, description]) => { - return { - label: `${matcher}.${method}()`, - type: 'function', - info: description, - }; - }), - ); - return { from: preCursor.from, - options, + options: this.instanceCompletions(matcher), }; }, @@ -82,206 +49,40 @@ export const luxonCompletions = defineComponent({ if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null; - const options: Completion[] = this.luxonDateTimeStaticMethods().map( - ([method, description]) => { + const options: Completion[] = Object.entries(luxonStaticDocs.functions) + .filter(([_, { doc }]) => doc && !doc.hidden) + .map(([method, { doc }]) => { return { label: `DateTime.${method}()`, type: 'function', - info: description, + info: createInfoBoxRenderer(doc, true), }; - }, - ); + }); return { from: preCursor.from, options, }; }, - - luxonDateTimeStaticMethods() { - return Object.entries({ - now: this.$locale.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.now'), - local: this.$locale.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.local'), - utc: this.$locale.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.utc'), - fromJSDate: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromJSDate', - ), - fromMillis: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromMillis', - ), - fromSeconds: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSeconds', - ), - fromObject: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromObject', - ), - fromISO: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromISO', - ), - fromRFC2822: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromRFC2822', - ), - fromHTTP: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromHTTP', - ), - fromFormat: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromFormat', - ), - fromSQL: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSQL', - ), - invalid: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.invalid', - ), - isDateTime: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.isDateTime', - ), - }); - }, - - luxonInstanceGetters() { - return Object.entries({ - isValid: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.isValid'), - invalidReason: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.invalidReason', - ), - invalidExplanation: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.invalidExplanation', - ), - locale: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.locale'), - numberingSystem: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.numberingSystem', - ), - outputCalendar: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.outputCalendar', - ), - zone: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.zone'), - zoneName: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.zoneName'), - year: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.year'), - quarter: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.quarter'), - month: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.month'), - day: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.day'), - hour: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.hour'), - minute: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.minute'), - second: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.second'), - millisecond: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.millisecond', - ), - weekYear: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekYear'), - weekNumber: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.weekNumber', - ), - weekday: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekday'), - ordinal: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.ordinal'), - monthShort: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.monthShort', - ), - monthLong: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.monthLong', - ), - weekdayShort: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.weekdayShort', - ), - weekdayLong: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.weekdayLong', - ), - offset: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.offset'), - offsetNumber: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.offsetNumber', - ), - offsetNameShort: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.offsetNameShort', - ), - offsetNameLong: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.offsetNameLong', - ), - isOffsetFixed: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.isOffsetFixed', - ), - isInDST: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.isInDST'), - isInLeapYear: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.isInLeapYear', - ), - daysInMonth: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.daysInMonth', - ), - daysInYear: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.daysInYear', - ), - weeksInWeekYear: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.weeksInWeekYear', - ), - }); - }, - - luxonInstanceMethods() { - return Object.entries({ - toUTC: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toUTC'), - toLocal: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toLocal'), - setZone: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.setZone'), - setLocale: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.setLocale', - ), - set: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.set'), - plus: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.plus'), - minus: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.minus'), - startOf: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.startOf'), - endOf: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.endOf'), - toFormat: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toFormat'), - toLocaleString: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toLocaleString', - ), - toLocaleParts: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toLocaleParts', - ), - toISO: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toISO'), - toISODate: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toISODate', - ), - toISOWeekDate: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toISOWeekDate', - ), - toISOTime: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toISOTime', - ), - toRFC2822: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toRFC2822', - ), - toHTTP: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toHTTP'), - toSQLDate: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toSQLDate', - ), - toSQLTime: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toSQLTime', - ), - toSQL: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toSQL'), - toString: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toString'), - valueOf: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.valueOf'), - toMillis: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toMillis'), - toSeconds: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toSeconds', - ), - toUnixInteger: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toUnixInteger', - ), - toJSON: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toJSON'), - toBSON: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toBSON'), - toObject: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toObject'), - toJsDate: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.toJsDate'), - diff: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.diff'), - diffNow: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.diffNow'), - until: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.until'), - hasSame: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.hasSame'), - equals: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.equals'), - toRelative: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toRelative', - ), - toRelativeCalendar: this.$locale.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toRelativeCalendar', - ), - min: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.min'), - max: this.$locale.baseText('codeNodeEditor.completer.luxon.instanceMethods.max'), - }); + instanceCompletions(matcher: string): Completion[] { + return Object.entries(luxonInstanceDocs.properties) + .filter(([_, { doc }]) => doc && !doc.hidden) + .map(([getter, { doc }]) => { + return { + label: `${matcher}.${getter}`, + info: createInfoBoxRenderer(doc), + }; + }) + .concat( + Object.entries(luxonInstanceDocs.functions) + .filter(([_, { doc }]) => doc && !doc.hidden) + .map(([method, { doc }]) => { + return { + label: `${matcher}.${method}()`, + info: createInfoBoxRenderer(doc, true), + }; + }), + ); }, }, }); diff --git a/packages/editor-ui/src/plugins/codemirror/completions/constants.ts b/packages/editor-ui/src/plugins/codemirror/completions/constants.ts index aad2c0a310a86..1db422594b73b 100644 --- a/packages/editor-ui/src/plugins/codemirror/completions/constants.ts +++ b/packages/editor-ui/src/plugins/codemirror/completions/constants.ts @@ -296,7 +296,7 @@ export const STRING_RECOMMENDED_OPTIONS = [ 'length', ]; -export const LUXON_RECOMMENDED_OPTIONS = ['format()', 'minus()', 'plus()', 'diff()', 'extract()']; +export const LUXON_RECOMMENDED_OPTIONS = ['format()', 'minus()', 'plus()', 'diffTo()', 'extract()']; export const OBJECT_RECOMMENDED_OPTIONS = ['keys()', 'values()', 'isEmpty()', 'hasField()']; export const ARRAY_RECOMMENDED_OPTIONS = ['length', 'last()', 'includes()', 'map()', 'filter()']; export const ARRAY_NUMBER_ONLY_METHODS = ['max()', 'min()', 'sum()', 'average()']; diff --git a/packages/editor-ui/src/plugins/codemirror/completions/datatype.completions.ts b/packages/editor-ui/src/plugins/codemirror/completions/datatype.completions.ts index 37e2d48abc027..733da5d7e0727 100644 --- a/packages/editor-ui/src/plugins/codemirror/completions/datatype.completions.ts +++ b/packages/editor-ui/src/plugins/codemirror/completions/datatype.completions.ts @@ -756,7 +756,6 @@ export const luxonInstanceOptions = ({ name: key, isFunction, docs: luxonInstanceDocs, - translations: i18n.luxonInstance, includeHidden, transformLabel, }) as Completion; @@ -778,7 +777,6 @@ export const luxonStaticOptions = () => { name: key, isFunction: true, docs: luxonStaticDocs, - translations: i18n.luxonStatic, }) as Completion; }) .filter(Boolean), @@ -788,14 +786,12 @@ export const luxonStaticOptions = () => { const createLuxonAutocompleteOption = ({ name, docs, - translations, isFunction = false, includeHidden = false, transformLabel = (label) => label, }: { name: string; docs: NativeDoc; - translations: Record; isFunction?: boolean; includeHidden?: boolean; transformLabel?: (label: string) => string; @@ -835,8 +831,7 @@ const createLuxonAutocompleteOption = ({ option.info = createCompletionOption({ name, isFunction, - // Add translated description - doc: { ...doc, description: translations[name] } as DocMetadata, + doc, transformLabel, }).info; return option; diff --git a/packages/editor-ui/src/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.instance.docs.ts b/packages/editor-ui/src/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.instance.docs.ts index ef4d7d07380a9..16d3d1befc88c 100644 --- a/packages/editor-ui/src/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.instance.docs.ts +++ b/packages/editor-ui/src/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.instance.docs.ts @@ -1,16 +1,18 @@ import type { NativeDoc } from 'n8n-workflow'; +import { i18n } from '@/plugins/i18n'; // Autocomplete documentation definition for DateTime instance props and methods -// Descriptions are added dynamically so they can be localized export const luxonInstanceDocs: Required = { typeName: 'DateTime', properties: { day: { doc: { name: 'day', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.day'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeday', returnType: 'number', + examples: [{ example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.day", evaluated: '30' }], }, }, daysInMonth: { @@ -34,57 +36,99 @@ export const luxonInstanceDocs: Required = { hour: { doc: { name: 'hour', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.hour'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimehour', returnType: 'number', + examples: [{ example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.hour", evaluated: '18' }], }, }, locale: { doc: { name: 'locale', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.locale'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimelocale', returnType: 'string', + examples: [{ example: '$now.locale', evaluated: "'en-US'" }], }, }, millisecond: { doc: { name: 'millisecond', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.millisecond'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemillisecond', returnType: 'number', + examples: [ + { + example: "dt = '2024-03-30T18:49:07.234'.toDateTime()\ndt.millisecond", + evaluated: '234', + }, + ], }, }, minute: { doc: { name: 'minute', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.minute'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeminute', returnType: 'number', + examples: [ + { example: "dt = '2024-03-30T18:49:07.234'.toDateTime()\ndt.minute", evaluated: '49' }, + ], }, }, month: { doc: { name: 'month', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.month'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemonth', returnType: 'number', + examples: [ + { example: "dt = '2024-03-30T18:49:07.234'.toDateTime()\ndt.month", evaluated: '3' }, + ], }, }, monthLong: { doc: { name: 'monthLong', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.monthLong'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemonthlong', returnType: 'string', + examples: [ + { + example: "dt = '2024-03-30T18:49:07.234'.toDateTime()\ndt.monthLong", + evaluated: "'March'", + }, + { + example: "dt = '2024-03-30T18:49:07.234'.toDateTime()\ndt.setLocale('de-DE').monthLong", + evaluated: "'März'", + }, + ], }, }, monthShort: { doc: { name: 'monthShort', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.monthShort'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemonthshort', returnType: 'string', + examples: [ + { + example: "dt = '2024-03-30T18:49:07.234'.toDateTime()\ndt.monthShort", + evaluated: "'Mar'", + }, + { + example: + "dt = '2024-03-30T18:49:07.234'.toDateTime()\ndt.setLocale('de-DE').monthShort", + evaluated: "'Mär'", + }, + ], }, }, numberingSystem: { @@ -144,49 +188,83 @@ export const luxonInstanceDocs: Required = { quarter: { doc: { name: 'quarter', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.quarter'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimequarter', returnType: 'number', + examples: [ + { example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.quarter", evaluated: '1' }, + { example: "'2024-12-01T18:49'.toDateTime().quarter", evaluated: '4' }, + ], }, }, second: { doc: { name: 'second', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.second'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimesecond', returnType: 'number', + examples: [ + { example: "dt = '2024-03-30T18:49:07.234'.toDateTime()\ndt.second", evaluated: '7' }, + ], }, }, weekday: { doc: { name: 'weekday', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekday'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweekday', returnType: 'number', + examples: [{ example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.weekday", evaluated: '6' }], }, }, weekdayLong: { doc: { name: 'weekdayLong', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekdayLong'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweekdaylong', returnType: 'string', + examples: [ + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.weekdayLong", + evaluated: "'Saturday'", + }, + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.setLocale('de-DE').weekdayLong", + evaluated: "'Samstag'", + }, + ], }, }, weekdayShort: { doc: { name: 'weekdayShort', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekdayShort'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweekdayshort', returnType: 'string', + examples: [ + { example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.weekdayShort", evaluated: "'Sat'" }, + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.setLocale('fr-FR').weekdayShort", + evaluated: "'sam.'", + }, + ], }, }, weekNumber: { doc: { name: 'weekNumber', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekNumber'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweeknumber', returnType: 'number', + examples: [ + { example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.weekNumber", evaluated: '13' }, + ], }, }, weeksInWeekYear: { @@ -210,17 +288,23 @@ export const luxonInstanceDocs: Required = { year: { doc: { name: 'year', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.year'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeyear', returnType: 'number', + examples: [{ example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.year", evaluated: '2024' }], }, }, zone: { doc: { name: 'zone', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.zone'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimezone', returnType: 'Zone', + examples: [ + { example: '$now.zone', evaluated: '{ zoneName: "Europe/Berlin", valid: true }' }, + ], }, }, zoneName: { @@ -235,6 +319,7 @@ export const luxonInstanceDocs: Required = { isInDST: { doc: { name: 'isInDST', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.isInDST'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeisindst', returnType: 'boolean', @@ -243,9 +328,14 @@ export const luxonInstanceDocs: Required = { isInLeapYear: { doc: { name: 'isInLeapYear', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.isInLeapYear'), section: 'query', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeisinleapyear', returnType: 'boolean', + examples: [ + { example: "'2024'.toDateTime().isInLeapYear", evaluated: 'true' }, + { example: "'2025'.toDateTime().isInLeapYear", evaluated: 'false' }, + ], }, }, isOffsetFixed: { @@ -271,74 +361,121 @@ export const luxonInstanceDocs: Required = { diff: { doc: { name: 'diff', + hidden: true, section: 'compare', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimediff', returnType: 'Duration', args: [ { name: 'other', type: 'DateTime' }, - { name: 'unit', type: 'string|string[]' }, - { name: 'opts', type: 'object' }, + { name: 'unit', type: 'string | string[]' }, + { name: 'options', type: 'Object' }, ], }, }, diffNow: { doc: { name: 'diffNow', + hidden: true, section: 'compare', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimediffnow', returnType: 'Duration', args: [ - { name: 'unit', type: 'string|string[]' }, - { name: 'opts', type: 'object' }, + { name: 'unit', type: 'string | string[]' }, + { name: 'options', type: 'Object' }, ], }, }, endOf: { doc: { name: 'endOf', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.endOf'), section: 'edit', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeendof', returnType: 'DateTime', - args: [{ name: 'unit', type: 'string', default: "'month'" }], + args: [ + { + name: 'unit', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.endOf.args.unit', + ), + type: 'string', + }, + { + name: 'options', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.endOf.args.opts', + ), + default: '{}', + type: 'Object', + }, + ], + examples: [ + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.endOf('month')", + evaluated: '[DateTime: 2024-03-31T23:59:59.999Z]', + }, + ], }, }, equals: { doc: { name: 'equals', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.equals'), section: 'compare', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeequals', returnType: 'boolean', - args: [{ name: 'other', type: 'DateTime' }], + args: [ + { + name: 'other', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.equals.args.other', + ), + type: 'DateTime', + }, + ], + examples: [ + { + example: + "dt = '2024-03-20T18:49+02:00'.toDateTime()\ndt.equals('2024-03-20T19:49+02:00'.toDateTime())", + evaluated: 'false', + }, + ], }, }, hasSame: { doc: { name: 'hasSame', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.hasSame'), section: 'compare', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimehassame', returnType: 'boolean', args: [ - { name: 'other', type: 'DateTime' }, - { name: 'unit', type: 'string' }, + { + name: 'other', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.hasSame.args.other', + ), + type: 'DateTime', + }, + { + name: 'unit', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.hasSame.args.unit', + ), + type: 'string', + }, + ], + examples: [ + { + example: "'2024-03-20'.toDateTime().hasSame('2024-03-18'.toDateTime(), 'month')", + evaluated: 'true', + }, + { + example: "'1982-03-20'.toDateTime().hasSame('2024-03-18'.toDateTime(), 'month')", + evaluated: 'false', + }, ], - }, - }, - minus: { - doc: { - name: 'minus', - section: 'edit', - docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeminus', - returnType: 'DateTime', - args: [{ name: 'duration', type: 'Duration|object|number' }], - }, - }, - plus: { - doc: { - name: 'plus', - section: 'edit', - docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeplus', - returnType: 'DateTime', - args: [{ name: 'duration', type: 'Duration|object|number' }], }, }, reconfigure: { @@ -348,7 +485,7 @@ export const luxonInstanceDocs: Required = { hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimereconfigure', returnType: 'DateTime', - args: [{ name: 'properties', type: 'object' }], + args: [{ name: 'properties', type: 'Object' }], }, }, resolvedLocaleOptions: { @@ -357,47 +494,132 @@ export const luxonInstanceDocs: Required = { section: 'other', hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeresolvedlocaleoptions', - returnType: 'object', - args: [{ name: 'opts', type: 'object' }], + returnType: 'Object', + args: [{ name: 'options', type: 'Object' }], }, }, set: { doc: { name: 'set', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.set'), section: 'edit', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeset', returnType: 'DateTime', - args: [{ name: 'values', type: 'object' }], + args: [ + { + name: 'values', + optional: false, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.set.args.values', + ), + type: 'Object', + }, + ], + examples: [ + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.set({ year:1982, month:10 })", + evaluated: '[DateTime: 1982-10-20T18:49:00.000Z]', + }, + ], }, }, setLocale: { doc: { name: 'setLocale', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.setLocale'), section: 'edit', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimesetlocale', returnType: 'DateTime', - args: [{ name: 'locale', type: 'any' }], + args: [ + { + name: 'locale', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.setLocale.args.locale', + ), + type: 'string', + }, + ], + examples: [ + { + example: "$now.setLocale('de-DE').toLocaleString({ dateStyle: 'long' })", + evaluated: "'5. Oktober 2024'", + }, + { + example: "$now.setLocale('fr-FR').toLocaleString({ dateStyle: 'long' })", + evaluated: "'5 octobre 2024'", + }, + ], }, }, setZone: { doc: { name: 'setZone', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.setZone'), section: 'edit', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimesetzone', returnType: 'DateTime', args: [ - { name: 'zone', type: 'string|Zone' }, - { name: 'opts', type: 'object' }, + { + name: 'zone', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.setZone.args.zone', + ), + default: '"local"', + type: 'string', + }, + { + name: 'options', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.setZone.args.opts', + ), + type: 'Object', + }, + ], + examples: [ + { + example: + "dt = '2024-01-01T00:00:00.000+02:00'.toDateTime()\ndt.setZone('America/Buenos_Aires')", + evaluated: '[DateTime: 2023-12-31T19:00:00.000-03:00]', + }, + { + example: "dt = '2024-01-01T00:00:00.000+02:00'.toDateTime()\ndt.setZone('UTC+7')", + evaluated: '[DateTime: 2024-01-01T05:00:00.000+07:00]', + }, ], }, }, startOf: { doc: { name: 'startOf', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.startOf'), section: 'edit', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimestartof', returnType: 'DateTime', - args: [{ name: 'unit', type: 'string', default: "'month'" }], + args: [ + { + name: 'unit', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.startOf.args.unit', + ), + type: 'string', + }, + { + name: 'options', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.startOf.args.opts', + ), + type: 'Object', + }, + ], + examples: [ + { + example: "'2024-03-20T18:49'.toDateTime().startOf('month')", + evaluated: '[DateTime: 2024-03-01T00:00:00.000Z]', + }, + ], }, }, toBSON: { @@ -418,7 +640,7 @@ export const luxonInstanceDocs: Required = { returnType: 'string', args: [ { name: 'fmt', type: 'string' }, - { name: 'opts', type: 'object' }, + { name: 'options', type: 'Object' }, ], }, }, @@ -434,10 +656,21 @@ export const luxonInstanceDocs: Required = { toISO: { doc: { name: 'toISO', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.toISO'), section: 'format', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoiso', returnType: 'string', - args: [{ name: 'opts', type: 'object' }], + args: [ + { + name: 'options', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toISO.args.opts', + ), + type: 'Object', + }, + ], + examples: [{ example: '$now.toISO()', evaluated: "'2024-04-05T18:44:55.525+02:00'" }], }, }, toISODate: { @@ -447,7 +680,7 @@ export const luxonInstanceDocs: Required = { hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoisodate', returnType: 'string', - args: [{ name: 'opts', type: 'object' }], + args: [{ name: 'options', type: 'Object' }], }, }, toISOTime: { @@ -457,7 +690,7 @@ export const luxonInstanceDocs: Required = { hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoisotime', returnType: 'string', - args: [{ name: 'opts', type: 'object' }], + args: [{ name: 'options', type: 'Object' }], }, }, toISOWeekDate: { @@ -490,9 +723,19 @@ export const luxonInstanceDocs: Required = { toLocal: { doc: { name: 'toLocal', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.toLocal'), section: 'edit', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetolocal', returnType: 'DateTime', + examples: [ + { + example: "dt = '2024-01-01T00:00:00.000Z'.toDateTime()\ndt.toLocal()", + evaluated: '[DateTime: 2024-01-01T01:00:00.000+01:00]', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toLocal.example', + ), + }, + ], }, }, toLocaleParts: { @@ -504,28 +747,103 @@ export const luxonInstanceDocs: Required = { returnType: 'string', args: [ { name: 'formatOpts', type: 'any' }, - { name: 'opts', type: 'object' }, + { name: 'options', type: 'Object' }, ], }, }, toLocaleString: { doc: { name: 'toLocaleString', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.toLocaleString'), section: 'format', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetolocalestring', returnType: 'string', args: [ - { name: 'formatOpts', type: 'any' }, - { name: 'opts', type: 'object' }, + { + name: 'formatOpts', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toLocaleString.args.opts', + ), + type: 'Object', + }, + ], + examples: [ + { example: '$now.toLocaleString()', evaluated: "'4/30/2024'" }, + { + example: "$now.toLocaleString({ dateStyle: 'medium', timeStyle: 'short' })", + evaluated: "'Apr 30, 2024, 10:00 PM'", + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toLocaleString.example', + ), + }, + { example: "$now.setLocale('de-DE').toLocaleString()", evaluated: "'30.4.2024'" }, + { example: "$now.toLocaleString({ dateStyle: 'short' })", evaluated: "'4/30/2024'" }, + { example: "$now.toLocaleString({ dateStyle: 'medium' })", evaluated: "'Apr 30, 2024'" }, + { example: "$now.toLocaleString({ dateStyle: 'long' })", evaluated: "'April 30, 2024'" }, + { + example: "$now.toLocaleString({ dateStyle: 'full' })", + evaluated: "'Tuesday, April 30, 2024'", + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toLocaleString.example', + ), + }, + { + example: "$now.toLocaleString({ year: 'numeric', month: 'numeric', day: 'numeric' })", + evaluated: "'4/30/2024'", + }, + { + example: "$now.toLocaleString({ year: '2-digit', month: '2-digit', day: '2-digit' })", + evaluated: "'04/30/24'", + }, + { + example: "$now.toLocaleString({ month: 'short', weekday: 'short', day: 'numeric' })", + evaluated: "'Tue, Apr 30'", + }, + { + example: "$now.toLocaleString({ month: 'long', weekday: 'long', day: 'numeric' })", + evaluated: "'Tuesday, April 30'", + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toLocaleString.example', + ), + }, + { example: "$now.toLocaleString({ timeStyle: 'short' })", evaluated: "'10:00 PM'" }, + { example: "$now.toLocaleString({ timeStyle: 'medium' })", evaluated: "'10:00:58 PM'" }, + { + example: "$now.toLocaleString({ timeStyle: 'long' })", + evaluated: "'10:00:58 PM GMT+2'", + }, + { + example: "$now.toLocaleString({ timeStyle: 'full' })", + evaluated: "'10:00:58 PM Central European Summer Time'", + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toLocaleString.example', + ), + }, + { + example: + "$now.toLocaleString({ hour: 'numeric', minute: 'numeric', hourCycle: 'h24' })", + evaluated: "'22:00'", + }, + { + example: + "$now.toLocaleString({ hour: '2-digit', minute: '2-digit', hourCycle: 'h12' })", + evaluated: "'10:00 PM'", + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toLocaleString.example', + ), + }, ], }, }, toMillis: { doc: { name: 'toMillis', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.toMillis'), section: 'format', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetomillis', returnType: 'number', + examples: [{ example: '$now.toMillis()', evaluated: '1712334324677' }], }, }, toObject: { @@ -534,17 +852,27 @@ export const luxonInstanceDocs: Required = { section: 'format', hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoobject', - returnType: 'object', - args: [{ name: 'opts', type: 'any' }], + returnType: 'Object', + args: [{ name: 'options', type: 'any' }], }, }, toRelative: { doc: { name: 'toRelative', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.toRelative'), section: 'format', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetorelative', returnType: 'string', - args: [{ name: 'options', type: 'object' }], + args: [ + { + name: 'options', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toRelative.args.opts', + ), + type: 'Object', + }, + ], }, }, toRelativeCalendar: { @@ -554,7 +882,7 @@ export const luxonInstanceDocs: Required = { hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetorelativecalendar', returnType: 'string', - args: [{ name: 'options', type: 'object' }], + args: [{ name: 'options', type: 'Object' }], }, }, toRFC2822: { @@ -569,9 +897,11 @@ export const luxonInstanceDocs: Required = { toSeconds: { doc: { name: 'toSeconds', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.toSeconds'), section: 'format', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoseconds', returnType: 'number', + examples: [{ example: '$now.toSeconds()', evaluated: '1712334442.372' }], }, }, toSQL: { @@ -581,7 +911,7 @@ export const luxonInstanceDocs: Required = { docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetosql', returnType: 'string', hidden: true, - args: [{ name: 'options', type: 'object' }], + args: [{ name: 'options', type: 'Object' }], }, }, toSQLDate: { @@ -605,9 +935,11 @@ export const luxonInstanceDocs: Required = { toString: { doc: { name: 'toString', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.toString'), section: 'format', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetostring', returnType: 'string', + examples: [{ example: '$now.toString()', evaluated: "'2024-04-05T18:44:55.525+02:00'" }], }, }, toUnixInteger: { @@ -622,12 +954,34 @@ export const luxonInstanceDocs: Required = { toUTC: { doc: { name: 'toUTC', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.toUTC'), section: 'edit', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoutc', returnType: 'DateTime', args: [ - { name: 'offset', type: 'number' }, - { name: 'opts', type: 'object' }, + { + name: 'zone', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toUTC.args.zone', + ), + default: '"local"', + type: 'string', + }, + { + name: 'options', + optional: true, + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.toUTC.args.opts', + ), + type: 'Object', + }, + ], + examples: [ + { + example: "dt = '2024-01-01T00:00:00.000+02:00'.toDateTime()\ndt.toUTC()", + evaluated: '[DateTime: 2023-12-31T22:00:00.000Z]', + }, ], }, }, diff --git a/packages/editor-ui/src/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.static.docs.ts b/packages/editor-ui/src/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.static.docs.ts index 2911e8fe0e620..638da176ebb7c 100644 --- a/packages/editor-ui/src/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.static.docs.ts +++ b/packages/editor-ui/src/plugins/codemirror/completions/nativesAutocompleteDocs/luxon.static.docs.ts @@ -1,7 +1,7 @@ import type { NativeDoc } from 'n8n-workflow'; +import { i18n } from '@/plugins/i18n'; // Autocomplete documentation definition for DateTime class static props and methods -// Descriptions are added dynamically so they can be localized export const luxonStaticDocs: Required = { typeName: 'DateTime', properties: {}, @@ -9,6 +9,7 @@ export const luxonStaticDocs: Required = { now: { doc: { name: 'now', + description: i18n.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.now'), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimenow', returnType: 'DateTime', }, @@ -16,65 +17,198 @@ export const luxonStaticDocs: Required = { local: { doc: { name: 'local', + description: i18n.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.local'), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimelocal', returnType: 'DateTime', args: [ - { name: 'year?', type: 'number' }, - { name: 'month', type: 'number' }, - { name: 'day', type: 'number' }, - { name: 'hour', type: 'number' }, - { name: 'minute', type: 'number' }, - { name: 'second', type: 'number' }, - { name: 'millisecond', type: 'number' }, + { + name: 'year', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.year'), + }, + { + name: 'month', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.month'), + }, + { + name: 'day', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.day'), + }, + { + name: 'hour', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.hour'), + }, + { + name: 'minute', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.minute'), + }, + { + name: 'second', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.second'), + }, + { + name: 'millisecond', + optional: true, + type: 'number', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.millisecond', + ), + }, + ], + examples: [ + { + example: 'DateTime.local(1982, 12, 3)', + evaluated: '[DateTime: 1982-12-03T00:00:00.000-05:00]', + }, ], }, }, utc: { doc: { name: 'utc', + description: i18n.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.utc'), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeutc', returnType: 'DateTime', args: [ - { name: 'year?', type: 'number' }, - { name: 'month', type: 'number' }, - { name: 'day', type: 'number' }, - { name: 'hour', type: 'number' }, - { name: 'minute', type: 'number' }, - { name: 'second', type: 'number' }, - { name: 'millisecond', type: 'number' }, + { + name: 'year', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.year'), + }, + { + name: 'month', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.month'), + }, + { + name: 'day', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.day'), + }, + { + name: 'hour', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.hour'), + }, + { + name: 'minute', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.minute'), + }, + { + name: 'second', + optional: true, + type: 'number', + description: i18n.baseText('codeNodeEditor.completer.luxon.instanceMethods.second'), + }, + { + name: 'millisecond', + optional: true, + type: 'number', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.instanceMethods.millisecond', + ), + }, + ], + examples: [ + { + example: 'DateTime.utc(1982, 12, 3)', + evaluated: '[DateTime: 1982-12-03T00:00:00.000Z]', + }, ], }, }, fromJSDate: { doc: { name: 'fromJSDate', + hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromjsdate', returnType: 'DateTime', args: [ { name: 'date', type: 'Date' }, - { name: 'options?', type: 'object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, fromMillis: { doc: { name: 'fromMillis', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromMillis', + ), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefrommillis', returnType: 'DateTime', args: [ - { name: 'milliseconds', type: 'number' }, - { name: 'options?', type: 'object' }, + { + name: 'milliseconds', + type: 'number', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromMillis.args.milliseconds', + ), + }, + { + name: 'options', + optional: true, + type: 'Object', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromMillis.args.opts', + ), + }, + ], + examples: [ + { + example: 'DateTime.fromMillis(1711838940000)', + evaluated: '[DateTime: 2024-03-30T18:49:00.000Z]', + }, ], }, }, fromSeconds: { doc: { name: 'fromSeconds', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSeconds', + ), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromseconds', returnType: 'DateTime', args: [ - { name: 'seconds', type: 'number' }, - { name: 'options?', type: 'object' }, + { + name: 'seconds', + type: 'number', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSeconds.args.seconds', + ), + }, + { + name: 'options', + optional: true, + type: 'Object', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSeconds.args.opts', + ), + }, + ], + examples: [ + { + example: 'DateTime.fromSeconds(1711838940)', + evaluated: '[DateTime: 2024-03-30T18:49:00.000Z]', + }, ], }, }, @@ -83,65 +217,90 @@ export const luxonStaticDocs: Required = { name: 'fromObject', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromobject', returnType: 'DateTime', + hidden: true, args: [ - { name: 'obj', type: 'object' }, - { name: 'options?', type: 'object' }, + { name: 'obj', type: 'Object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, fromISO: { doc: { name: 'fromISO', + description: i18n.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromISO'), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromiso', returnType: 'DateTime', args: [ - { name: 'text', type: 'string' }, - { name: 'options?', type: 'object' }, + { + name: 'isoString', + type: 'string', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromISO.args.isoString', + ), + }, + { + name: 'options', + optional: true, + type: 'Object', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromISO.args.opts', + ), + }, + ], + examples: [ + { + example: "DateTime.fromISO('2024-05-10T14:15:59.493Z')", + evaluated: '[DateTime: 2024-05-10T14:15:59.493Z]', + }, ], }, }, fromRFC2822: { doc: { name: 'fromRFC2822', + hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromrfc2822', returnType: 'DateTime', args: [ { name: 'text', type: 'string' }, - { name: 'options?', type: 'object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, fromHTTP: { doc: { name: 'fromHTTP', + hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromhttp', returnType: 'DateTime', args: [ { name: 'text', type: 'string' }, - { name: 'options?', type: 'object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, fromFormat: { doc: { name: 'fromFormat', + hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromformat', returnType: 'DateTime', args: [ { name: 'text', type: 'string' }, { name: 'fmt', type: 'string' }, - { name: 'options?', type: 'object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, fromSQL: { doc: { name: 'fromSQL', + hidden: true, docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromsql', returnType: 'DateTime', args: [ { name: 'text', type: 'string' }, - { name: 'options?', type: 'object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, @@ -150,18 +309,30 @@ export const luxonStaticDocs: Required = { name: 'invalid', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeinvalid', returnType: 'DateTime', + hidden: true, args: [ { name: 'reason', type: 'DateTime' }, - { name: 'explanation?', type: 'string' }, + { name: 'explanation', optional: true, type: 'string' }, ], }, }, isDateTime: { doc: { name: 'isDateTime', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.isDateTime', + ), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeisdatetime', returnType: 'boolean', - args: [{ name: 'o', type: 'object' }], + args: [ + { + name: 'maybeDateTime', + type: 'any', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.isDateTime.args.maybeDateTime', + ), + }, + ], }, }, expandFormat: { @@ -169,9 +340,10 @@ export const luxonStaticDocs: Required = { name: 'expandFormat', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeexpandformat', returnType: 'string', + hidden: true, args: [ { name: 'fmt', type: 'any' }, - { name: 'localeOpts?', type: 'any' }, + { name: 'localeOpts', optional: true, type: 'any' }, ], }, }, @@ -179,11 +351,12 @@ export const luxonStaticDocs: Required = { doc: { name: 'fromFormatExplain', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromformatexplain', - returnType: 'object', + returnType: 'Object', + hidden: true, args: [ { name: 'text', type: 'string' }, { name: 'fmt', type: 'string' }, - { name: 'options?', type: 'object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, @@ -192,10 +365,11 @@ export const luxonStaticDocs: Required = { name: 'fromString', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromstring', returnType: 'DateTime', + hidden: true, args: [ { name: 'text', type: 'string' }, { name: 'fmt', type: 'string' }, - { name: 'options?', type: 'object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, @@ -203,35 +377,62 @@ export const luxonStaticDocs: Required = { doc: { name: 'fromStringExplain', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromstringexplain', - returnType: 'object', + returnType: 'Object', + hidden: true, args: [ { name: 'text', type: 'string' }, { name: 'fmt', type: 'string' }, - { name: 'options?', type: 'object' }, + { name: 'options', optional: true, type: 'Object' }, ], }, }, max: { doc: { name: 'max', + description: i18n.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.max'), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemax', - returnType: 'DateTime|undefined', + returnType: 'DateTime', args: [ - { name: 'dateTime1', type: 'DateTime' }, - { name: '...' }, - { name: 'dateTimeN', type: 'DateTime' }, + { + name: 'dateTimes', + variadic: true, + type: 'DateTime', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.max.args.dateTimes', + ), + }, + ], + examples: [ + { + example: + "DateTime.max('2024-03-30T18:49'.toDateTime(), '2025-03-30T18:49'.toDateTime())", + evaluated: '[DateTime: 2025-03-30T18:49:00.000Z]', + }, ], }, }, min: { doc: { name: 'min', + description: i18n.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.min'), docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemin', - returnType: 'DateTime|undefined', + returnType: 'DateTime', args: [ - { name: 'dateTime1', type: 'DateTime' }, - { name: '...' }, - { name: 'dateTimeN', type: 'DateTime' }, + { + name: 'dateTimes', + variadic: true, + type: 'DateTime', + description: i18n.baseText( + 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.min.args.dateTimes', + ), + }, + ], + examples: [ + { + example: + "DateTime.min('2024-03-30T18:49'.toDateTime(), '2025-03-30T18:49'.toDateTime())", + evaluated: '[DateTime: 2024-03-30T18:49:00.000Z]', + }, ], }, }, @@ -240,9 +441,10 @@ export const luxonStaticDocs: Required = { name: 'parseFormatForOpts', docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeparseformatforopts', returnType: 'string', + hidden: true, args: [ { name: 'fmt', type: 'any' }, - { name: 'localeOpts?', type: 'any' }, + { name: 'localeOpts', optional: true, type: 'any' }, ], }, }, diff --git a/packages/editor-ui/src/plugins/i18n/index.ts b/packages/editor-ui/src/plugins/i18n/index.ts index c8c0bab310e8e..a1a277d027fda 100644 --- a/packages/editor-ui/src/plugins/i18n/index.ts +++ b/packages/editor-ui/src/plugins/i18n/index.ts @@ -418,131 +418,6 @@ export class I18nClass { values: this.baseText('codeNodeEditor.completer.globalObject.values'), }; - luxonInstance: Record = { - // getters - isValid: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.isValid'), - invalidReason: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.invalidReason'), - invalidExplanation: this.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.invalidExplanation', - ), - locale: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.locale'), - numberingSystem: this.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.numberingSystem', - ), - outputCalendar: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.outputCalendar'), - zone: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.zone'), - zoneName: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.zoneName'), - year: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.year'), - quarter: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.quarter'), - month: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.month'), - day: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.day'), - hour: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.hour'), - minute: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.minute'), - second: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.second'), - millisecond: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.millisecond'), - weekYear: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekYear'), - weekNumber: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekNumber'), - weekday: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekday'), - ordinal: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.ordinal'), - monthShort: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.monthShort'), - monthLong: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.monthLong'), - weekdayShort: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekdayShort'), - weekdayLong: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.weekdayLong'), - offset: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.offset'), - offsetNumber: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.offsetNumber'), - offsetNameShort: this.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.offsetNameShort', - ), - offsetNameLong: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.offsetNameLong'), - isOffsetFixed: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.isOffsetFixed'), - isInDST: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.isInDST'), - isInLeapYear: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.isInLeapYear'), - daysInMonth: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.daysInMonth'), - daysInYear: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.daysInYear'), - weeksInWeekYear: this.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.weeksInWeekYear', - ), - - // methods - toUTC: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toUTC'), - toLocal: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toLocal'), - setZone: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.setZone'), - setLocale: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.setLocale'), - set: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.set'), - plus: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.plus'), - minus: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.minus'), - startOf: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.startOf'), - endOf: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.endOf'), - toFormat: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toFormat'), - toLocaleString: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toLocaleString'), - toLocaleParts: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toLocaleParts'), - toISO: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toISO'), - toISODate: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toISODate'), - toISOWeekDate: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toISOWeekDate'), - toISOTime: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toISOTime'), - toRFC2822: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toRFC2822'), - toHTTP: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toHTTP'), - toSQLDate: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toSQLDate'), - toSQLTime: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toSQLTime'), - toSQL: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toSQL'), - toString: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toString'), - valueOf: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.valueOf'), - toMillis: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toMillis'), - toSeconds: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toSeconds'), - toUnixInteger: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toUnixInteger'), - toJSON: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toJSON'), - toBSON: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toBSON'), - toObject: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toObject'), - toJSDate: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toJsDate'), - diff: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.diff'), - diffNow: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.diffNow'), - until: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.until'), - hasSame: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.hasSame'), - equals: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.equals'), - toRelative: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.toRelative'), - toRelativeCalendar: this.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.toRelativeCalendar', - ), - min: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.min'), - max: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.max'), - reconfigure: this.baseText('codeNodeEditor.completer.luxon.instanceMethods.reconfigure'), - resolvedLocaleOptions: this.baseText( - 'codeNodeEditor.completer.luxon.instanceMethods.resolvedLocaleOptions', - ), - }; - - luxonStatic: Record = { - now: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.now'), - local: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.local'), - utc: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.utc'), - fromJSDate: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromJSDate'), - fromMillis: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromMillis'), - fromSeconds: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSeconds'), - fromObject: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromObject'), - fromISO: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromISO'), - fromRFC2822: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromRFC2822'), - fromHTTP: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromHTTP'), - fromFormat: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromFormat'), - fromSQL: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSQL'), - invalid: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.invalid'), - isDateTime: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.isDateTime'), - expandFormat: this.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.expandFormat', - ), - fromFormatExplain: this.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromFormatExplain', - ), - fromString: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromString'), - fromStringExplain: this.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromStringExplain', - ), - max: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.max'), - min: this.baseText('codeNodeEditor.completer.luxon.dateTimeStaticMethods.min'), - parseFormatForOpts: this.baseText( - 'codeNodeEditor.completer.luxon.dateTimeStaticMethods.parseFormatForOpts', - ), - }; - autocompleteUIValues: Record = { docLinkLabel: this.baseText('expressionEdit.learnMore'), }; diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index 0135bca4c1928..1850eaffa122c 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -242,46 +242,60 @@ "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromFormatExplain": "Explain how a string would be parsed by fromFormat().", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromHTTP": "Create a DateTime from an HTTP header date", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromISO": "Create a DateTime from an ISO 8601 string", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromISO.args.isoString": "ISO 8601 string to convert to a DateTime", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromISO.args.opts": "Configuration options. See See Luxon docs for more info.", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromJSDate": "Create a DateTime from a JavaScript Date object. Uses the default zone", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromMillis": "Create a DateTime from a number of milliseconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromMillis.args.milliseconds": "Number of milliseconds since the epoch (meaning since 1 January 1970 00:00:00 UTC)", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromMillis.args.opts": "Configuration options. See See Luxon docs for more info.", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromObject": "Create a DateTime from a JavaScript object with keys like 'year' and 'hour' with reasonable defaults", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromRFC2822": "Create a DateTime from an RFC 2822 string", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromString": "Deprecated: use `fromFormat` instead.", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromStringExplain": "Deprecated: use `fromFormatExplain` instead.", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSQL": "Create a DateTime from a SQL date, time, or datetime", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSeconds": "Create a DateTime from a number of seconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSeconds.args.seconds": "Number of seconds since the epoch (meaning since 1 January 1970 00:00:00 UTC)", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.fromSeconds.args.opts": "Configuration options. See Luxon docs for more info.", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.invalid": "Create an invalid DateTime.", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.isDateTime": "Check if an object is a DateTime. Works across context boundaries", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.isDateTime.args.maybeDateTime": "Potential DateTime to check. Only instances of the Luxon DateTime class will return true.", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.local": "Create a local DateTime", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.max": "Return the max of several date times.", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.max.args.dateTimes": "DateTime objects to compare", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.min": "Return the min of several date times.", - "codeNodeEditor.completer.luxon.dateTimeStaticMethods.now": "Create a DateTime for the current instant, in the system's time zone", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.min.args.dateTimes": "DateTime objects to compare", + "codeNodeEditor.completer.luxon.dateTimeStaticMethods.now": "Create a DateTime for the current instant, in the workflow's local time zone", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.parseFormatForOpts": "Produce the the fully expanded format token for the locale Does NOT quote characters, so quoted tokens will not round trip correctly.", "codeNodeEditor.completer.luxon.dateTimeStaticMethods.utc": "Create a DateTime in UTC", - "codeNodeEditor.completer.luxon.instanceMethods.day": "Get the day of the month (1-30ish).", + "codeNodeEditor.completer.luxon.instanceMethods.day": "The day of the month (1-31).", "codeNodeEditor.completer.luxon.instanceMethods.daysInMonth": "Returns the number of days in this DateTime's month.", "codeNodeEditor.completer.luxon.instanceMethods.daysInYear": "Returns the number of days in this DateTime's year.", "codeNodeEditor.completer.luxon.instanceMethods.diff": "Return the difference between two DateTimes as a Duration.", "codeNodeEditor.completer.luxon.instanceMethods.diffNow": "Return the difference between this DateTime and right now.", - "codeNodeEditor.completer.luxon.instanceMethods.endOf": "Set this DateTime to the end (meaning the last millisecond) of a unit of time.", - "codeNodeEditor.completer.luxon.instanceMethods.equals": "Equality check.", - "codeNodeEditor.completer.luxon.instanceMethods.hasSame": "Return whether this DateTime is in the same unit of time as another DateTime.", - "codeNodeEditor.completer.luxon.instanceMethods.hour": "Get the hour of the day (0-23).", + "codeNodeEditor.completer.luxon.instanceMethods.endOf": "Rounds the DateTime up to the end of one of its units, e.g. the end of the month", + "codeNodeEditor.completer.luxon.instanceMethods.endOf.args.unit": "The unit to round to the end of. Can be year, quarter, month, week, day, hour, minute, second, or millisecond.", + "codeNodeEditor.completer.luxon.instanceMethods.endOf.args.opts": "Object with options that affect the output. Possible properties:\nuseLocaleWeeks (boolean): Whether to use the locale when calculating the start of the week. Defaults to false.", + "codeNodeEditor.completer.luxon.instanceMethods.equals": "Returns true if the two DateTimes represent exactly the same moment and are in the same time zone. For a less strict comparison, use hasSame().", + "codeNodeEditor.completer.luxon.instanceMethods.equals.args.other": "The other DateTime to compare", + "codeNodeEditor.completer.luxon.instanceMethods.hasSame": "Returns true if the two DateTimes are the same, down to the unit specified. Time zones are ignored (only local times are compared), so use toUTC() first if needed.", + "codeNodeEditor.completer.luxon.instanceMethods.hasSame.args.other": "The other DateTime to compare", + "codeNodeEditor.completer.luxon.instanceMethods.hasSame.args.unit": "The unit of time to check sameness down to. One of year, quarter, month, week, day, hour, minute, second, or millisecond.", + "codeNodeEditor.completer.luxon.instanceMethods.hour": "The hour of the day (0-23).", "codeNodeEditor.completer.luxon.instanceMethods.invalidExplanation": "Returns an explanation of why this DateTime became invalid, or null if the DateTime is valid.", "codeNodeEditor.completer.luxon.instanceMethods.invalidReason": "Returns an error code if this DateTime is invalid, or null if the DateTime is valid.", - "codeNodeEditor.completer.luxon.instanceMethods.isInDST": "Get whether the DateTime is in a DST.", - "codeNodeEditor.completer.luxon.instanceMethods.isInLeapYear": "Returns true if this DateTime is in a leap year, false otherwise.", + "codeNodeEditor.completer.luxon.instanceMethods.isInDST": "Whether the DateTime is in daylight saving time.", + "codeNodeEditor.completer.luxon.instanceMethods.isInLeapYear": "Whether the DateTime is in a leap year.", "codeNodeEditor.completer.luxon.instanceMethods.isOffsetFixed": "Get whether this zone's offset ever changes, as in a DST.", "codeNodeEditor.completer.luxon.instanceMethods.isValid": "Returns whether the DateTime is valid. Invalid DateTimes occur when The DateTime was created from invalid calendar information, such as the 13th month or February 30. The DateTime was created by an operation on another invalid date.", - "codeNodeEditor.completer.luxon.instanceMethods.locale": "Get the locale of a DateTime, such 'en-GB'. The locale is used when formatting the DateTime.", + "codeNodeEditor.completer.luxon.instanceMethods.locale": "The locale of a DateTime, such 'en-GB'. The locale is used when formatting the DateTime.", "codeNodeEditor.completer.luxon.instanceMethods.max": "Return the max of several date times.", - "codeNodeEditor.completer.luxon.instanceMethods.millisecond": "Get the millisecond of the second (0-999).", + "codeNodeEditor.completer.luxon.instanceMethods.millisecond": "The millisecond of the second (0-999).", "codeNodeEditor.completer.luxon.instanceMethods.min": "Return the min of several date times", "codeNodeEditor.completer.luxon.instanceMethods.minus": "Subtract hours, minutes, seconds, or milliseconds increases the timestamp by the right number of milliseconds.", - "codeNodeEditor.completer.luxon.instanceMethods.minute": "Get the minute of the hour (0-59).", - "codeNodeEditor.completer.luxon.instanceMethods.month": "Get the month (1-12).", - "codeNodeEditor.completer.luxon.instanceMethods.monthLong": "Get the human readable long month name, such as 'October'.", - "codeNodeEditor.completer.luxon.instanceMethods.monthShort": "Get the human readable short month name, such as 'Oct'.", + "codeNodeEditor.completer.luxon.instanceMethods.minute": "The minute of the hour (0-59).", + "codeNodeEditor.completer.luxon.instanceMethods.month": "The month (1-12).", + "codeNodeEditor.completer.luxon.instanceMethods.monthLong": "The textual long month name, e.g. 'October'. Defaults to the system's locale if unspecified.", + "codeNodeEditor.completer.luxon.instanceMethods.monthShort": "The textual abbreviated month name, e.g. 'Oct'. Defaults to the system's locale if unspecified.", "codeNodeEditor.completer.luxon.instanceMethods.numberingSystem": "Get the numbering system of a DateTime, such 'beng'. The numbering system is used when formatting the DateTime.", "codeNodeEditor.completer.luxon.instanceMethods.offset": "Get the UTC offset of this DateTime in minutes", "codeNodeEditor.completer.luxon.instanceMethods.offsetNameLong": "Get the long human name for the zone's current offset, for example \"Eastern Standard Time\" or \"Eastern Daylight Time\".", @@ -290,48 +304,61 @@ "codeNodeEditor.completer.luxon.instanceMethods.ordinal": "Get the ordinal (meaning the day of the year).", "codeNodeEditor.completer.luxon.instanceMethods.outputCalendar": "Get the output calendar of a DateTime, such 'islamic'. The output calendar is used when formatting the DateTime.", "codeNodeEditor.completer.luxon.instanceMethods.plus": "Add hours, minutes, seconds, or milliseconds increases the timestamp by the right number of milliseconds.", - "codeNodeEditor.completer.luxon.instanceMethods.quarter": "Get the quarter.", + "codeNodeEditor.completer.luxon.instanceMethods.quarter": "The quarter of the year (1-4).", "codeNodeEditor.completer.luxon.instanceMethods.reconfigure": "'Set' the locale, numberingSystem, or outputCalendar. Returns a newly-constructed DateTime.", "codeNodeEditor.completer.luxon.instanceMethods.resolvedLocaleOptions": "Returns the resolved Intl options for this DateTime. This is useful in understanding the behavior of formatting methods.", - "codeNodeEditor.completer.luxon.instanceMethods.second": "Get the second of the minute (0-59).", - "codeNodeEditor.completer.luxon.instanceMethods.set": "Set the values of specified units. Returns a newly-constructed DateTime.", - "codeNodeEditor.completer.luxon.instanceMethods.setLocale": "Set the locale. Returns a newly-constructed DateTime.", - "codeNodeEditor.completer.luxon.instanceMethods.setZone": "Set the DateTime's zone to specified zone. Returns a newly-constructed DateTime.", - "codeNodeEditor.completer.luxon.instanceMethods.startOf": "Set this DateTime to the beginning of a unit of time.", + "codeNodeEditor.completer.luxon.instanceMethods.second": "The second of the minute (0-59).", + "codeNodeEditor.completer.luxon.instanceMethods.set": "Assigns new values to specified units of the DateTime. To round a DateTime, see also startOf() and endOf().", + "codeNodeEditor.completer.luxon.instanceMethods.set.args.values": "An object containing the units to set and corresponding values to assign. Possible keys are year, month, day, hour, minute, second and millsecond.", + "codeNodeEditor.completer.luxon.instanceMethods.setLocale": "Sets the locale, which determines the language and formatting for the DateTime. Useful when generating a textual representation of the DateTime, e.g. with format() or toLocaleString().", + "codeNodeEditor.completer.luxon.instanceMethods.setLocale.args.locale": "The locale to set, e.g. 'en-GB' for British English or 'pt-BR' for Brazilian Portuguese. List (unofficial)", + "codeNodeEditor.completer.luxon.instanceMethods.setZone": "Converts the DateTime to the given time zone. The DateTime still represents the same moment unless specified in the options. See also toLocal() and toUTC().", + "codeNodeEditor.completer.luxon.instanceMethods.setZone.args.zone": "A zone identifier, either in the format 'America/New_York', 'UTC+3', or the strings 'local' or 'utc'. 'local' is the workflow's local time zone, this can be changed in workflow settings.", + "codeNodeEditor.completer.luxon.instanceMethods.setZone.args.opts": "Options that affect the output. Possible properties:\nkeepCalendarTime (boolean): Whether to keep the time the same and only change the offset. Defaults to false.", + "codeNodeEditor.completer.luxon.instanceMethods.startOf": "Rounds the DateTime down to the beginning of one of its units, e.g. the start of the month", + "codeNodeEditor.completer.luxon.instanceMethods.startOf.args.unit": "The unit to round to the beginning of. One of year, quarter, month, week, day, hour, minute, second, or millisecond.", + "codeNodeEditor.completer.luxon.instanceMethods.startOf.args.opts": "Object with options that affect the output. Possible properties:\nuseLocaleWeeks (boolean): Whether to use the locale when calculating the start of the week. Defaults to false.", "codeNodeEditor.completer.luxon.instanceMethods.toBSON": "Returns a BSON serializable equivalent to this DateTime.", "codeNodeEditor.completer.luxon.instanceMethods.toFormat": "Returns a string representation of this DateTime formatted according to the specified format string.", "codeNodeEditor.completer.luxon.instanceMethods.toHTTP": "Returns a string representation of this DateTime appropriate for use in HTTP headers.", "codeNodeEditor.completer.luxon.instanceMethods.toISO": "Returns an ISO 8601-compliant string representation of this DateTime.", + "codeNodeEditor.completer.luxon.instanceMethods.toISO.args.opts": "Configuration options. See Luxon docs for more info.", "codeNodeEditor.completer.luxon.instanceMethods.toISODate": "Returns an ISO 8601-compliant string representation of this DateTime's date component.", "codeNodeEditor.completer.luxon.instanceMethods.toISOTime": "Returns an ISO 8601-compliant string representation of this DateTime's time component.", "codeNodeEditor.completer.luxon.instanceMethods.toISOWeekDate": "Returns an ISO 8601-compliant string representation of this DateTime's week date.", "codeNodeEditor.completer.luxon.instanceMethods.toJSON": "Returns an ISO 8601 representation of this DateTime appropriate for use in JSON.", "codeNodeEditor.completer.luxon.instanceMethods.toJsDate": "Returns a JavaScript Date equivalent to this DateTime.", - "codeNodeEditor.completer.luxon.instanceMethods.toLocal": "Set the DateTime's zone to the host's local zone. Returns a newly-constructed DateTime.", + "codeNodeEditor.completer.luxon.instanceMethods.toLocal": "Converts a DateTime to the workflow's local time zone. The DateTime still represents the same moment unless specified in the parameters. The workflow's time zone can be set in the workflow settings.", + "codeNodeEditor.completer.luxon.instanceMethods.toLocal.example": "if time zone is Europe/Berlin", "codeNodeEditor.completer.luxon.instanceMethods.toLocaleParts": "Returns an array of format \"parts\", meaning individual tokens along with metadata.", - "codeNodeEditor.completer.luxon.instanceMethods.toLocaleString": "Returns a localized string representing this date. Accepts the same options as the Intl.DateTimeFormat constructor and any presets defined by Luxon.", - "codeNodeEditor.completer.luxon.instanceMethods.toMillis": "Returns the epoch milliseconds of this DateTime.", + "codeNodeEditor.completer.luxon.instanceMethods.toLocaleString": "Returns a localized string representing the DateTime, i.e. in the language and format corresponding to its locale. Defaults to the system's locale if none specified.", + "codeNodeEditor.completer.luxon.instanceMethods.toLocaleString.args.opts": "Configuration options for the rendering. See Intl.DateTimeFormat for a full list. Defaults to rendering a short date.", + "codeNodeEditor.completer.luxon.instanceMethods.toLocaleString.example": "Configuration options for the rendering. See Intl.DateTimeFormat for a full list. Defaults to rendering a short date.", + "codeNodeEditor.completer.luxon.instanceMethods.toMillis": "Returns a Unix timestamp in milliseconds (the number elapsed since 1st Jan 1970)", "codeNodeEditor.completer.luxon.instanceMethods.toObject": "Returns a JavaScript object with this DateTime's year, month, day, and so on.", "codeNodeEditor.completer.luxon.instanceMethods.toRFC2822": "Returns an RFC 2822-compatible string representation of this DateTime, always in UTC.", - "codeNodeEditor.completer.luxon.instanceMethods.toRelative": "Returns a string representation of a this time relative to now, such as 'in two days'.", + "codeNodeEditor.completer.luxon.instanceMethods.toRelative": "Returns a textual representation of the time relative to now, e.g. 'in two days'. Rounds down by default.", + "codeNodeEditor.completer.luxon.instanceMethods.toRelative.args.opts": "Options that affect the output. Possible properties:\nunit = the unit to default to (years, months, days, etc.).\nlocale = the language and formatting to use (e.g. de, fr)", "codeNodeEditor.completer.luxon.instanceMethods.toRelativeCalendar": "Returns a string representation of this date relative to today, such as '\"'yesterday' or 'next month'.", "codeNodeEditor.completer.luxon.instanceMethods.toSQL": "Returns a string representation of this DateTime appropriate for use in SQL DateTime.", "codeNodeEditor.completer.luxon.instanceMethods.toSQLDate": "Returns a string representation of this DateTime appropriate for use in SQL Date.", "codeNodeEditor.completer.luxon.instanceMethods.toSQLTime": "Returns a string representation of this DateTime appropriate for use in SQL Time.", - "codeNodeEditor.completer.luxon.instanceMethods.toSeconds": "Returns the epoch seconds of this DateTime.", - "codeNodeEditor.completer.luxon.instanceMethods.toString": "Returns a string representation of this DateTime appropriate for debugging.", - "codeNodeEditor.completer.luxon.instanceMethods.toUTC": "Set the DateTime's zone to UTC. Returns a newly-constructed DateTime.", + "codeNodeEditor.completer.luxon.instanceMethods.toSeconds": "Returns a Unix timestamp in seconds (the number elapsed since 1st Jan 1970)", + "codeNodeEditor.completer.luxon.instanceMethods.toString": "Returns a string representation of the DateTime. Similar to toISO(). For more formatting options, see format() or toLocaleString().", + "codeNodeEditor.completer.luxon.instanceMethods.toUTC": "Converts the DateTime to the given time zone. The DateTime still represents the same moment unless specified in the options. See also toLocal() and toUTC().", + "codeNodeEditor.completer.luxon.instanceMethods.toUTC.args.zone": "A zone identifier, either in the format 'America/New_York', 'UTC+3', or the strings 'local' or 'utc'", + "codeNodeEditor.completer.luxon.instanceMethods.toUTC.args.opts": "Options that affect the output. Possible properties:\nkeepCalendarTime (boolean): Whether to keep the time the same and only change the offset. Defaults to false.", "codeNodeEditor.completer.luxon.instanceMethods.toUnixInteger": "Returns the epoch seconds (as a whole number) of this DateTime.", "codeNodeEditor.completer.luxon.instanceMethods.until": "Return an Interval spanning between this DateTime and another DateTime.", "codeNodeEditor.completer.luxon.instanceMethods.valueOf": "Returns the epoch milliseconds of this DateTime.", - "codeNodeEditor.completer.luxon.instanceMethods.weekNumber": "Get the week number of the week year (1-52ish).", + "codeNodeEditor.completer.luxon.instanceMethods.weekNumber": "The week number of the year (1-52ish).", "codeNodeEditor.completer.luxon.instanceMethods.weekYear": "Get the week year.", - "codeNodeEditor.completer.luxon.instanceMethods.weekday": "Get the day of the week. 1 is Monday and 7 is Sunday.", - "codeNodeEditor.completer.luxon.instanceMethods.weekdayLong": "Get the human readable long weekday, such as 'Monday'.", - "codeNodeEditor.completer.luxon.instanceMethods.weekdayShort": "Get the human readable short weekday, such as 'Mon'.", + "codeNodeEditor.completer.luxon.instanceMethods.weekday": "The day of the week. 1 is Monday and 7 is Sunday.", + "codeNodeEditor.completer.luxon.instanceMethods.weekdayLong": "The textual long weekday name, e.g. 'Wednesday'. Defaults to the system's locale if unspecified.", + "codeNodeEditor.completer.luxon.instanceMethods.weekdayShort": "The textual abbreviated weekday name, e.g. 'Wed'. Defaults to the system's locale if unspecified.", "codeNodeEditor.completer.luxon.instanceMethods.weeksInWeekYear": "Returns the number of weeks in this DateTime's year.", - "codeNodeEditor.completer.luxon.instanceMethods.year": "Get the year.", - "codeNodeEditor.completer.luxon.instanceMethods.zone": "Get the time zone associated with this DateTime.", + "codeNodeEditor.completer.luxon.instanceMethods.year": "The year.", + "codeNodeEditor.completer.luxon.instanceMethods.zone": "The time zone associated with the DateTime", "codeNodeEditor.completer.luxon.instanceMethods.zoneName": "Get the name of the time zone.", "codeNodeEditor.completer.selector.all": "@:_reusableBaseText.codeNodeEditor.completer.all", "codeNodeEditor.completer.selector.context": "Extra data about the node", diff --git a/packages/workflow/src/Expression.ts b/packages/workflow/src/Expression.ts index 35f0ddca6c165..8ec3e3a37e4de 100644 --- a/packages/workflow/src/Expression.ts +++ b/packages/workflow/src/Expression.ts @@ -73,18 +73,23 @@ export class Expression { * */ convertObjectValueToString(value: object): string { - const typeName = Array.isArray(value) ? 'Array' : 'Object'; - if (value instanceof DateTime && value.invalidReason !== null) { throw new ApplicationError('invalid DateTime'); } + let typeName = value.constructor.name ?? 'Object'; + if (DateTime.isDateTime(value)) { + typeName = 'DateTime'; + } + let result = ''; if (value instanceof Date) { // We don't want to use JSON.stringify for dates since it disregards workflow timezone result = DateTime.fromJSDate(value, { zone: this.workflow.settings?.timezone ?? getGlobalState().defaultTimezone, }).toISO(); + } else if (DateTime.isDateTime(value)) { + result = value.toString(); } else { result = JSON.stringify(value); } diff --git a/packages/workflow/src/Extensions/DateExtensions.ts b/packages/workflow/src/Extensions/DateExtensions.ts index 327c4ade3cecd..071f6ba850748 100644 --- a/packages/workflow/src/Extensions/DateExtensions.ts +++ b/packages/workflow/src/Extensions/DateExtensions.ts @@ -10,29 +10,35 @@ import type { } from 'luxon'; import type { ExtensionMap } from './Extensions'; import { convertToDateTime } from './utils'; - -type DurationUnit = - | 'milliseconds' - | 'seconds' - | 'minutes' - | 'hours' - | 'days' - | 'weeks' - | 'months' - | 'quarter' - | 'years'; -type DatePart = - | 'day' - | 'week' - | 'month' - | 'year' - | 'hour' - | 'minute' - | 'second' - | 'millisecond' - | 'weekNumber' - | 'yearDayNumber' - | 'weekday'; +import { toDateTime as stringToDateTime } from './StringExtensions'; + +const durationUnits = [ + 'milliseconds', + 'seconds', + 'minutes', + 'hours', + 'days', + 'weeks', + 'months', + 'quarters', + 'years', +] as const; +type DurationUnit = (typeof durationUnits)[number]; + +const dateParts = [ + 'day', + 'week', + 'month', + 'year', + 'hour', + 'minute', + 'second', + 'millisecond', + 'weekNumber', + 'yearDayNumber', + 'weekday', +] as const; +type DatePart = (typeof dateParts)[number]; const DURATION_MAP: Record = { day: 'days', @@ -73,6 +79,16 @@ function isDateTime(date: unknown): date is DateTime { return date ? DateTime.isDateTime(date) : false; } +function toDateTime(date: string | Date | DateTime): DateTime { + if (isDateTime(date)) return date; + + if (typeof date === 'string') { + return stringToDateTime(date); + } + + return DateTime.fromJSDate(date); +} + function generateDurationObject(durationValue: number, unit: DurationUnit): DurationObjectUnits { const convertedUnit = DURATION_MAP[unit] || unit; return { [`${convertedUnit}`]: durationValue }; @@ -216,10 +232,37 @@ function plus( return DateTime.fromJSDate(date).plus(duration).toJSDate(); } -function toDateTime(date: Date | DateTime): DateTime { - if (isDateTime(date)) return date; +function diffTo(date: DateTime, args: [string | Date | DateTime, DurationUnit | DurationUnit[]]) { + const [otherDate, unit = 'days'] = args; + let units = Array.isArray(unit) ? unit : [unit]; - return DateTime.fromJSDate(date); + if (units.length === 0) { + units = ['days']; + } + + const allowedUnitSet = new Set([...dateParts, ...durationUnits]); + const errorUnit = units.find((u) => !allowedUnitSet.has(u)); + + if (errorUnit) { + throw new ExpressionExtensionError( + `Unsupported unit '${String(errorUnit)}'. Supported: ${durationUnits + .map((u) => `'${u}'`) + .join(', ')}.`, + ); + } + + const diffResult = date.diff(toDateTime(otherDate), units); + + if (units.length > 1) { + return diffResult.toObject(); + } + + return diffResult.as(units[0]); +} + +function diffToNow(date: DateTime, args: [DurationUnit | DurationUnit[]]) { + const [unit] = args; + return diffTo(date, [DateTime.now(), unit]); } function toInt(date: Date | DateTime): number { @@ -237,7 +280,7 @@ function toBoolean() { endOfMonth.doc = { name: 'endOfMonth', - returnType: 'Date', + returnType: 'DateTime', hidden: true, description: 'Transforms a date to the last possible moment that lies within the month.', section: 'edit', @@ -267,37 +310,98 @@ beginningOf.doc = { description: 'Transform a Date to the start of the given time period. Default unit is `week`.', section: 'edit', hidden: true, - returnType: 'Date', + returnType: 'DateTime', args: [{ name: 'unit?', type: 'DurationUnit' }], docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-beginningOf', }; extract.doc = { name: 'extract', - description: 'Extracts the part defined in `datePart` from a Date. Default unit is `week`.', + description: + 'Extracts a part of the date or time, e.g. the month, as a number. To extract textual names instead, see format().', + examples: [ + { example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.extract('month')", evaluated: '3' }, + { example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.extract('hour')", evaluated: '18' }, + ], section: 'query', returnType: 'number', - args: [{ name: 'datePart?', type: 'DurationUnit' }], + args: [ + { + name: 'unit', + optional: true, + description: + 'The part of the date or time to return. One of: year, month, week, day, hour, minute, second', + default: '"week"', + type: 'string', + }, + ], docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-extract', }; format.doc = { name: 'format', - description: 'Formats a Date in the given structure.', + description: + 'Converts the DateTime to a string, using the format specified. Formatting guide. For common formats, toLocaleString() may be easier.', + examples: [ + { + example: "dt = '2024-04-30T18:49'.toDateTime()\ndt.format('dd/LL/yyyy')", + evaluated: "'30/04/2024'", + }, + { + example: "dt = '2024-04-30T18:49'.toDateTime()\ndt.format('dd LLL yy')", + evaluated: "'30 Apr 24'", + }, + { + example: "dt = '2024-04-30T18:49'.toDateTime()\ndt.setLocale('fr').format('dd LLL yyyy')", + evaluated: "'30 avr. 2024'", + }, + { + example: "dt = '2024-04-30T18:49'.toDateTime()\ndt.format(\"HH 'hours and' mm 'minutes'\")", + evaluated: "'18 hours and 49 minutes'", + }, + ], returnType: 'string', section: 'format', - args: [{ name: 'fmt', default: "'yyyy-MM-dd'", type: 'TimeFormat' }], + args: [ + { + name: 'fmt', + description: + 'The format of the string to return ', + default: "'yyyy-MM-dd'", + type: 'string', + }, + ], docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-format', }; isBetween.doc = { name: 'isBetween', - description: 'Checks if a Date is between two given dates.', - section: 'query', + description: 'Returns true if the DateTime lies between the two moments specified', + examples: [ + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.isBetween('2020-06-01', '2025-06-01')", + evaluated: 'true', + }, + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.isBetween('2020', '2025')", + evaluated: 'true', + }, + ], + section: 'compare', returnType: 'boolean', args: [ - { name: 'date1', type: 'Date|string' }, - { name: 'date2', type: 'Date|string' }, + { + name: 'date1', + description: + 'The moment that the base DateTime must be after. Can be an ISO date string or a Luxon DateTime.', + type: 'string | DateTime', + }, + { + name: 'date2', + description: + 'The moment that the base DateTime must be before. Can be an ISO date string or a Luxon DateTime.', + type: 'string | DateTime', + }, ], docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-isBetween', }; @@ -317,7 +421,14 @@ isInLast.doc = { toDateTime.doc = { name: 'toDateTime', - description: 'Convert a JavaScript Date to a Luxon DateTime.', + description: + 'Converts a JavaScript Date to a Luxon DateTime. The DateTime contains the same information, but is easier to manipulate.', + examples: [ + { + example: "jsDate = new Date('2024-03-30T18:49')\njsDate.toDateTime().plus(5, 'days')", + evaluated: '[DateTime: 2024-05-05T18:49:00.000Z]', + }, + ], returnType: 'DateTime', hidden: true, docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-toDateTime', @@ -325,28 +436,135 @@ toDateTime.doc = { minus.doc = { name: 'minus', - description: 'Subtracts a given time period from a Date. Default unit is `milliseconds`.', + description: 'Subtracts a given period of time from the DateTime', + examples: [ + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.minus(7, 'days')", + evaluated: '[DateTime: 2024-04-23T18:49:00.000Z]', + }, + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.minus(4, 'years')", + evaluated: '[DateTime: 2020-04-30T18:49:00.000Z]', + }, + ], section: 'edit', - returnType: 'Date', + returnType: 'DateTime', args: [ - { name: 'n', type: 'number' }, - { name: 'unit?', type: 'DurationUnit' }, + { + name: 'n', + description: + 'The number of units to subtract. Or use a Luxon Duration object to subtract multiple units at once.', + type: 'number | object', + }, + { + name: 'unit', + optional: true, + description: + 'The units of the number. One of: years, months, weeks, days, hours, minutes, seconds, milliseconds', + default: '"milliseconds"', + type: 'string', + }, ], docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-minus', }; plus.doc = { name: 'plus', - description: 'Adds a given time period to a Date. Default unit is `milliseconds`.', + description: 'Adds a given period of time to the DateTime', + examples: [ + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.plus(7, 'days')", + evaluated: '[DateTime: 2024-04-07T18:49:00.000Z]', + }, + { + example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.plus(4, 'years')", + evaluated: '[DateTime: 2028-03-30T18:49:00.000Z]', + }, + ], section: 'edit', - returnType: 'Date', + returnType: 'DateTime', args: [ - { name: 'n', type: 'number' }, - { name: 'unit?', type: 'DurationUnit' }, + { + name: 'n', + description: + 'The number of units to add. Or use a Luxon Duration object to add multiple units at once.', + type: 'number | object', + }, + { + name: 'unit', + optional: true, + description: + 'The units of the number. One of: years, months, weeks, days, hours, minutes, seconds, milliseconds', + default: '"milliseconds"', + type: 'string', + }, ], docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-plus', }; +diffTo.doc = { + name: 'diffTo', + description: 'Returns the difference between two DateTimes, in the given unit(s)', + examples: [ + { + example: "dt = '2025-01-01'.toDateTime()\ndt.diffTo('2024-03-30T18:49:07.234', 'days')", + evaluated: '276.21', + }, + { + example: + "dt1 = '2025-01-01T00:00:00.000'.toDateTime();\ndt2 = '2024-03-30T18:49:07.234'.toDateTime();\ndt1.diffTo(dt2, ['months', 'days'])", + evaluated: '{ months: 9, days: 1.21 }', + }, + ], + section: 'compare', + returnType: 'number | Record', + args: [ + { + name: 'otherDateTime', + default: '$now', + description: + 'The moment to subtract the base DateTime from. Can be an ISO date string or a Luxon DateTime.', + type: 'string | DateTime', + }, + { + name: 'unit', + default: "'days'", + description: + 'The unit, or array of units, to return the result in. Possible values: years, months, weeks, days, hours, minutes, seconds, milliseconds.', + type: 'string | string[]', + }, + ], + docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-diffTo', +}; + +diffToNow.doc = { + name: 'diffToNow', + description: + 'Returns the difference between the current moment and the DateTime, in the given unit(s). For a textual representation, use toRelative() instead.', + examples: [ + { + example: "dt = '2023-03-30T18:49:07.234'.toDateTime()\ndt.diffToNow('days')", + evaluated: '371.9', + }, + { + example: "dt = '2023-03-30T18:49:07.234.toDateTime()\ndt.diffToNow(['months', 'days'])", + evaluated: '{ months: 12, days: 5.9 }', + }, + ], + section: 'compare', + returnType: 'number | Record', + args: [ + { + name: 'unit', + description: + 'The unit, or array of units, to return the result in. Possible values: years, months, weeks, days, hours, minutes, seconds, milliseconds.', + default: "'days'", + type: 'string | string[]', + }, + ], + docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-diffToNow', +}; + export const dateExtensions: ExtensionMap = { typeName: 'Date', functions: { @@ -361,6 +579,8 @@ export const dateExtensions: ExtensionMap = { plus, format, toDateTime, + diffTo, + diffToNow, toInt, toFloat, toBoolean, diff --git a/packages/workflow/src/Extensions/StringExtensions.ts b/packages/workflow/src/Extensions/StringExtensions.ts index 7062e2f6323c8..592aa8ac3c2a0 100644 --- a/packages/workflow/src/Extensions/StringExtensions.ts +++ b/packages/workflow/src/Extensions/StringExtensions.ts @@ -217,7 +217,7 @@ function toDate(value: string): Date { return date; } -function toDateTime(value: string, extraArgs: [string]): DateTime { +export function toDateTime(value: string, extraArgs: [string] = ['']): DateTime { try { const [valueFormat] = extraArgs; diff --git a/packages/workflow/test/ExpressionExtensions/DateExtensions.test.ts b/packages/workflow/test/ExpressionExtensions/DateExtensions.test.ts index e2fd830f11d24..2e542fc377e4e 100644 --- a/packages/workflow/test/ExpressionExtensions/DateExtensions.test.ts +++ b/packages/workflow/test/ExpressionExtensions/DateExtensions.test.ts @@ -109,6 +109,22 @@ describe('Data Transformation Functions', () => { ).toThrow(); }); + test('.diffTo() should work with a single unit', () => { + expect( + evaluate( + "={{ '2025-01-01'.toDateTime().diffTo('2024-03-30T18:49:07.234', 'days').floor() }}", + ), + ).toEqual(276); + }); + + test('.diffTo() should work with an array of units', () => { + expect( + evaluate( + "={{ '2025-01-01T00:00:00.000'.toDateTime().diffTo('2024-03-30T18:49:07.234', ['months', 'days']) }}", + ), + ).toEqual({ months: 9, days: 1.2158884953703704 }); + }); + describe('toDateTime', () => { test('should return itself for DateTime', () => { const result = evaluate(