Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(theme:_httpclient): add timestampSecond #1670

Merged
merged 4 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions packages/theme/src/services/http/http.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,19 @@ export class _HttpClient {
return params;
}

const { nullValueHandling, dateValueHandling } = this.cog;
Object.keys(params).forEach(key => {
let _data = params[key];
let paramValue = params[key];
// 忽略空值
if (this.cog.nullValueHandling === 'ignore' && _data == null) return;
if (nullValueHandling === 'ignore' && paramValue == null) return;
// 将时间转化为:时间戳 (秒)
if (this.cog.dateValueHandling === 'timestamp' && _data instanceof Date) {
_data = _data.valueOf();
if (
paramValue instanceof Date &&
(dateValueHandling === 'timestamp' || dateValueHandling === 'timestampSecond')
) {
paramValue = dateValueHandling === 'timestamp' ? paramValue.valueOf() : Math.trunc(paramValue.valueOf() / 1000);
}
newParams[key] = _data;
newParams[key] = paramValue;
});
return new HttpParams({ fromObject: newParams });
}
Expand Down
8 changes: 8 additions & 0 deletions packages/theme/src/services/http/http.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,14 @@ describe('theme: http.client', () => {
const ret = backend.expectOne(() => true) as TestRequest;
expect(ret.request.urlWithParams.length).toBeGreaterThan(URL.length + 15);
}));
it('should be working second-level timestamps', fakeAsync(() => {
createModule({ dateValueHandling: 'timestampSecond' });
const now = new Date();
http.get(URL, { a: now }).subscribe();
tick();
const ret = backend.expectOne(() => true) as TestRequest;
expect(ret.request.urlWithParams).toContain(`${Math.trunc(+now / 1000)}`);
}));
it('should be ingore null values', fakeAsync(() => {
createModule({ nullValueHandling: 'ignore' });
http.get(URL, { a: 1, b: null, c: undefined }).subscribe();
Expand Down
5 changes: 3 additions & 2 deletions packages/util/config/theme/http.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ export interface AlainThemeHttpClientConfig {
nullValueHandling?: 'include' | 'ignore';
/**
* 时间值处理,默认:`timestamp`
* - timestamp:时间戳
* - timestamp:时间戳毫秒级
* - timestampSecond:时间戳秒级
* - ignore:忽略处理,保持原始状态
*/
dateValueHandling?: 'timestamp' | 'ignore';
dateValueHandling?: 'timestamp' | 'timestampSecond' | 'ignore';
}
22 changes: 15 additions & 7 deletions packages/util/date-time/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ subtitle: Date Time Conversion
type: Tools
---

## toDate

Convert to `Date` format, support `Date, number, string` types, If the argument is a number, it is treated as a timestamp.

* `formatString` If parsing fails try to parse the date by pressing `formatString`
* `defaultValue` If parsing fails returned default value, default: `new Date(NaN)`
* `timestampSecond` Whether the incoming value is in seconds

## formatDate

Format date, supports `Date, number, string` types, If the argument is a number, it is treated as a timestamp.

* Please refer to [date-fnd format](https://date-fns.org/v2.30.0/docs/format) for string format
* `dateLocale` Recommended to be consistent with NG-ZORRO by using `inject(NZ_DATE_LOCALE)`

## dateTimePickerUtil

一组针对 [DatePicker](https://ng.ant.design/components/date-picker/en) 的工具类。
Expand Down Expand Up @@ -39,10 +54,3 @@ getTimeDistance('week')
- `month`, `-month` This month or last month
- `year`, `-year` This year or last year
- `time` Specify start time, default is `now`

## toDate

Return the date parsed from string using the given format string, If the argument is a number, it is treated as a timestamp.

* `formatString` If parsing fails try to parse the date by pressing `formatString`
* `defaultValue` If parsing fails returned default value, default: `new Date(NaN)`
22 changes: 15 additions & 7 deletions packages/util/date-time/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ subtitle: 日期时间转换
type: Tools
---

## toDate

转换成 `Date` 格式,支持 `Date, number, string` 类型,如果是 `number` 表示 Unix timestamp。

* `formatString` 如果转换失败尝试根据 `formatString` 格式来转换
* `defaultValue` 无效日期应返回的默认值,默认:`new Date(NaN)`
* `timestampSecond` 传入值是否秒级

## formatDate

格式化日期,支持 `Date, number, string` 类型,如果是 `number` 表示 Unix timestamp)。

* 字符串格式请参考 [date-fnd format](https://date-fns.org/v2.30.0/docs/format)
* `dateLocale` 建议通过使用 `inject(NZ_DATE_LOCALE)` 与 NG-ZORRO 保持一致

## dateTimePickerUtil

一组针对 [DatePicker](https://ng.ant.design/components/date-picker/en) 的工具类。
Expand Down Expand Up @@ -39,10 +54,3 @@ getTimeDistance('week')
- `month`、`-month` 本月或上月
- `year`、`-year` 今年或去年
- `time` 指定开始时间,默认为:`now`

## toDate

转换成 `Date` 格式,支持 `Date, number, string` 类型,如果是 `number` 表示 Unix timestamp。

* `formatString` 如果转换失败尝试根据 `formatString` 格式来转换
* `defaultValue` 无效日期应返回的默认值,默认:`new Date(NaN)`
5 changes: 3 additions & 2 deletions packages/util/date-time/time.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,13 @@ describe('util: time', () => {
expect(toDate(null).toString()).toBe(`Invalid Date`);
expect(f(toDate(NOW))).toBe(`2000-01-01 00:00:00`);
expect(f(toDate(+NOW))).toBe(`2000-01-01 00:00:00`);
expect(f(toDate(Math.trunc(+NOW / 1000), { timestampSecond: true }))).toBe(`2000-01-01 00:00:00`);
expect(f(toDate(`${+NOW}`))).toBe(`2000-01-01 00:00:00`);
expect(f(toDate(f(NOW)))).toBe(`2000-01-01 00:00:00`);
expect(isNaN(toDate(new String('') as NzSafeAny) as NzSafeAny)).toBe(true);
});

function f(d: Date): string {
return format(d, `yyyy-MM-dd HH:mm:ss`, { locale: zhCN });
function f(d: Date, formatString = `yyyy-MM-dd HH:mm:ss`): string {
return format(d, formatString, { locale: zhCN });
}
});
36 changes: 24 additions & 12 deletions packages/util/date-time/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from 'date-fns';

import type { NzSafeAny } from 'ng-zorro-antd/core/types';
import type { DateLocale } from 'ng-zorro-antd/i18n';
import { DateLocale } from 'ng-zorro-antd/i18n';

/**
* Get the time range, return `[ Date, Date]` for the start and end dates
Expand Down Expand Up @@ -84,30 +84,35 @@ export function fixEndTimeOfRange(dates: [Date, Date]): [Date, Date] {
return [startOfDay(dates[0]), endOfDay(dates[1])];
}

export type ToDateOptions = string | { formatString?: string; defaultValue?: NzSafeAny };
export interface ToDateOptions {
/** If parsing fails try to parse the date by pressing `formatString` */
formatString?: string;
/** If parsing fails returned default value, default: `new Date(NaN)` */
defaultValue?: NzSafeAny;
timestampSecond?: boolean;
}

/**
* Return the date parsed from string using the given format string
* - If the argument is a number, it is treated as a timestamp.
* Convert to `Date` format
*
* @param formatString If parsing fails try to parse the date by pressing `formatString`
* @param defaultValue If parsing fails returned default value, default: `new Date(NaN)`
* @param value When is a number, it's treated as a timestamp; If it's seconds, you need to provide the `options.timestampSecond` parameter.
*/
export function toDate(value?: Date | string | number | null, options?: ToDateOptions): Date {
if (typeof options === 'string') options = { formatString: options };
const { formatString, defaultValue } = {
export function toDate(value?: Date | string | number | null, options?: string | ToDateOptions): Date {
const { formatString, defaultValue, timestampSecond } = {
formatString: 'yyyy-MM-dd HH:mm:ss',
defaultValue: new Date(NaN),
...options
timestampSecond: false,
...(typeof options === 'string' ? { formatString: options } : options)
};
if (value == null) {
return defaultValue;
}
if (value instanceof Date) {
return value;
}
if (typeof value === 'number' || (typeof value === 'string' && /[0-9]{10,13}/.test(value))) {
return new Date(+value);
if (typeof value === 'number' || (typeof value === 'string' && /^[0-9]+$/.test(value))) {
const valueNumber = +value;
return new Date(timestampSecond ? valueNumber * 1000 : valueNumber);
}
let tryDate = parseISO(value);
if (isNaN(tryDate as NzSafeAny)) {
Expand All @@ -117,6 +122,13 @@ export function toDate(value?: Date | string | number | null, options?: ToDateOp
return isNaN(tryDate as NzSafeAny) ? defaultValue : tryDate;
}

/**
* Format date, supports `Date, number, string` types
*
* @param value When is a number, it is treated as a timestamp (Support seconds and milliseconds timestamp).
* @param formatString Please refer to [date-fnd format](https://date-fns.org/v2.30.0/docs/format) for string format
* @param dateLocale Recommended to be consistent with NG-ZORRO by using `inject(NZ_DATE_LOCALE)`
*/
export function formatDate(value: Date | string | number, formatString: string, dateLocale?: DateLocale): string {
value = toDate(value);
if (isNaN(value as NzSafeAny)) return '';
Expand Down
3 changes: 3 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import localeZh from '@angular/common/locales/zh';
import { APP_INITIALIZER, ErrorHandler, Inject, Injector, NgModule, PLATFORM_ID } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NZ_DATE_LOCALE } from 'ng-zorro-antd/i18n';
import { zhCN as dateLang } from 'date-fns/locale';

// angular i18n
registerLocaleData(localeZh);
Expand Down Expand Up @@ -82,6 +84,7 @@ function registerElements(injector: Injector, platformId: {}): void {
// deps: [ReuseTabService],
// },
{ provide: ALAIN_I18N_TOKEN, useClass: I18NService, multi: false },
{ provide: NZ_DATE_LOCALE, useValue: dateLang },
StartupService,
{
provide: APP_INITIALIZER,
Expand Down