Skip to content

Commit

Permalink
feat(helper): add date helper
Browse files Browse the repository at this point in the history
  • Loading branch information
Mister-Hope committed Jan 29, 2024
1 parent 2dc8ea5 commit 20e5e46
Show file tree
Hide file tree
Showing 6 changed files with 310 additions and 3 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
"release:publish": "lerna publish --dist-tag next from-package",
"release:version": "lerna version",
"test": "pnpm test:unit && pnpm test:e2e",
"test:cov": "vitest run --coverage ",
"test:cov": "cross-env TZ=Etc/UTC vitest run --coverage ",
"test:e2e": "pnpm --dir e2e e2e:ci:build && pnpm --dir e2e e2e:ci:build",
"test:unit": "vitest run"
"test:unit": "cross-env TZ=Etc/UTC vitest run"
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown",
Expand All @@ -37,6 +37,7 @@
"@vitest/coverage-istanbul": "^1.2.1",
"conventional-changelog-cli": "^4.1.0",
"cpx2": "^7.0.1",
"cross-env": "^7.0.3",
"eslint": "^8.56.0",
"eslint-config-vuepress": "^4.10.0",
"eslint-config-vuepress-typescript": "^4.10.0",
Expand Down
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion tools/helper/src/node/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './logger.js'
export * from './packageManager.js'
106 changes: 106 additions & 0 deletions tools/helper/src/shared/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { isDef, isString } from './helper.js'

export interface DateInfo {
type: 'date' | 'time' | 'full'
value: Date | null
}

const TIME_REG =
/(?:(\d{2,4})[/-](\d{1,2})[/-](\d{1,2}))?\s*(?:(\d{1,2}):(\d{1,2})(?::(\d{1,2})(?::(\d{3}))?)?)?/u

/**
* Get Date info from user input, return null when input is invalid
*
* 从用户输入中获取日期信息,输入无效时返回 null
*/
export const parseDate = (date: unknown): DateInfo | null => {
if (date instanceof Date) {
if (date.valueOf() === null) return null

const isDate =
date.getHours() === 0 &&
date.getMinutes() === 0 &&
date.getSeconds() === 0 &&
date.getMilliseconds() === 0

return {
type: isDate ? 'date' : 'full',
value: date,
}
}

if (isString(date)) {
const result = new Date(date)

if (result.valueOf()) {
const isDate =
result.getHours() === 0 &&
result.getMinutes() === 0 &&
result.getSeconds() === 0 &&
result.getMilliseconds() === 0

return {
type: isDate ? 'date' : 'full',
value: result,
}
} else {
const match = TIME_REG.exec(date.trim())

if (match) {
const [year, month, day, hour, minute, second] = match
.slice(1)
.map((item) => (isDef(item) ? parseInt(item) : item))

if (isDef(year) && isDef(month) && isDef(day)) {
const isDate = !isDef(hour) && !isDef(minute) && !isDef(second)

return {
type: isDate ? 'date' : 'full',
value: isDate
? new Date(
year && Number(year) < 100 ? year + 2000 : year,
month - 1,
day,
)
: new Date(
year && Number(year) < 100 ? year + 2000 : year,
month - 1,
day,
hour,
minute,
hour && minute && !second ? 0 : second,
),
}
}
}
}
}

return null
}

/**
* Date sorter from latest to oldest
*
* @description Invalid date will appear at last
*
* 最新到最旧的日期排序器
*
* @description 无效日期将出现在最后
*/
export const dateSorter = (
valueA: Date | number | string | undefined,
valueB: Date | number | string | undefined,
): number => {
const dateA = parseDate(
typeof valueA === 'number' ? new Date(valueA) : valueA,
)?.value
const dateB = parseDate(
typeof valueB === 'number' ? new Date(valueB) : valueB,
)?.value

if (!dateA) return dateB ? 1 : 0
if (!dateB) return -1

return dateB.getTime() - dateA.getTime()
}
1 change: 1 addition & 0 deletions tools/helper/src/shared/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './date.js'
export * from './helper.js'
export * from './url.js'
189 changes: 189 additions & 0 deletions tools/helper/tests/shared/date.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { describe, expect, it } from 'vitest'
import { dateSorter, parseDate } from '../../src/shared/date.js'

const getCurrentDate = (date: Date): Date =>
new Date(date.getTime() + new Date().getTimezoneOffset() * 60 * 1000)

