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

Commit

Permalink
fix(duration-formatter): Fixes incorrect results when units are below…
Browse files Browse the repository at this point in the history
… milliseconds
  • Loading branch information
rowa-audil authored and lukasholzer committed Aug 18, 2020
1 parent 61c6339 commit b9affb7
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 82 deletions.
12 changes: 6 additions & 6 deletions apps/dev/src/formatters/formatters-demo.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ <h2>Bytes</h2>
<h2>Count</h2>
<p>Default: {{ exampleValue | dtCount }}</p>
<p>With unit: {{ exampleValue | dtCount: 'req.' }}</p>
<h2>Duration</h2>
<p>Default: {{ exampleValue | dtDuration: 'DEFAULT' }}</p>
<p>
Format: precise & chaining duration + rate:
{{ exampleValue | dtDuration: 'PRECISE' | dtRate: 'min' }}
</p>
<h2>Percent</h2>
<p>Default: {{ exampleValue | dtPercent }}</p>
<p>Max precision 1: {{ exampleValue | dtPercent: 1 }}</p>
Expand All @@ -22,9 +28,3 @@ <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>
Format: precise & chaining duration + rate:
{{ exampleValue | dtDuration: 'PRECISE' | dtRate: 'min' }}
</p>
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ export function toDurationMode(
// 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
[DtTimeUnit.YEAR, 12 * 30.41666 * 24 * 60 * 60 * 1000000000],
[DtTimeUnit.MONTH, 30.41666 * 24 * 60 * 60 * 1000000000],
[DtTimeUnit.DAY, 24 * 60 * 60 * 1000000000],
[DtTimeUnit.HOUR, 60 * 60 * 1000000000],
[DtTimeUnit.MINUTE, 60 * 1000000000],
[DtTimeUnit.SECOND, 1000000000],
[DtTimeUnit.MILLISECOND, 1000000],
[DtTimeUnit.MICROSECOND, 1000],
[DtTimeUnit.NANOSECOND, 1],
]);

/** 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;
/** Converting numbers like 0.001001 won't return the intended result so the comma needs to be moved. */
export const MOVE_COMMA = 100000000000;
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ import {
} from '../duration-formatter-constants';

