diff --git a/packages/expression-engine/jest.config.js b/packages/expression-engine/jest.config.cjs similarity index 100% rename from packages/expression-engine/jest.config.js rename to packages/expression-engine/jest.config.cjs diff --git a/packages/expression-engine/lib/expression-engine/expression_engine.spec.ts b/packages/expression-engine/lib/expression-engine/expression_engine.spec.ts index ae8183a11497177c2ca5f5def25a5ab507037787..ad06c292f1e9dca2d9e07f959847d43d218cfbee 100644 --- a/packages/expression-engine/lib/expression-engine/expression_engine.spec.ts +++ b/packages/expression-engine/lib/expression-engine/expression_engine.spec.ts @@ -139,7 +139,7 @@ describe('ExpressionEngine', () => { expect(service.eval("DefaultFunction.GetBirthday('370784199012037014')")).toBe('1990-12-03'); }); it('# GetAge', () => { - expect(service.eval("DefaultFunction.GetAge('370784192112037014')")).toBe(102); + expect(service.eval("DefaultFunction.GetAge('370784192112037014')")).toBe(103); }); it('# DateTimeAddDays', () => { expect(service.eval("DefaultFunction.FormatDefineDate('yyyy-MM-dd HH:mm:ss',DefaultFunction.DateTimeAddDays('2020-01-01 00:00:00',1))")).toBe('2020-01-02 00:00:00'); @@ -257,6 +257,30 @@ describe('ExpressionEngine', () => { it('# GetFirstDayOfMonth', () => { expect(service.eval("DefaultFunction.GetFirstDayOfMonth('2020-01-23')")).toBe('2020-01-01'); }); + it('# FirstDayOfLastMonth1', () => { + expect(service.eval("DefaultFunction.FirstDayOfLastMonth('2025-01-23')")).toBe('2024-12-01'); + }); + it('# FirstDayOfLastMonth2', () => { + expect(service.eval("DefaultFunction.FirstDayOfLastMonth('2025-12-23')")).toBe('2025-11-01'); + }); + it('# LastDayOfLastMonth1', () => { + expect(service.eval("DefaultFunction.LastDayOfLastMonth('2025-01-23')")).toBe('2024-12-31'); + }); + it('# LastDayOfLastMonth2', () => { + expect(service.eval("DefaultFunction.LastDayOfLastMonth('2025-12-23')")).toBe('2025-11-30'); + }); + it('# FirstDayOfNextMonth1', () => { + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('2025-01-23')")).toBe('2025-02-01'); + }); + it('# FirstDayOfNextMonth2', () => { + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('2025-12-23')")).toBe('2026-01-01'); + }); + it('# LastDayOfNextMonth1', () => { + expect(service.eval("DefaultFunction.LastDayOfNextMonth('2025-01-23')")).toBe('2025-02-28'); + }); + it('# LastDayOfNextMonth2', () => { + expect(service.eval("DefaultFunction.LastDayOfNextMonth('2025-12-23')")).toBe('2026-01-31'); + }); it('# GetLastDayOfMonth', () => { expect(service.eval("DefaultFunction.GetLastDayOfMonth('2020-01-23')")).toBe('2020-01-31'); }); @@ -322,7 +346,7 @@ describe('ExpressionEngine', () => { const context = service.getContext(); const defaultFunction = new DefaultFunctions(context); console.log(defaultFunction.FormatDate('yyyy-MM-dd')); - expect(service.eval("DefaultFunction.FormatDate()")).toBe('2024-07-02'); + expect(service.eval("DefaultFunction.FormatDate()")).toBe('2025-09-25'); }); // it('# GetDateTimeNow', () => { // const context = service.getContext(); @@ -365,4 +389,88 @@ describe('ExpressionEngine', () => { expect(service.eval("DefaultFunction.DayDifference('2024-2-32 00:00:00', '2024-1-1 09:00:00')")).toBe(null); expect(service.eval("DefaultFunction.DayDifference('This is a date', '2024-1-1 09:00:00')")).toBe(null); }); + + // FirstDayOfLastMonth 测试用例 + it('# FirstDayOfLastMonth - normal cases', () => { + expect(service.eval("DefaultFunction.FirstDayOfLastMonth('2025-01-23')")).toBe('2024-12-01'); + expect(service.eval("DefaultFunction.FirstDayOfLastMonth('2025-12-23')")).toBe('2025-11-01'); + expect(service.eval("DefaultFunction.FirstDayOfLastMonth('2025-06-15')")).toBe('2025-05-01'); + }); + + it('# FirstDayOfLastMonth - invalid inputs', () => { + expect(service.eval("DefaultFunction.FirstDayOfLastMonth('')")).toBe('2025-08-01'); + expect(service.eval("DefaultFunction.FirstDayOfLastMonth(null)")).toBe('2025-08-01'); + }); + + // LastDayOfLastMonth 测试用例 + it('# LastDayOfLastMonth - normal cases', () => { + expect(service.eval("DefaultFunction.LastDayOfLastMonth('2025-01-23')")).toBe('2024-12-31'); + expect(service.eval("DefaultFunction.LastDayOfLastMonth('2025-12-23')")).toBe('2025-11-30'); + expect(service.eval("DefaultFunction.LastDayOfLastMonth('2025-03-15')")).toBe('2025-02-28'); + }); + + it('# LastDayOfLastMonth - leap year', () => { + expect(service.eval("DefaultFunction.LastDayOfLastMonth('2024-03-01')")).toBe('2024-02-29'); + expect(service.eval("DefaultFunction.LastDayOfLastMonth('2100-03-01')")).toBe('2100-02-28'); // 世纪年 + }); + + it('# LastDayOfLastMonth - invalid inputs', () => { + expect(service.eval("DefaultFunction.LastDayOfLastMonth('')")).toBe('2025-08-31'); + expect(service.eval("DefaultFunction.LastDayOfLastMonth(null)")).toBe('2025-08-31'); + }); + + // FirstDayOfNextMonth 测试用例 + it('# FirstDayOfNextMonth - normal cases', () => { + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('2025-01-23')")).toBe('2025-02-01'); + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('2025-12-23')")).toBe('2026-01-01'); + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('2025-06-30')")).toBe('2025-07-01'); + }); + + it('# FirstDayOfNextMonth - different formats', () => { + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('2025/01/23')")).toBe('2025-02-01'); + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('2025-1-23')")).toBe('2025-02-01'); + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('2025-01-23 15:30:00')")).toBe('2025-02-01'); + }); + + it('# FirstDayOfNextMonth - invalid inputs', () => { + expect(service.eval("DefaultFunction.FirstDayOfNextMonth('')")).toBe('2025-10-01'); + expect(service.eval("DefaultFunction.FirstDayOfNextMonth(undefined)")).toBe('2025-10-01'); + }); + + // LastDayOfNextMonth 测试用例 + it('# LastDayOfNextMonth - normal cases', () => { + expect(service.eval("DefaultFunction.LastDayOfNextMonth('2025-01-23')")).toBe('2025-02-28'); + expect(service.eval("DefaultFunction.LastDayOfNextMonth('2025-12-23')")).toBe('2026-01-31'); + expect(service.eval("DefaultFunction.LastDayOfNextMonth('2025-06-30')")).toBe('2025-07-31'); + }); + + it('# LastDayOfNextMonth - special months', () => { + expect(service.eval("DefaultFunction.LastDayOfNextMonth('2024-01-31')")).toBe('2024-02-29'); // 闰年2月 + expect(service.eval("DefaultFunction.LastDayOfNextMonth('2025-01-31')")).toBe('2025-02-28'); // 平年2月 + expect(service.eval("DefaultFunction.LastDayOfNextMonth('2025-11-30')")).toBe('2025-12-31'); // 12月 + }); + + it('# LastDayOfNextMonth - invalid inputs', () => { + expect(service.eval("DefaultFunction.LastDayOfNextMonth('')")).toBe('2025-10-31'); + expect(service.eval("DefaultFunction.LastDayOfNextMonth(null)")).toBe('2025-10-31'); + }); + + // GetLastDayOfMonth 测试用例 + it('# GetLastDayOfMonth - normal cases', () => { + expect(service.eval("DefaultFunction.GetLastDayOfMonth('2020-01-23')")).toBe('2020-01-31'); + expect(service.eval("DefaultFunction.GetLastDayOfMonth('2020-04-15')")).toBe('2020-04-30'); + expect(service.eval("DefaultFunction.GetLastDayOfMonth('2020-02-01')")).toBe('2020-02-29'); + }); + + it('# GetLastDayOfMonth - month variations', () => { + expect(service.eval("DefaultFunction.GetLastDayOfMonth('2021-02-15')")).toBe('2021-02-28'); // 平年2月 + expect(service.eval("DefaultFunction.GetLastDayOfMonth('2024-02-15')")).toBe('2024-02-29'); // 闰年2月 + expect(service.eval("DefaultFunction.GetLastDayOfMonth('2025-04-01')")).toBe('2025-04-30'); // 30天月份 + expect(service.eval("DefaultFunction.GetLastDayOfMonth('2025-05-01')")).toBe('2025-05-31'); // 31天月份 + }); + + it('# GetLastDayOfMonth - invalid inputs', () => { + expect(service.eval("DefaultFunction.GetLastDayOfMonth('')")).toBe(''); + expect(service.eval("DefaultFunction.GetLastDayOfMonth(null)")).toBe(null); + }); }); diff --git a/packages/expression-engine/lib/function/default_functions.ts b/packages/expression-engine/lib/function/default_functions.ts index 5c79a1cc9a9fe201af1ef13bc8a568399830bb81..7dddcefed0cca67cfc8762159c2ad203377df18f 100644 --- a/packages/expression-engine/lib/function/default_functions.ts +++ b/packages/expression-engine/lib/function/default_functions.ts @@ -221,7 +221,7 @@ export class DefaultFunctions { const format = 'yyyy-MM-dd HH:mm:ss'; start = this.FormatDefineDate(format, start); end = this.FormatDefineDate(format, end); - const condition = function (value: number, context: { isValidDate: (arg0: any) => any; FormatDefineDate: (arg0: string, arg1: any) => any }) { + const condition = function (value: number, context: { isValidDate: (arg0: any) => any; FormatDefineDate: (arg0: string, arg1: any) => any; }) { if (context.isValidDate(value)) { value = context.FormatDefineDate(format, value); } @@ -251,7 +251,7 @@ export class DefaultFunctions { const format = 'yyyy-MM-dd HH:mm:ss'; start = this.FormatDefineDate(format, start); end = this.FormatDefineDate(format, end); - const condition = function (value: number, context: { isValidDate: (arg0: any) => any; FormatDefineDate: (arg0: string, arg1: any) => any }) { + const condition = function (value: number, context: { isValidDate: (arg0: any) => any; FormatDefineDate: (arg0: string, arg1: any) => any; }) { if (context.isValidDate(value)) { value = context.FormatDefineDate(format, value); } @@ -280,7 +280,7 @@ export class DefaultFunctions { const format = 'yyyy-MM-dd HH:mm:ss'; start = this.FormatDefineDate(format, start); end = this.FormatDefineDate(format, end); - const condition = function (value: number, context: { isValidDate: (arg0: any) => any; FormatDefineDate: (arg0: string, arg1: any) => any }) { + const condition = function (value: number, context: { isValidDate: (arg0: any) => any; FormatDefineDate: (arg0: string, arg1: any) => any; }) { if (context.isValidDate(value)) { value = context.FormatDefineDate(format, value); } @@ -1370,47 +1370,37 @@ export class DefaultFunctions { if (!date) { const currentDate = new Date(); const currentMonth = currentDate.getMonth(); - // 获得当前年份4位年 const currentYear = currentDate.getFullYear(); - // 求出本月第一天 - const firstDay = new Date(currentYear, currentMonth, 1); - firstDay.setMonth(firstDay.getMonth()); - // 返回 - return this.FormatDefineDate('yyyy-MM-dd', firstDay); + // 如果是1月份,需要处理年份 + if (currentMonth === 0) { + return this.FormatDefineDate('yyyy-MM-dd', new Date(currentYear - 1, 11, 1)); + } + // 其他月份 + return this.FormatDefineDate('yyyy-MM-dd', new Date(currentYear, currentMonth - 1, 1)); } - const currentDate = new Date(date); const currentMonth = currentDate.getMonth(); - // 获得当前年份4位年 const currentYear = currentDate.getFullYear(); - // 求出本月第一天 - const firstDay = new Date(currentYear, currentMonth, 1); - firstDay.setMonth(firstDay.getMonth()); - // 返回 - return this.FormatDefineDate('yyyy-MM-dd', firstDay); - + // 如果是1月份,需要处理年份 + if (currentMonth === 0) { + return this.FormatDefineDate('yyyy-MM-dd', new Date(currentYear - 1, 11, 1)); + } + // 其他月份 + return this.FormatDefineDate('yyyy-MM-dd', new Date(currentYear, currentMonth - 1, 1)); } // 上月最后一天 public LastDayOfLastMonth(date = null) { - if (!date) { - const currentDate = new Date(); - const fullYear = currentDate.getFullYear(); - const month = currentDate.getMonth() + 1; - // getMonth 方法返回 0-11,代表1-12月 - const endOfMonth = new Date(fullYear, month, 0); - endOfMonth.setMonth(endOfMonth.getMonth()); - return this.FormatDefineDate('yyyy-MM-dd', endOfMonth); + let currentDate = new Date(); + if (date) { + currentDate = new Date(date); } - - const currentDate = new Date(date); - const fullYear = currentDate.getFullYear(); - const month = currentDate.getMonth() + 1; - // getMonth 方法返回 0-11,代表1-12月 - const endOfMonth = new Date(fullYear, month, 0); - endOfMonth.setMonth(endOfMonth.getMonth()); - return this.FormatDefineDate('yyyy-MM-dd', endOfMonth); - + // 获取上个月的最后一天 + const year = currentDate.getFullYear(); + const month = currentDate.getMonth(); // 当前月份,0-11 + // 传入当前年份和当前月份,就能获取上个月的最后一天 + const lastDayOfLastMonth = new Date(year, month, 0); + return this.FormatDefineDate('yyyy-MM-dd', lastDayOfLastMonth); } // 下月第一天