Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
feat(duration-formatter): Adds formatting modes and improves output c…
Browse files Browse the repository at this point in the history
…onfiguration.

Fixes #444

BREAKING CHANGE: Removed experiementalFormatTime and
DtExperimentalFormatTime in favor of dtDuration pipe.
  • Loading branch information
rowa-audil authored and tomheller committed Feb 28, 2020
1 parent d1502af commit 9d6199a
Show file tree
Hide file tree
Showing 23 changed files with 1,462 additions and 352 deletions.
6 changes: 4 additions & 2 deletions apps/dev/src/formatters/formatters-demo.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ <h2>Rate</h2>
<p>per second: {{ exampleValue | dtCount | dtRate: 's' }}</p>
<p>Chaining rate + bytes: {{ exampleValue | dtRate: 's' | dtBytes }}</p>
<p>Chaining bytes + rate: {{ exampleValue | dtBytes | dtRate: 's' }}</p>
<h2>Duration</h2>
<p>Default: {{ exampleValue | dtDuration: 'DEFAULT' }}</p>
<p>
InputUnit(Day -> Second): Time Formatter: {{ exampleValue | dtTime: 'd':'s' }}
Format: precise & chaining duration + rate:
{{ exampleValue | dtDuration: 'PRECISE' | dtRate: 'min' }}
</p>
<p>InputUnit(Ms): Time Formatter: {{ exampleValue | dtTime }}</p>
37 changes: 25 additions & 12 deletions libs/barista-components/formatters/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ The `dtRate` pipe provides a way to add a rate info to the value

<ba-live-example name="DtExampleFormattersRate"></ba-live-example>

### Time
### Duration

The `dtTime` pipe provides a way to format a input time to a timestamp
The `dtDuration` pipe provides a way to format an input time to a timestamp

<ba-live-example name="DtExampleFormattersTime"></ba-live-example>

Expand Down Expand Up @@ -136,18 +136,31 @@ from a previous pipe with a rate. The function takes the following parameters:
| `input` | `DtFormattedValue | number` | | numeric value to be transformed by the pipe |
| `rateUnit` | `DtRateUnit | string` | | rate unit |

### Time
### Duration

The `formatTime` function converts a number to a timestamp. Default behaviour
will print the first available value/unit and only the next two descending
steps. Optionally you can set the input unit and which unit you want to set as
the lower limit.
The `formatDuration` function converts a number to a duration string and
consumes a formatMethod which configures how the output is built.

| Name | Type | Default | Description |
| ----------- | ------------ | ----------- | -------------------------------------------------------------------------------------------------------------- |
| `input` | `number` | `ms` | numeric value to be transformed by the pipe |
| `inputUnit` | `DtTimeUnit` | `undefined` | Which timeunit is used for the input |
| `toUnit` | `DtTimeUnit` | `undefined` | Which timeunit is the smallest possible output (Pipe disregards toUnit when unit is bigger than the inputUnit) |
- **'DEFAULT':** will look for the first unit that has a value and will only
print the next two descending units as long as they have values. The results
for each time unit will be rounded to a decimal number.
- **'PRECISE':** will only print the unit that it consumed or was set as the
outputUnit. The output value can be real numbers. (e.g. 1.54 s)
- **Custom/Number(1-n):** will tell the formatter to print a custom amount of
units.

You can specify the following properties on your options:

| Name | Type | Default | Description |
| -------------- | ------------------------------- | -------------- | ------------------------------------------------ |
| `input` | `number` | | Numeric value to be transformed |
| `formatMethod` | `'DEFAULT | 'PRECISE' | number` | `'DEFAULT'` | Formatting/Precision mode configuring the output |
| `outputUnit` | `DtTimeUnit` | `undefined` | Which unit to transform the input to |
| `inputUnit` | `DtTimeUnit` | `Milliseconds` | Which timeunit is used for the input |

#### Examples

<ba-live-example name="DtExampleFormattersDuration"></ba-live-example>

## Special uses (e.g. infographics, tiles)

Expand Down
9 changes: 2 additions & 7 deletions libs/barista-components/formatters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
* limitations under the License.
*/

import { DtTime } from './src/time/time';
import { formatTime } from './src/time/time-formatter';

