From 27962ab2837b8dda0be7b58b1e55ac769047e533 Mon Sep 17 00:00:00 2001 From: chenos Date: Wed, 17 Apr 2024 22:22:52 +0800 Subject: [PATCH] fix: parse iso week (#4068) * fix: parse iso week * fix: error * test: ci * fix: ci test * fix: --allowOnly * fix: parse iso week --- .../utils/src/__tests__/parse-date.test.ts | 4 ++++ .../utils/src/__tests__/parse-filter.test.ts | 13 ++++++++-- packages/core/utils/src/parse-date.ts | 24 +++++++++++++++---- packages/core/utils/src/parse-filter.ts | 11 +++++---- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/packages/core/utils/src/__tests__/parse-date.test.ts b/packages/core/utils/src/__tests__/parse-date.test.ts index 7965e30b8c..485914a46f 100644 --- a/packages/core/utils/src/__tests__/parse-date.test.ts +++ b/packages/core/utils/src/__tests__/parse-date.test.ts @@ -32,12 +32,16 @@ describe('parse date', () => { expectDate('2023W01').toEqual(['2023-01-02T00:00:00.000Z', '2023-01-09T00:00:00.000Z']); expectDate('2023W01+08:00').toEqual(['2023-01-01T16:00:00.000Z', '2023-01-08T16:00:00.000Z']); expectDate('2023W01', { timezone: '+08:00' }).toEqual(['2023-01-01T16:00:00.000Z', '2023-01-08T16:00:00.000Z']); + expectDate('2024W16+08:00').toEqual(['2024-04-14T16:00:00.000Z', '2024-04-21T16:00:00.000Z']); + expectDate('2024W16').toEqual(['2024-04-15T00:00:00.000Z', '2024-04-22T00:00:00.000Z']); }); it('should parse week', async () => { expectDate('2023w01').toEqual(['2023-01-01T00:00:00.000Z', '2023-01-08T00:00:00.000Z']); expectDate('2023w01+08:00').toEqual(['2022-12-31T16:00:00.000Z', '2023-01-07T16:00:00.000Z']); expectDate('2023w01', { timezone: '+08:00' }).toEqual(['2022-12-31T16:00:00.000Z', '2023-01-07T16:00:00.000Z']); + expectDate('2024w16+08:00').toEqual(['2024-04-13T16:00:00.000Z', '2024-04-20T16:00:00.000Z']); + expectDate('2024w16').toEqual(['2024-04-14T00:00:00.000Z', '2024-04-21T00:00:00.000Z']); }); it('should parse month', () => { diff --git a/packages/core/utils/src/__tests__/parse-filter.test.ts b/packages/core/utils/src/__tests__/parse-filter.test.ts index 97f2712fc0..091316009d 100644 --- a/packages/core/utils/src/__tests__/parse-filter.test.ts +++ b/packages/core/utils/src/__tests__/parse-filter.test.ts @@ -80,8 +80,7 @@ describe('utc to unit', () => { unit: 'week', }).toBe('2023w01+00:00'); }); - // TODO: 本地运行没问题,但是在 github action 上跑不过 - it.skip('should be iso week', async () => { + it('should be iso week', async () => { expectUtc2unit({ now: '2023-01-08T00:00:00.000Z', timezone: '+00:00', @@ -96,6 +95,16 @@ describe('utc to unit', () => { now: '2023-01-01T00:00:00.000Z', unit: 'isoWeek', }).toBe('2022W52+00:00'); + expectUtc2unit({ + now: '2024-04-17T03:06:46.754Z', + unit: 'isoWeek', + offset: 1, + }).toBe('2024W17+00:00'); + expectUtc2unit({ + now: '2024-04-17T03:06:46.754Z', + unit: 'isoWeek', + offset: -1, + }).toBe('2024W15+00:00'); }); it('should be day', async () => { expectUtc2unit({ diff --git a/packages/core/utils/src/parse-date.ts b/packages/core/utils/src/parse-date.ts index 2a91715759..54e69b97c0 100644 --- a/packages/core/utils/src/parse-date.ts +++ b/packages/core/utils/src/parse-date.ts @@ -35,18 +35,34 @@ function parseQuarter(value) { } } -function parseWeek(value) { +export function parseWeek(value) { if (/^\d\d\d\d[W]\d\d$/.test(value)) { const arr = value.split('W'); - // dayjs 还不支持 dayjs("2019W19","gggg[W]ww") 这种语法 - // 参见:https://github.com/iamkun/dayjs/issues/784 + const year = dayjs(arr[0], 'YYYY').format('GGGG'); + if (year !== arr[0]) { + return { + unit: 'isoWeek', + start: dayjs(arr[0], 'YYYY') + .add(1, 'week') + .startOf('isoWeek') + .isoWeek(Number(arr[1])) + .format('YYYY-MM-DD HH:mm:ss'), + }; + } return { unit: 'isoWeek', - start: dayjs(arr[0], 'YYYY').add(Number(arr[1]), 'weeks').format('YYYY-MM-DD HH:mm:ss'), + start: dayjs(arr[0], 'YYYY').isoWeek(Number(arr[1])).format('YYYY-MM-DD HH:mm:ss'), }; } if (/^\d\d\d\d[w]\d\d$/.test(value)) { const arr = value.split('w'); + const year = dayjs(arr[0], 'YYYY').format('gggg'); + if (year !== arr[0]) { + return { + unit: 'week', + start: dayjs(arr[0], 'YYYY').add(1, 'week').startOf('week').week(Number(arr[1])).format('YYYY-MM-DD HH:mm:ss'), + }; + } return { unit: 'week', start: dayjs(arr[0], 'YYYY').week(Number(arr[1])).format('YYYY-MM-DD HH:mm:ss'), diff --git a/packages/core/utils/src/parse-filter.ts b/packages/core/utils/src/parse-filter.ts index 72435dd14e..0a48912226 100644 --- a/packages/core/utils/src/parse-filter.ts +++ b/packages/core/utils/src/parse-filter.ts @@ -1,5 +1,6 @@ import _ from 'lodash'; import set from 'lodash/set'; +import moment from 'moment'; import { offsetFromString } from './date'; import { dayjs } from './dayjs'; import { getValuesByPath } from './getValuesByPath'; @@ -212,14 +213,14 @@ export function getDayRange(options: GetDayRangeOptions) { ]; } -function toMoment(value) { +function toMoment(value, useMoment = false) { if (!value) { - return dayjs(); + return (useMoment ? moment() : dayjs()) as dayjs.Dayjs; } if (dayjs.isDayjs(value)) { return value; } - return dayjs(value); + return (useMoment ? moment(value) : dayjs(value)) as dayjs.Dayjs; } export type Utc2unitOptions = { @@ -231,7 +232,7 @@ export type Utc2unitOptions = { export function utc2unit(options: Utc2unitOptions) { const { now, unit, timezone = '+00:00', offset } = options; - let m = toMoment(now); + let m = toMoment(now, unit === 'isoWeek'); m = m.utcOffset(offsetFromString(timezone)); m = m.startOf(unit); if (offset > 0) { @@ -251,7 +252,7 @@ export function utc2unit(options: Utc2unitOptions) { return timezone ? r + timezone : r; } -const toUnit = (unit, offset?: number) => { +export const toUnit = (unit, offset?: number) => { return ({ now, timezone, field }) => { if (field?.timezone) { timezone = field?.timezone;