/**
* Converts any duration to milliseconds
* Converts any duration to a Unit
* @param duration numeric time value
* @param inputUnit dtTimeUnit value describing which unit the duration is in
*/
export function dtConvertToMilliseconds(
export function dtConvertToUnit(
duration: number,
inputUnit: DtTimeUnit,
): number | undefined {
if (duration >= 0) {
return inputUnit === DtTimeUnit.MICROSECOND ||
inputUnit === DtTimeUnit.NANOSECOND
? (duration * CONVERSION_FACTORS_TO_MS.get(inputUnit)!) / MOVE_COMMA
): number {
const convertedDuration =
duration < 1
? (duration * MOVE_COMMA * CONVERSION_FACTORS_TO_MS.get(inputUnit)!) /
MOVE_COMMA
: duration * CONVERSION_FACTORS_TO_MS.get(inputUnit)!;
}
return convertedDuration;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
* limitations under the License.
*/

export * from './convert-to-milliseconds';
export * from './convert-to-unit';
export * from './transform-result';
export * from './transform-result-precise';
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ import { DtTimeUnit } from '../../unit';
import {
CONVERSION_FACTORS_TO_MS,
DurationMode,
MOVE_COMMA,
} from '../duration-formatter-constants';
import { dtConvertToMilliseconds } from './convert-to-milliseconds';
import { dtConvertToUnit } from './convert-to-unit';

/**
* Calculates the duration precisely. Will convert duration to the inputUnit or to the outputUnit if set. (floating point number for its corelated unit)
Expand All @@ -38,10 +37,7 @@ export function dtTransformResultPrecise(
formatMethod: DurationMode,
maxDecimals?: number,
): Map<DtTimeUnit, string> | undefined {
const amount =
inputUnit === DtTimeUnit.MILLISECOND
? duration
: dtConvertToMilliseconds(duration, inputUnit);
const amount = dtConvertToUnit(duration, inputUnit);
return outputUnit !== undefined
? calcResult(amount!, formatMethod, outputUnit, maxDecimals)
: calcResult(amount!, formatMethod, inputUnit, maxDecimals);
Expand All @@ -56,10 +52,6 @@ function calcResult(
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;
}
if (maxDecimals) {
amount = Math.round(amount * 10 ** maxDecimals) / 10 ** maxDecimals;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import {
CONVERSION_FACTORS_TO_MS,
CONVERSIONUNITS,
DurationMode,
MOVE_COMMA,
} from '../duration-formatter-constants';
import { dtConvertToUnit } from './convert-to-unit';

/**
* Calculates output duration in either "DEFAULT" or "CUSTOM" mode.
Expand All @@ -38,18 +38,15 @@ export function dtTransformResult(
const result = new Map<DtTimeUnit, string>();
const unitsToDisplay =
typeof formatMethod === 'number' ? formatMethod : CONVERSIONUNITS;
let rest = duration * CONVERSION_FACTORS_TO_MS.get(inputUnit)!;
let rest = dtConvertToUnit(duration, inputUnit);
// debugger;
let displayedUnits = 0;

let amount;
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)!);
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { dtConvertToMilliseconds } from '../duration-formatter-utils';
import { dtConvertToUnit } from '../duration-formatter-utils';
import { DtTimeUnit } from '../../unit';

describe('DtDurationFormatter', () => {
Expand All @@ -24,107 +24,107 @@ describe('DtDurationFormatter', () => {
output: number;
}

describe('dtConvertToMilliseconds()', () => {
describe('dtConvertToUnit()', () => {
[
{
duration: 1,
inputUnit: DtTimeUnit.MILLISECOND,
output: 1,
output: 1000000,
},
{
duration: 999.99,
inputUnit: DtTimeUnit.MILLISECOND,
output: 999.99,
output: 999990000,
},
{
duration: 1,
inputUnit: DtTimeUnit.SECOND,
output: 1000,
output: 1000000000,
},
{
duration: 1.5,
inputUnit: DtTimeUnit.SECOND,
output: 1500,
output: 1500000000,
},
{
duration: 1,
inputUnit: DtTimeUnit.MINUTE,
output: 60000,
output: 60000000000,
},
{
duration: 0.5,
inputUnit: DtTimeUnit.MINUTE,
output: 30000,
output: 30000000000,
},
{
duration: 0.00005,
inputUnit: DtTimeUnit.MINUTE,
output: 3,
output: 3000000,
},
{
duration: 1,
inputUnit: DtTimeUnit.HOUR,
output: 3600000,
output: 3600000000000,
},
{
duration: 1,
inputUnit: DtTimeUnit.DAY,
output: 86400000,
output: 86400000000000,
},
{
duration: 1,
inputUnit: DtTimeUnit.MONTH,
output: 2627999423.9999995,
output: 2627999423999999.5,
},
{
duration: 1,
inputUnit: DtTimeUnit.YEAR,
output: 31535993088,
output: 31535993088000000,
},
{
duration: 1,
inputUnit: DtTimeUnit.MICROSECOND,
output: 0.001,
output: 1000,
},
{
duration: 1000,
inputUnit: DtTimeUnit.MICROSECOND,
output: 1,
output: 1000000,
},
{
duration: 123.455,
inputUnit: DtTimeUnit.MICROSECOND,
output: 0.123455,
output: 123455,
},
{
duration: 1,
inputUnit: DtTimeUnit.NANOSECOND,
output: 0.000001,
output: 1,
},
{
duration: 1000000,
inputUnit: DtTimeUnit.NANOSECOND,
output: 1,
output: 1000000,
},
{
duration: 123.455,
inputUnit: DtTimeUnit.NANOSECOND,
output: 0.000123455,
output: 123.455,
},
{
duration: -123.455,
inputUnit: DtTimeUnit.NANOSECOND,
output: undefined,
output: -123.455,
},
{
duration: -0.001,
inputUnit: DtTimeUnit.NANOSECOND,
output: undefined,
output: -0.001,
},
{
duration: -1,
inputUnit: DtTimeUnit.NANOSECOND,
output: undefined,
output: -1,
},
{
duration: 0,
Expand All @@ -133,9 +133,9 @@ describe('DtDurationFormatter', () => {
},
].forEach((testCase: TestCase) => {
it(`Duration '${testCase.duration}', input unit '${testCase.inputUnit}' should equal to '${testCase.output}'`, () => {
expect(
dtConvertToMilliseconds(testCase.duration, testCase.inputUnit),
).toBe(testCase.output);
expect(dtConvertToUnit(testCase.duration, testCase.inputUnit)).toBe(
testCase.output,
);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('DtDurationFormatter', () => {
maxDecimals?: number;
}

describe('dtTransformResultPrecise() with OutputUnit', () => {
describe('dtTransformResultPrecise() Mode: OutputUnit', () => {
[
{
duration: 1,
Expand Down Expand Up @@ -145,7 +145,7 @@ describe('DtDurationFormatter', () => {
});
});

describe('dtTransformResultPrecise() Mode: Precise', () => {
describe('dtTransformResultPrecise() Mode: Precise + Output Unit', () => {
[
{
duration: 1500,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,7 @@ describe('DtDurationFormatter', () => {
displayedOutput: '1 µs 1 ns',
},
].forEach((testCase: TestCase) => {
// tslint:disable-next-line: dt-no-focused-tests
it.only(`Duration '${testCase.duration}', input unit '${testCase.inputUnit}' should equal to '${testCase.displayedOutput}'`, () => {
it(`Duration '${testCase.duration}', input unit '${testCase.inputUnit}' should equal to '${testCase.displayedOutput}'`, () => {
const formatMethod: DurationMode = toDurationMode(
testCase.formatMethod,
)!;
Expand All @@ -211,7 +210,7 @@ describe('DtDurationFormatter', () => {
});
});

describe('dtTransformResult() Mode: Custom', () => {
describe('dtTransformResult() Mode: Custom amount of units', () => {
[
{
duration: 123456789,
Expand Down
Loading

0 comments on commit b9affb7

Please sign in to comment.