Skip to content

Commit 322ee99

Browse files
fix: support anything coercer supports for date parsing (#1078)
* fix: support anything coercer supports for date parsing * chore: update tests, cleanup * refactor: coercer in formatter * chore: static defaults
1 parent 36aaeea commit 322ee99

File tree

6 files changed

+54
-15
lines changed

6 files changed

+54
-15
lines changed

projects/common/src/utilities/coercers/date-coercer.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1+
import { TimeDuration } from '../../time/time-duration';
2+
import { TimeUnit } from '../../time/time-unit.type';
13
import { Coercer, CoercerOptions } from './coercer';
24

35
export class DateCoercer extends Coercer<Date, DateCoercerOptions> {
6+
private static readonly DEFAULT_TIME_WINDOW: DateCoercerOptions = {
7+
earliestDate: new Date(Date.now() - new TimeDuration(10, TimeUnit.Year).toMillis()),
8+
latestDate: new Date(Date.now() + new TimeDuration(10, TimeUnit.Year).toMillis())
9+
};
10+
411
public constructor(options: DateCoercerOptions = {}) {
512
super(options);
613
}
714

815
protected assignDefaults(options: DateCoercerOptions): DateCoercerOptions {
9-
const tenYearsInMillis = 10 * 365 * 24 * 60 * 60 * 1000;
10-
const now = Date.now();
11-
const tenYearsAgo = new Date(now - tenYearsInMillis);
12-
const tenYearsFuture = new Date(now + tenYearsInMillis);
13-
1416
return {
15-
earliestDate: tenYearsAgo,
16-
latestDate: tenYearsFuture,
17+
...DateCoercer.DEFAULT_TIME_WINDOW,
1718
...super.assignDefaults(options)
1819
};
1920
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { DateFormatter } from './date-formatter';
2+
3+
describe('Date formatter', () => {
4+
const dateString = '2021-08-19T23:35:45.861Z';
5+
6+
test('can format a date string', () => {
7+
expect(new DateFormatter().format(dateString)).toEqual('19 Aug 2021 11:35 PM');
8+
});
9+
});

projects/common/src/utilities/formatters/date/date-formatter.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { formatDate } from '@angular/common';
22
import { defaults } from 'lodash-es';
3+
import { DateCoercer } from '../../coercers/date-coercer';
34

45
export const enum DateFormatMode {
56
TimeOnly,
@@ -16,13 +17,14 @@ export class DateFormatter {
1617
};
1718

1819
protected readonly options: Readonly<Required<DateFormatOptions>>;
20+
private readonly dateCoercer: DateCoercer = new DateCoercer();
1921

2022
// Temporary placeholder, need to flesh this out
2123
public constructor(options: DateFormatOptions = {}) {
2224
this.options = this.applyOptionDefaults(options);
2325
}
2426

25-
public format(value: Date | number | undefined): string {
27+
public format(value: Date | number | undefined | string): string {
2628
return this.convertDateToString(value);
2729
}
2830

@@ -32,12 +34,13 @@ export class DateFormatter {
3234
return newOptions;
3335
}
3436

35-
protected convertDateToString(value: Date | number | undefined): string {
36-
if (value === undefined) {
37+
protected convertDateToString(value: Date | number | string | undefined): string {
38+
const coercedValue = this.dateCoercer.coerce(value);
39+
if (coercedValue === undefined) {
3740
return '-';
3841
}
3942

40-
return formatDate(value, this.getFormatString(), 'en_US');
43+
return formatDate(coercedValue, this.getFormatString(), 'en_US');
4144
}
4245

4346
private getFormatString(): string {
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { Pipe, PipeTransform } from '@angular/core';
2+
import { isNil } from 'lodash-es';
23
import { DateFormatOptions, DateFormatter } from './date-formatter';
34

45
@Pipe({
56
name: 'htDisplayDate'
67
})
78
export class DisplayDatePipe implements PipeTransform {
8-
public transform(value?: Date | number | null, options: DateFormatOptions = {}): string {
9-
return value !== null ? new DateFormatter(options).format(value) : '-';
9+
public transform(value?: string | Date | number | null, options: DateFormatOptions = {}): string {
10+
return isNil(value) ? '-' : new DateFormatter(options).format(value);
1011
}
1112
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Injector } from '@angular/core';
2+
import { TableCellTimestampParser } from './table-cell-timestamp-parser';
3+
4+
describe('table cell timestamp parser', () => {
5+
const dateString = '2021-08-19T23:35:45.861Z';
6+
const date = new Date(dateString);
7+
const dateMillis = date.getTime();
8+
9+
test('can parse date strings', () => {
10+
// tslint:disable-next-line: no-object-literal-type-assertion
11+
expect(new TableCellTimestampParser({} as Injector).parseValue(dateString)).toEqual(date);
12+
});
13+
14+
test('can parse numbers', () => {
15+
// tslint:disable-next-line: no-object-literal-type-assertion
16+
expect(new TableCellTimestampParser({} as Injector).parseValue(dateMillis)).toEqual(dateMillis);
17+
});
18+
19+
test('can parse date objects', () => {
20+
// tslint:disable-next-line: no-object-literal-type-assertion
21+
expect(new TableCellTimestampParser({} as Injector).parseValue(date)).toEqual(date);
22+
});
23+
});
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { DateCoercer } from '@hypertrace/common';
12
import { TableCellParser } from '../table-cell-parser';
23
import { TableCellParserBase } from '../table-cell-parser-base';
34
import { CoreTableCellParserType } from '../types/core-table-cell-parser-type';
@@ -6,14 +7,15 @@ import { CoreTableCellParserType } from '../types/core-table-cell-parser-type';
67
type: CoreTableCellParserType.Timestamp
78
})
89
export class TableCellTimestampParser extends TableCellParserBase<CellData, Value, Value> {
10+
private readonly dateCoercer: DateCoercer = new DateCoercer();
911
public parseValue(cellData: CellData): Value {
1012
switch (typeof cellData) {
1113
case 'number':
1214
return cellData;
1315
case 'object':
1416
return cellData instanceof Date ? cellData : cellData.value;
1517
default:
16-
return undefined;
18+
return this.dateCoercer.coerce(cellData);
1719
}
1820
}
1921

@@ -22,5 +24,5 @@ export class TableCellTimestampParser extends TableCellParserBase<CellData, Valu
2224
}
2325
}
2426

25-
type CellData = Date | number | { value: Date | number };
27+
type CellData = Date | number | string | { value: Date | number };
2628
type Value = Date | number | undefined;

0 commit comments

Comments
 (0)