From 164772afb8daa558c93b4aac53b152ac7cd7270b Mon Sep 17 00:00:00 2001 From: Junyi Date: Tue, 1 Apr 2025 15:10:28 +0800 Subject: [PATCH] fix(database): fix datetimeNoTz field (#6588) * fix(database): fix datetimeNoTz field * fix(database): fix test case --- .../src/fields/datetime-no-tz-field.ts | 55 ++++++++++--------- .../__tests__/triggers/collection.test.ts | 44 +++++++++++++++ 2 files changed, 72 insertions(+), 27 deletions(-) diff --git a/packages/core/database/src/fields/datetime-no-tz-field.ts b/packages/core/database/src/fields/datetime-no-tz-field.ts index 695ace4813..676ac778a2 100644 --- a/packages/core/database/src/fields/datetime-no-tz-field.ts +++ b/packages/core/database/src/fields/datetime-no-tz-field.ts @@ -29,26 +29,24 @@ export class DatetimeNoTzField extends Field { return DatetimeNoTzTypeMySQL; } - return DataTypes.STRING; + return DataTypes.DATE; } - init() { + beforeSave = async (instance, options) => { const { name, defaultToCurrentTime, onUpdateToCurrentTime } = this.options; - this.beforeSave = async (instance, options) => { - const value = instance.get(name); + const value = instance.get(name); - if (!value && instance.isNewRecord && defaultToCurrentTime) { - instance.set(name, new Date()); - return; - } + if (!value && instance.isNewRecord && defaultToCurrentTime) { + instance.set(name, new Date()); + return; + } - if (onUpdateToCurrentTime) { - instance.set(name, new Date()); - return; - } - }; - } + if (onUpdateToCurrentTime) { + instance.set(name, new Date()); + return; + } + }; additionalSequelizeOptions(): {} { const { name } = this.options; @@ -57,17 +55,14 @@ export class DatetimeNoTzField extends Field { const timezone = this.database.options.rawTimezone || '+00:00'; const isPg = this.database.inDialect('postgres'); + const isMySQLCompatibleDialect = this.database.isMySQLCompatibleDialect(); return { get() { const val = this.getDataValue(name); if (val instanceof Date) { - if (isPg) { - return moment(val).format('YYYY-MM-DD HH:mm:ss'); - } - // format to YYYY-MM-DD HH:mm:ss - const momentVal = moment(val).utcOffset(timezone); + const momentVal = moment(val); return momentVal.format('YYYY-MM-DD HH:mm:ss'); } @@ -75,18 +70,24 @@ export class DatetimeNoTzField extends Field { }, set(val) { - if (typeof val === 'string' && isIso8601(val)) { - const momentVal = moment(val).utcOffset(timezone); - val = momentVal.format('YYYY-MM-DD HH:mm:ss'); + if (val == null) { + return this.setDataValue(name, null); } - if (val && val instanceof Date) { - // format to YYYY-MM-DD HH:mm:ss - const momentVal = moment(val).utcOffset(timezone); - val = momentVal.format('YYYY-MM-DD HH:mm:ss'); + const dateOffset = new Date().getTimezoneOffset(); + const momentVal = moment(val); + if ((typeof val === 'string' && isIso8601(val)) || val instanceof Date) { + momentVal.utcOffset(timezone); + momentVal.utcOffset(-dateOffset, true); } - return this.setDataValue(name, val); + if (isMySQLCompatibleDialect) { + momentVal.millisecond(0); + } + + const date = momentVal.toDate(); + + return this.setDataValue(name, date); }, }; } diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/triggers/collection.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/triggers/collection.test.ts index f67b7a84e4..cff13e5d64 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/triggers/collection.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/triggers/collection.test.ts @@ -359,6 +359,50 @@ describe('workflow > triggers > collection', () => { const executions = await workflow.getExecutions(); expect(executions.length).toBe(1); }); + + it('datetime field not changed', async () => { + const workflow = await WorkflowModel.create({ + enabled: true, + sync: true, + type: 'collection', + config: { + mode: 2, + collection: 'posts', + changed: ['createdAt'], + }, + }); + + const post = await PostRepo.create({ values: { title: 't1' } }); + await PostRepo.update({ filterByTk: post.id, values: { ...post.get(), title: 't2' } }); + + const executions = await workflow.getExecutions(); + expect(executions.length).toBe(0); + }); + + it('datetimeNoTz field not changed', async () => { + db.getCollection('posts').addField('dateOnly', { + type: 'datetimeNoTz', + }); + + await db.sync(); + + const workflow = await WorkflowModel.create({ + enabled: true, + sync: true, + type: 'collection', + config: { + mode: 2, + collection: 'posts', + changed: ['dateOnly'], + }, + }); + + const post = await PostRepo.create({ values: { title: 't1', dateOnly: '2020-01-01 00:00:00' } }); + await PostRepo.update({ filterByTk: post.id, values: { ...post.get(), title: 't2' } }); + + const executions = await workflow.getExecutions(); + expect(executions.length).toBe(0); + }); }); describe('config.condition', () => {