From 3fb28ce9b0ff183989d1b7fee39fb4a6a0d3edad Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Thu, 19 Aug 2021 19:30:28 -0400 Subject: [PATCH 1/4] fix: support anything coercer supports for date parsing --- .../src/utilities/formatters/date/display-date.pipe.ts | 7 +++++-- .../cells/data-parsers/table-cell-timestamp-parser.ts | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/projects/common/src/utilities/formatters/date/display-date.pipe.ts b/projects/common/src/utilities/formatters/date/display-date.pipe.ts index 762db76f4..4e2c931d9 100644 --- a/projects/common/src/utilities/formatters/date/display-date.pipe.ts +++ b/projects/common/src/utilities/formatters/date/display-date.pipe.ts @@ -1,11 +1,14 @@ import { Pipe, PipeTransform } from '@angular/core'; +import { isNil } from 'lodash-es'; +import { DateCoercer } from '../../coercers/date-coercer'; import { DateFormatOptions, DateFormatter } from './date-formatter'; @Pipe({ name: 'htDisplayDate' }) export class DisplayDatePipe implements PipeTransform { - public transform(value?: Date | number | null, options: DateFormatOptions = {}): string { - return value !== null ? new DateFormatter(options).format(value) : '-'; + private readonly dateCoercer: DateCoercer = new DateCoercer(); + public transform(value?: string | Date | number | null, options: DateFormatOptions = {}): string { + return isNil(value) ? '-' : new DateFormatter(options).format(this.dateCoercer.coerce(value)); } } diff --git a/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.ts b/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.ts index 31ef3da31..831a3fb96 100644 --- a/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.ts +++ b/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.ts @@ -1,3 +1,4 @@ +import { DateCoercer } from '@hypertrace/common'; import { TableCellParser } from '../table-cell-parser'; import { TableCellParserBase } from '../table-cell-parser-base'; import { CoreTableCellParserType } from '../types/core-table-cell-parser-type'; @@ -6,6 +7,7 @@ import { CoreTableCellParserType } from '../types/core-table-cell-parser-type'; type: CoreTableCellParserType.Timestamp }) export class TableCellTimestampParser extends TableCellParserBase { + private readonly dateCoercer: DateCoercer = new DateCoercer(); public parseValue(cellData: CellData): Value { switch (typeof cellData) { case 'number': @@ -13,7 +15,7 @@ export class TableCellTimestampParser extends TableCellParserBase Date: Thu, 19 Aug 2021 19:51:23 -0400 Subject: [PATCH 2/4] chore: update tests, cleanup --- .../formatters/date/display-date.pipe.test.ts | 9 +++++++++ .../formatters/date/display-date.pipe.ts | 4 +++- .../table-cell-timestamp-parser.test.ts | 20 +++++++++++++++++++ .../table-cell-timestamp-parser.ts | 2 +- 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 projects/common/src/utilities/formatters/date/display-date.pipe.test.ts create mode 100644 projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.test.ts diff --git a/projects/common/src/utilities/formatters/date/display-date.pipe.test.ts b/projects/common/src/utilities/formatters/date/display-date.pipe.test.ts new file mode 100644 index 000000000..fcc53c6b8 --- /dev/null +++ b/projects/common/src/utilities/formatters/date/display-date.pipe.test.ts @@ -0,0 +1,9 @@ +import { DisplayDatePipe } from './display-date.pipe'; + +describe('Display date pipe', () => { + const dateString = '2021-08-19T23:35:45.861Z'; + + test('can render a formatted string', () => { + expect(new DisplayDatePipe().transform(dateString)).toEqual('19 Aug 2021 11:35 PM'); + }); +}); diff --git a/projects/common/src/utilities/formatters/date/display-date.pipe.ts b/projects/common/src/utilities/formatters/date/display-date.pipe.ts index 4e2c931d9..10fac2acc 100644 --- a/projects/common/src/utilities/formatters/date/display-date.pipe.ts +++ b/projects/common/src/utilities/formatters/date/display-date.pipe.ts @@ -9,6 +9,8 @@ import { DateFormatOptions, DateFormatter } from './date-formatter'; export class DisplayDatePipe implements PipeTransform { private readonly dateCoercer: DateCoercer = new DateCoercer(); public transform(value?: string | Date | number | null, options: DateFormatOptions = {}): string { - return isNil(value) ? '-' : new DateFormatter(options).format(this.dateCoercer.coerce(value)); + const coercedDate = this.dateCoercer.coerce(value); + + return isNil(coercedDate) ? '-' : new DateFormatter(options).format(coercedDate); } } diff --git a/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.test.ts b/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.test.ts new file mode 100644 index 000000000..87fb76786 --- /dev/null +++ b/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.test.ts @@ -0,0 +1,20 @@ +import { Injector } from '@angular/core'; +import { TableCellTimestampParser } from './table-cell-timestamp-parser'; + +describe('table cell timestamp parser', () => { + const dateString = '2021-08-19T23:35:45.861Z'; + const date = new Date(dateString); + const dateMillis = date.getTime(); + + test('can parse date strings', () => { + expect(new TableCellTimestampParser({} as Injector).parseValue(dateString)).toEqual(date); + }); + + test('can parse numbers', () => { + expect(new TableCellTimestampParser({} as Injector).parseValue(dateMillis)).toEqual(dateMillis); + }); + + test('can parse date objects', () => { + expect(new TableCellTimestampParser({} as Injector).parseValue(date)).toEqual(date); + }); +}); diff --git a/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.ts b/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.ts index 831a3fb96..6dc6851bd 100644 --- a/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.ts +++ b/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.ts @@ -24,5 +24,5 @@ export class TableCellTimestampParser extends TableCellParserBase Date: Thu, 19 Aug 2021 20:07:54 -0400 Subject: [PATCH 3/4] refactor: coercer in formatter --- .../utilities/formatters/date/date-formatter.test.ts | 9 +++++++++ .../src/utilities/formatters/date/date-formatter.ts | 11 +++++++---- .../formatters/date/display-date.pipe.test.ts | 9 --------- .../utilities/formatters/date/display-date.pipe.ts | 6 +----- .../data-parsers/table-cell-timestamp-parser.test.ts | 3 +++ 5 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 projects/common/src/utilities/formatters/date/date-formatter.test.ts delete mode 100644 projects/common/src/utilities/formatters/date/display-date.pipe.test.ts diff --git a/projects/common/src/utilities/formatters/date/date-formatter.test.ts b/projects/common/src/utilities/formatters/date/date-formatter.test.ts new file mode 100644 index 000000000..d4e95e3ef --- /dev/null +++ b/projects/common/src/utilities/formatters/date/date-formatter.test.ts @@ -0,0 +1,9 @@ +import { DateFormatter } from './date-formatter'; + +describe('Date formatter', () => { + const dateString = '2021-08-19T23:35:45.861Z'; + + test('can format a date string', () => { + expect(new DateFormatter().format(dateString)).toEqual('19 Aug 2021 11:35 PM'); + }); +}); diff --git a/projects/common/src/utilities/formatters/date/date-formatter.ts b/projects/common/src/utilities/formatters/date/date-formatter.ts index a1e14c7c9..1af7144f7 100644 --- a/projects/common/src/utilities/formatters/date/date-formatter.ts +++ b/projects/common/src/utilities/formatters/date/date-formatter.ts @@ -1,5 +1,6 @@ import { formatDate } from '@angular/common'; import { defaults } from 'lodash-es'; +import { DateCoercer } from '../../coercers/date-coercer'; export const enum DateFormatMode { TimeOnly, @@ -16,13 +17,14 @@ export class DateFormatter { }; protected readonly options: Readonly>; + private readonly dateCoercer: DateCoercer = new DateCoercer(); // Temporary placeholder, need to flesh this out public constructor(options: DateFormatOptions = {}) { this.options = this.applyOptionDefaults(options); } - public format(value: Date | number | undefined): string { + public format(value: Date | number | undefined | string): string { return this.convertDateToString(value); } @@ -32,12 +34,13 @@ export class DateFormatter { return newOptions; } - protected convertDateToString(value: Date | number | undefined): string { - if (value === undefined) { + protected convertDateToString(value: Date | number | string | undefined): string { + const coercedValue = this.dateCoercer.coerce(value); + if (coercedValue === undefined) { return '-'; } - return formatDate(value, this.getFormatString(), 'en_US'); + return formatDate(coercedValue, this.getFormatString(), 'en_US'); } private getFormatString(): string { diff --git a/projects/common/src/utilities/formatters/date/display-date.pipe.test.ts b/projects/common/src/utilities/formatters/date/display-date.pipe.test.ts deleted file mode 100644 index fcc53c6b8..000000000 --- a/projects/common/src/utilities/formatters/date/display-date.pipe.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { DisplayDatePipe } from './display-date.pipe'; - -describe('Display date pipe', () => { - const dateString = '2021-08-19T23:35:45.861Z'; - - test('can render a formatted string', () => { - expect(new DisplayDatePipe().transform(dateString)).toEqual('19 Aug 2021 11:35 PM'); - }); -}); diff --git a/projects/common/src/utilities/formatters/date/display-date.pipe.ts b/projects/common/src/utilities/formatters/date/display-date.pipe.ts index 10fac2acc..7e24a77fd 100644 --- a/projects/common/src/utilities/formatters/date/display-date.pipe.ts +++ b/projects/common/src/utilities/formatters/date/display-date.pipe.ts @@ -1,16 +1,12 @@ import { Pipe, PipeTransform } from '@angular/core'; import { isNil } from 'lodash-es'; -import { DateCoercer } from '../../coercers/date-coercer'; import { DateFormatOptions, DateFormatter } from './date-formatter'; @Pipe({ name: 'htDisplayDate' }) export class DisplayDatePipe implements PipeTransform { - private readonly dateCoercer: DateCoercer = new DateCoercer(); public transform(value?: string | Date | number | null, options: DateFormatOptions = {}): string { - const coercedDate = this.dateCoercer.coerce(value); - - return isNil(coercedDate) ? '-' : new DateFormatter(options).format(coercedDate); + return isNil(value) ? '-' : new DateFormatter(options).format(value); } } diff --git a/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.test.ts b/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.test.ts index 87fb76786..ca68255e5 100644 --- a/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.test.ts +++ b/projects/components/src/table/cells/data-parsers/table-cell-timestamp-parser.test.ts @@ -7,14 +7,17 @@ describe('table cell timestamp parser', () => { const dateMillis = date.getTime(); test('can parse date strings', () => { + // tslint:disable-next-line: no-object-literal-type-assertion expect(new TableCellTimestampParser({} as Injector).parseValue(dateString)).toEqual(date); }); test('can parse numbers', () => { + // tslint:disable-next-line: no-object-literal-type-assertion expect(new TableCellTimestampParser({} as Injector).parseValue(dateMillis)).toEqual(dateMillis); }); test('can parse date objects', () => { + // tslint:disable-next-line: no-object-literal-type-assertion expect(new TableCellTimestampParser({} as Injector).parseValue(date)).toEqual(date); }); }); From 6147b9ec7b839371098990ed7bed4effdc9e2a3a Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Thu, 19 Aug 2021 20:31:17 -0400 Subject: [PATCH 4/4] chore: static defaults --- .../common/src/utilities/coercers/date-coercer.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/projects/common/src/utilities/coercers/date-coercer.ts b/projects/common/src/utilities/coercers/date-coercer.ts index fd5991000..8d8a25e6c 100644 --- a/projects/common/src/utilities/coercers/date-coercer.ts +++ b/projects/common/src/utilities/coercers/date-coercer.ts @@ -1,19 +1,20 @@ +import { TimeDuration } from '../../time/time-duration'; +import { TimeUnit } from '../../time/time-unit.type'; import { Coercer, CoercerOptions } from './coercer'; export class DateCoercer extends Coercer { + private static readonly DEFAULT_TIME_WINDOW: DateCoercerOptions = { + earliestDate: new Date(Date.now() - new TimeDuration(10, TimeUnit.Year).toMillis()), + latestDate: new Date(Date.now() + new TimeDuration(10, TimeUnit.Year).toMillis()) + }; + public constructor(options: DateCoercerOptions = {}) { super(options); } protected assignDefaults(options: DateCoercerOptions): DateCoercerOptions { - const tenYearsInMillis = 10 * 365 * 24 * 60 * 60 * 1000; - const now = Date.now(); - const tenYearsAgo = new Date(now - tenYearsInMillis); - const tenYearsFuture = new Date(now + tenYearsInMillis); - return { - earliestDate: tenYearsAgo, - latestDate: tenYearsFuture, + ...DateCoercer.DEFAULT_TIME_WINDOW, ...super.assignDefaults(options) }; }