github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/webapp/javascript/util/formatDate.ts (about) 1 /* eslint-disable no-underscore-dangle */ 2 import { add, format, getUnixTime } from 'date-fns'; 3 4 const multiplierMapping = new Map( 5 Object.entries({ 6 s: 'seconds', 7 m: 'minutes', 8 h: 'hours', 9 d: 'days', 10 w: 'weeks', 11 M: 'months', 12 y: 'years', 13 }) 14 ); 15 16 export function convertPresetsToDate(from: string) { 17 const match = from.match(/^now-(?<number>\d+)(?<multiplier>\D+)$/); 18 if (!match) { 19 throw new Error(`Could not apply regex to '${from}'`); 20 } 21 22 const { groups } = match; 23 if (!groups) { 24 throw new Error(`Could not extract required fields from regex'`); 25 } 26 27 const { number, multiplier } = groups; 28 29 const _multiplier = multiplierMapping.get(multiplier); 30 if (!_multiplier) { 31 throw new Error(`Cant access ${multiplier} from map`); 32 } 33 const now = new Date(); 34 35 const _from = 36 add(now, { 37 [_multiplier]: -number, 38 }).getTime() / 1000; 39 40 return { _from, number, _multiplier }; 41 } 42 43 export function readableRange( 44 from: string, 45 until: string, 46 offsetInMinutes: number 47 ) { 48 const dateFormat = 'yyyy-MM-dd hh:mm a'; 49 if (/^now-/.test(from) && until === 'now') { 50 const { number, _multiplier } = convertPresetsToDate(from); 51 const multiplier = 52 parseInt(number, 10) >= 2 ? _multiplier : _multiplier.slice(0, -1); 53 return `Last ${number} ${multiplier}`; 54 } 55 56 const d1 = getUTCdate(parseUnixTime(from), offsetInMinutes); 57 const d2 = getUTCdate(parseUnixTime(until), offsetInMinutes); 58 59 if (!isValidDate(d1) || !isValidDate(d2)) { 60 return ''; 61 } 62 63 return `${format(d1, dateFormat)} - ${format(d2, dateFormat)}`; 64 } 65 66 function isValidDate(d: Date) { 67 return d instanceof Date && !isNaN(d.getTime()); 68 } 69 70 /** 71 * formateAsOBject() returns a Date object 72 * based on the passed-in parameter value 73 * which is either a Number repsenting a date 74 * or a default preset(example: "now-1h") 75 * this is neccessary because the DatePicker component 76 * from react-datepicker package has a property (selected) 77 * that requires an input of type Date if we passed another 78 * type the Component will throw an error and the app will crash 79 */ 80 export function formatAsOBject(value: string) { 81 if (/^now-/.test(value)) { 82 const { _from } = convertPresetsToDate(value); 83 return new Date(_from * 1000); 84 } 85 if (value === 'now') { 86 return new Date(); 87 } 88 return parseUnixTime(value); 89 } 90 91 export function parseUnixTime(value: string) { 92 const parsed = parseInt(value, 10); 93 switch (value.length) { 94 default: 95 // Seconds. 96 return new Date(parsed * 1000); 97 case 13: // Milliseconds. 98 return new Date(parsed); 99 case 16: // Microseconds. 100 return new Date(Math.round(parsed / 1000)); 101 case 19: // Nanoseconds. 102 return new Date(Math.round(parsed / 1000 / 1000)); 103 } 104 } 105 106 export const getUTCdate = (date: Date, offsetInMinutes: number): Date => 107 offsetInMinutes === 0 108 ? new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000) 109 : date; 110 111 export const getTimelineFormatDate = (date: Date, hours: number) => { 112 if (hours < 12) { 113 return format(date, 'HH:mm:ss'); 114 } 115 if (hours >= 12 && hours <= 24) { 116 return format(date, 'HH:mm'); 117 } 118 if (hours > 24) { 119 return format(date, 'MMM do HH:mm'); 120 } 121 return format(date, 'MMM do HH:mm'); 122 }; 123 124 export function timezoneToOffset(timezone: 'utc' | 'browser'): number { 125 if (timezone === 'utc') { 126 return 0; 127 } 128 129 // Use browser's 130 // FIXME: this does not account for arbitrary timezones 131 // eg one that is not the user's browser 132 return new Date().getTimezoneOffset(); 133 } 134 135 /** 136 * given a Date returns its representation in unix timestamp 137 */ 138 export function toUnixTimestamp(d: Date) { 139 return getUnixTime(d); 140 }