export * from './src/formatters-module';
export * from './src/unit';
export {
Expand All @@ -37,8 +34,6 @@ export { formatRate } from './src/rate/rate-formatter';
export * from './src/rate/rate';
export * from './src/bits/bits-formatter';
export * from './src/bits/bits';
export {
formatTime as experimentalFormatTime,
DtTime as DtExperimentalFormatTime,
};
export * from './src/duration/duration';
export * from './src/duration/duration-formatter';
export { DtDateRange, dtFormatDateRange } from './src/date/date-range';
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @license
* Copyright 2020 Dynatrace LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { DtTimeUnit } from '../unit';

export type DurationMode = 'DEFAULT' | 'PRECISE' | number;

export function toDurationMode(
formatMethod: string | number,
): DurationMode | undefined {
if (formatMethod === 'DEFAULT') {
return 'DEFAULT';
} else if (formatMethod === 'PRECISE') {
return 'PRECISE';
} else if (typeof formatMethod === 'number') {
return formatMethod;
}
}

// tslint:disable: no-magic-numbers
/** Factorials needed for converting milliseconds to other time units */
export const CONVERSION_FACTORS_TO_MS = new Map<DtTimeUnit, number>([
[DtTimeUnit.YEAR, 12 * 30.41666 * 24 * 60 * 60 * 1000],
[DtTimeUnit.MONTH, 30.41666 * 24 * 60 * 60 * 1000],
[DtTimeUnit.DAY, 24 * 60 * 60 * 1000],
[DtTimeUnit.HOUR, 60 * 60 * 1000],
[DtTimeUnit.MINUTE, 60 * 1000],
[DtTimeUnit.SECOND, 1000],
[DtTimeUnit.MILLISECOND, 1],
[DtTimeUnit.MICROSECOND, 1000], // Has to be handled differently because IEEE can't handle floating point numbers very well
[DtTimeUnit.NANOSECOND, 1], // Has to be handled differently because IEEE can't handle floating point numbers very well
]);

/** Default for the conversionunit when no formatmethod is passed as a number. */
export const CONVERSIONUNITS = 3;

/** Use when converting a duration to micro- or nanoseconds */
export const MOVE_COMMA = 1000000;
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @license
* Copyright 2020 Dynatrace LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { DtTimeUnit } from '../../unit';
import {
CONVERSION_FACTORS_TO_MS,
MOVE_COMMA,
} from '../duration-formatter-constants';

/**
* Converts any duration to milliseconds
* @param duration numeric time value
* @param inputUnit dtTimeUnit value describing which unit the duration is in
*/
export function dtConvertToMilliseconds(
duration: number,
inputUnit: DtTimeUnit,
): number | undefined {
if (duration >= 0) {
console.log(
duration * CONVERSION_FACTORS_TO_MS.get(inputUnit)! * MOVE_COMMA,
inputUnit,
duration,
);
return inputUnit === DtTimeUnit.MICROSECOND ||
inputUnit === DtTimeUnit.NANOSECOND
? (duration * CONVERSION_FACTORS_TO_MS.get(inputUnit)!) / MOVE_COMMA
: duration * CONVERSION_FACTORS_TO_MS.get(inputUnit)!;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* @license
* Copyright 2020 Dynatrace LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export * from './convert-to-milliseconds';
export * from './transform-result';
export * from './transform-result-precise';
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* @license
* Copyright 2020 Dynatrace LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { DtTimeUnit } from '../../unit';
import {
CONVERSION_FACTORS_TO_MS,
DurationMode,
MOVE_COMMA,
} from '../duration-formatter-constants';
import { dtConvertToMilliseconds } from './convert-to-milliseconds';

/**
* Calculates the duration precisely. Will convert duration to the inputUnit or to the outputUnit if set. (floating point number for its corelated unit)
* @param duration numeric time value
* @param inputUnit dtTimeUnit value describing which unit the duration is in
* @param outputUnit dtTimeUnit | undefined value describing the unit to which it should format
* @param formatMethod the formatting method
*/

export function dtTransformResultPrecise(
duration: number,
inputUnit: DtTimeUnit,
outputUnit: DtTimeUnit | undefined,
formatMethod: DurationMode,
): Map<DtTimeUnit, string> | undefined {
const amount =
inputUnit === DtTimeUnit.MILLISECOND
? duration
: dtConvertToMilliseconds(duration, inputUnit);
return outputUnit !== undefined
? calcResult(amount!, formatMethod, outputUnit)
: calcResult(amount!, formatMethod, inputUnit);
}

function calcResult(
amount: number,
formatMethod: DurationMode,
unit: DtTimeUnit,
): Map<DtTimeUnit, string> {
let result = new Map<DtTimeUnit, string>();
if (formatMethod === 'PRECISE') {
amount = amount / CONVERSION_FACTORS_TO_MS.get(unit)!;
// Need to move the comma since IEEE can't handle floating point numbers very well.
if (unit === DtTimeUnit.MICROSECOND || unit === DtTimeUnit.NANOSECOND) {
amount *= MOVE_COMMA;
}
result.set(unit, amount.toString());
} else {
amount = Math.trunc(amount / CONVERSION_FACTORS_TO_MS.get(unit)!);
amount < 1 ? result.set(unit, '< 1') : result.set(unit, amount.toString());
}
return result;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* @license
* Copyright 2020 Dynatrace LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { DtTimeUnit } from '../../unit';
import {
CONVERSION_FACTORS_TO_MS,
CONVERSIONUNITS,
DurationMode,
MOVE_COMMA,
} from '../duration-formatter-constants';

/**
* Calculates output duration in either "DEFAULT" or "CUSTOM" mode.
* If precision is DEFAULT then displays a maximum of three units, but
* if precision is a number, then displays that amount of units.
* @param duration numeric time value
* @param inputUnit dtTimeUnit value describing which unit the duration is in
* @param formatMethod the formatting method
*/
export function dtTransformResult(
duration: number,
inputUnit: DtTimeUnit,
formatMethod: DurationMode,
): Map<DtTimeUnit, string> | undefined {
const result = new Map<DtTimeUnit, string>();

let rest = duration * CONVERSION_FACTORS_TO_MS.get(inputUnit)!;
let displayedUnits = 0;
let unitsToDisplay =
typeof formatMethod === 'number' ? formatMethod : CONVERSIONUNITS;
for (const key of Array.from(CONVERSION_FACTORS_TO_MS.keys())) {
if (key === DtTimeUnit.MICROSECOND) {
rest = Math.round(rest * MOVE_COMMA); // handles IEEE floating point number problem
}
const amount = Math.trunc(rest / CONVERSION_FACTORS_TO_MS.get(key)!);
if (displayedUnits < unitsToDisplay) {
if (amount > 0) {
result.set(key, amount.toString());
// Only increase when a unit with a value bigger than 0 exists
displayedUnits++;
} else if (displayedUnits > 0) {
// Only increase when a unit with a value is already set
displayedUnits++;
}
}
rest = rest - amount * CONVERSION_FACTORS_TO_MS.get(key)!;
}
return result;
}
Loading

0 comments on commit 9d6199a

Please sign in to comment.