describe('getDate()', () => {
it('Should return null', () => {
expect(parseDate(undefined)).toEqual(null)
})

describe('Should parse day', () => {
it('date string', () => {
expect(parseDate('2020-04-04T00:00:00.000Z')).toEqual({
type: 'date',
value: new Date('2020-04-04T00:00:00.000Z'),
})

expect(parseDate('2020-04-04T12:00:00.000Z')).toEqual({
type: 'full',
value: new Date('2020-04-04T12:00:00.000Z'),
})
})

it('date', () => {
expect(parseDate('1918-01-01')).toEqual({
value: getCurrentDate(new Date('1918-01-01')),
type: 'date',
})
})

it('simple date like string', () => {
expect(parseDate('2018-1-1')).toEqual({
value: getCurrentDate(new Date('2018-01-01')),
type: 'date',
})
})

it('date like string with splash', () => {
expect(parseDate('1918/01/01')).toEqual({
value: getCurrentDate(new Date('1918-01-01')),
type: 'date',
})

expect(parseDate('2018/1/1')).toEqual({
value: getCurrentDate(new Date('2018-01-01')),
type: 'date',
})
})

it('date string with spaces', () => {
expect(parseDate(' 1918-01-01')).toEqual({
value: getCurrentDate(new Date('1918-01-01')),
type: 'date',
})
})

it('date like string with spaces', () => {
expect(parseDate(' 2018-1-1 ')).toEqual({
value: getCurrentDate(new Date('2018-01-01')),
type: 'date',
})
})

it('date like string with splash and spaces', () => {
expect(parseDate(' 2018/1/1 ')).toEqual({
value: getCurrentDate(new Date('2018-01-01')),
type: 'date',
})
})

it('date like string with spaces and short year', () => {
expect(parseDate('18-01-01')).toEqual({
value: getCurrentDate(new Date('2018-01-01')),
type: 'date',
})
})

it('date like string with splash and spaces and short year', () => {
expect(parseDate('18/01/01 ')).toEqual({
value: getCurrentDate(new Date('2018-01-01')),
type: 'date',
})
})
})

it('Should parse whole date', () => {
expect(parseDate('2018/12/1 12:30')).toEqual({
value: new Date('2018-12-01 12:30'),
type: 'full',
})

expect(parseDate('18/12/01 12:30')).toEqual({
value: new Date('2018-12-01 12:30'),
type: 'full',
})

expect(parseDate(' 2018/12/01 12:30:00 ')).toEqual({
value: new Date('2018-12-01 12:30'),
type: 'full',
})

expect(parseDate(' 2018-12-01 12:30:00 ')).toEqual({
value: new Date('2018-12-01 12:30'),
type: 'full',
})

expect(parseDate(' 2018-12-1 12:30:00 ')).toEqual({
value: new Date('2018-12-01 12:30'),
type: 'full',
})
})
})

describe('dateSorter()', () => {
it('should return 0 if both dates are the same', () => {
const date = new Date('2022-01-01')

expect(dateSorter(date, date)).toBe(0)

expect(
dateSorter(
new Date('2020-04-04T00:00:00.000Z'),
new Date('2020-04-04T00:00:00.000Z'),
),
).toBe(0)
})

it('should return a positive number if dateA is older than dateB', () => {
const dateA = new Date('2022-01-01')
const dateB = new Date('2022-01-02')

expect(dateSorter(dateA, dateB)).toBeGreaterThan(0)

expect(
dateSorter(
new Date('2020-04-04T00:00:00.000Z'),
new Date('2020-05-05T00:00:00.000Z'),
),
).toBeGreaterThan(0)
})

it('should return a negative number if dateA is newer than dateB', () => {
const dateA = new Date('2022-01-02')
const dateB = new Date('2022-01-01')

expect(dateSorter(dateA, dateB)).toBeLessThan(0)
expect(
dateSorter(
new Date('2020-05-05T00:00:00.000Z'),
new Date('2020-04-04T00:00:00.000Z'),
),
).toBeLessThan(0)
})

it('should return 1 if dateA is undefined', () => {
const dateB = new Date('2022-01-01')

expect(dateSorter(undefined, dateB)).toBe(1)
})

it('should return -1 if dateB is undefined', () => {
const dateA = new Date('2022-01-01')

expect(dateSorter(dateA, undefined)).toBe(-1)
})

it('should return 0 if both dates are undefined', () => {
expect(dateSorter(undefined, undefined)).toBe(0)
})

it('should be a correct date sorter', () => {
const dates = [
'2021-01-01',
'2022-04-05 08:00:00',
undefined,
'04:38:45',
'2022-03-08',
]

expect(dates.sort(dateSorter)).toEqual([
'2022-04-05 08:00:00',
'2022-03-08',
'2021-01-01',
'04:38:45',
undefined,
])
})
})

0 comments on commit 20e5e46

Please sign in to comment.