| // Copyright (C) 2018 The Android Open Source Project | |
| // | |
| // 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 {assertTrue} from '../base/logging'; | |
| const EPSILON = 0.0000000001; | |
| // TODO(hjd): Combine with timeToCode. | |
| export function timeToString(sec: number) { | |
| const units = ['s', 'ms', 'us', 'ns']; | |
| const sign = Math.sign(sec); | |
| let n = Math.abs(sec); | |
| let u = 0; | |
| while (n < 1 && n !== 0 && u < units.length - 1) { | |
| n *= 1000; | |
| u++; | |
| } | |
| return `${sign < 0 ? '-' : ''}${Math.round(n * 10) / 10} ${units[u]}`; | |
| } | |
| export function fromNs(ns: number) { | |
| return ns / 1e9; | |
| } | |
| export function toNsFloor(seconds: number) { | |
| return Math.floor(seconds * 1e9); | |
| } | |
| export function toNsCeil(seconds: number) { | |
| return Math.ceil(seconds * 1e9); | |
| } | |
| export function toNs(seconds: number) { | |
| return Math.round(seconds * 1e9); | |
| } | |
| // 1000000023ns -> "1.000 000 023" | |
| export function formatTimestamp(sec: number) { | |
| const parts = sec.toFixed(9).split('.'); | |
| parts[1] = parts[1].replace(/\B(?=(\d{3})+(?!\d))/g, ' '); | |
| return parts.join('.'); | |
| } | |
| // TODO(hjd): Rename to formatTimestampWithUnits | |
| // 1000000023ns -> "1s 23ns" | |
| export function timeToCode(sec: number): string { | |
| let result = ''; | |
| let ns = Math.round(sec * 1e9); | |
| if (ns < 1) return '0s'; | |
| const unitAndValue = [ | |
| ['m', 60000000000], | |
| ['s', 1000000000], | |
| ['ms', 1000000], | |
| ['us', 1000], | |
| ['ns', 1], | |
| ]; | |
| unitAndValue.forEach((pair) => { | |
| const unit = pair[0] as string; | |
| const val = pair[1] as number; | |
| if (ns >= val) { | |
| const i = Math.floor(ns / val); | |
| ns -= i * val; | |
| result += i.toLocaleString() + unit + ' '; | |
| } | |
| }); | |
| return result.slice(0, -1); | |
| } | |
| export function currentDateHourAndMinute(): string { | |
| const date = new Date(); | |
| return `${date.toISOString().substr(0, 10)}-${date.getHours()}-${ | |
| date.getMinutes()}`; | |
| } | |
| export class TimeSpan { | |
| readonly start: number; | |
| readonly end: number; | |
| constructor(start: number, end: number) { | |
| assertTrue(start <= end); | |
| this.start = start; | |
| this.end = end; | |
| } | |
| clone() { | |
| return new TimeSpan(this.start, this.end); | |
| } | |
| equals(other: TimeSpan): boolean { | |
| return Math.abs(this.start - other.start) < EPSILON && | |
| Math.abs(this.end - other.end) < EPSILON; | |
| } | |
| get duration() { | |
| return this.end - this.start; | |
| } | |
| isInBounds(sec: number) { | |
| return this.start <= sec && sec <= this.end; | |
| } | |
| add(sec: number): TimeSpan { | |
| return new TimeSpan(this.start + sec, this.end + sec); | |
| } | |
| contains(other: TimeSpan) { | |
| return this.start <= other.start && other.end <= this.end; | |
| } | |
| } |