1// Copyright (C) 2018 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {assertTrue} from '../base/logging'; 16 17const EPSILON = 0.0000000001; 18 19// TODO(hjd): Combine with timeToCode. 20export function timeToString(sec: number) { 21 const units = ['s', 'ms', 'us', 'ns']; 22 const sign = Math.sign(sec); 23 let n = Math.abs(sec); 24 let u = 0; 25 while (n < 1 && n !== 0 && u < units.length - 1) { 26 n *= 1000; 27 u++; 28 } 29 return `${sign < 0 ? '-' : ''}${Math.round(n * 10) / 10} ${units[u]}`; 30} 31 32export function fromNs(ns: number) { 33 return ns / 1e9; 34} 35 36export function toNsFloor(seconds: number) { 37 return Math.floor(seconds * 1e9); 38} 39 40export function toNsCeil(seconds: number) { 41 return Math.ceil(seconds * 1e9); 42} 43 44export function toNs(seconds: number) { 45 return Math.round(seconds * 1e9); 46} 47 48// 1000000023ns -> "1.000 000 023" 49export function formatTimestamp(sec: number) { 50 const parts = sec.toFixed(9).split('.'); 51 parts[1] = parts[1].replace(/\B(?=(\d{3})+(?!\d))/g, ' '); 52 return parts.join('.'); 53} 54 55// TODO(hjd): Rename to formatTimestampWithUnits 56// 1000000023ns -> "1s 23ns" 57export function timeToCode(sec: number) { 58 let result = ''; 59 let ns = Math.round(sec * 1e9); 60 if (ns < 1) return '0s'; 61 const unitAndValue = [ 62 ['m', 60000000000], 63 ['s', 1000000000], 64 ['ms', 1000000], 65 ['us', 1000], 66 ['ns', 1] 67 ]; 68 unitAndValue.forEach(pair => { 69 const unit = pair[0] as string; 70 const val = pair[1] as number; 71 if (ns >= val) { 72 const i = Math.floor(ns / val); 73 ns -= i * val; 74 result += i.toLocaleString() + unit + ' '; 75 } 76 }); 77 return result.slice(0, -1); 78} 79 80export class TimeSpan { 81 readonly start: number; 82 readonly end: number; 83 84 constructor(start: number, end: number) { 85 assertTrue(start <= end); 86 this.start = start; 87 this.end = end; 88 } 89 90 clone() { 91 return new TimeSpan(this.start, this.end); 92 } 93 94 equals(other: TimeSpan): boolean { 95 return Math.abs(this.start - other.start) < EPSILON && 96 Math.abs(this.end - other.end) < EPSILON; 97 } 98 99 get duration() { 100 return this.end - this.start; 101 } 102 103 isInBounds(sec: number) { 104 return this.start <= sec && sec <= this.end; 105 } 106 107 add(sec: number): TimeSpan { 108 return new TimeSpan(this.start + sec, this.end + sec); 109 } 110 111 contains(other: TimeSpan) { 112 return this.start <= other.start && other.end <= this.end; 113 } 114} 115