import moment from 'moment'; const TOFIXED_DEICMAL = 1; /** * 若想要有等差的Y軸刻度,則必須確保index是乘以一個共通的被乘數 * 此被乘數就是 stepSize * @param {number} maxTimeInSecond * @returns {object} {resultStepSize, unitToUse} */ export const getStepSizeOfYTicks = (maxTimeInSecond, numOfParts) => { const {unitToUse, timeValue} = getTimeUnitAndValueToUse(maxTimeInSecond); let resultStepSize; const getLarger = 1 + (1 / (numOfParts - 1)); resultStepSize = (timeValue * getLarger / numOfParts); return {resultStepSize, unitToUse}; } /** * Convert second to possibly day or hour or mins. * @param {number} secondToDecide * @returns {object} {unitToUse, timeValue} where timeValue is measured in unitToUse */ const getTimeUnitAndValueToUse = (secondToDecide) => { const day = 24 * 60 * 60; const hour = 60 * 60; const minutes = 60; const dd = secondToDecide / day; const hh = secondToDecide / hour; const mm = secondToDecide / minutes; if (dd > 0 && dd > 1) { return { unitToUse: "d", timeValue: secondToDecide / day, }; } else if (hh > 0 && hh > 1) { return { unitToUse: "h", timeValue: secondToDecide / hour, }; } else if (mm > 0 && mm > 1) { return { unitToUse: "m", timeValue: secondToDecide / minutes, }; } else { return { unitToUse: "s", timeValue: secondToDecide, } } }; /** * For the display of PrimeVue chart. * According to the max time of the data given, * split the Y axis into equal part as ticks. * @param {number} stepSize stepSize of Y axis * @param {number} index index of current visiting tick on Y axis * @param {string} unitToUse time unit to display; "dhms" usually */ export function getYTicksByIndex(stepSize, index, unitToUse){ const rawStepsizeMultIndex = (stepSize * index).toString(); const shortenStepsizeMultIndex = rawStepsizeMultIndex.substring( 0, rawStepsizeMultIndex.indexOf('.') + 1 + TOFIXED_DEICMAL); return `${shortenStepsizeMultIndex}${unitToUse}`; }; /** * 將秒數轉換成帶有時間單位的格式 * @param {number} second 總秒數 * @param {number} fixedNumber 小數點後幾位 * @returns {string} 轉換完的格式(ex: 1 day, 6.8 hrs) */ export function getTimeLabel(second, fixedNumber = 0) { const day = 24 * 60 * 60; const hour = 60 * 60; const minutes = 60; // 取餘數的操作會把 second 限制在一天之內的範圍(即從0到86399之間), // 意思是過了多少天後剩下多少秒。 const dd = Math.floor(second / day); const hh = Math.floor((second % day) / hour); const mm = Math.floor((second % hour) / minutes); if(dd > 0){ return (second / day).toFixed(fixedNumber) + " days"; } else if(hh > 0){ return ((second % day) / hour).toFixed(fixedNumber) + " hrs"; } else if(mm > 0){ return ((second % hour) / minutes).toFixed(fixedNumber) + " mins"; } if(second == 0){ return second + " sec"; } return second + " sec"; } /** * 將秒數轉換成帶有縮寫時間單位的格式 * @param {number} second 總秒數 * @param {number} fixedNumber 小數點後幾位 * @returns {string} 轉換完的格式(ex: 1 d, 6.8 h) * 如果秒數(second)大於等於一天(86400 秒),返回以天為單位的時間,帶有 d 標誌。 * 如果秒數小於一天但大於等於一小時(3600 秒),返回以小時為單位的時間,帶有 h 標誌。 * 如果秒數小於一小時但大於等於一分鐘(60 秒),返回以分鐘為單位的時間,帶有 m 標誌。 * 如果秒數等於 0 秒,返回 "0s"。 * 如果秒數小於 60 秒但大於 0 秒,返回原始秒數,帶有 s 標誌。 */ export function simpleTimeLabel(second, fixedNumber = 0) { const day = 24 * 60 * 60; const hour = 60 * 60; const minutes = 60; const dd = Math.floor(second / day); const hh = Math.floor((second / hour) / day); const mm = Math.floor((second / hour) / minutes); if(dd > 0){ return (second / day).toFixed(fixedNumber) + "d"; } else if(hh > 0){ return ((second % day) / hour).toFixed(fixedNumber) + "h"; } else if(mm > 0){ return ((second % hour) / minutes).toFixed(fixedNumber) + "m"; } if(second == 0){ return second + "s"; } return second + "s"; } /** * 考慮到每包資料內的時間範圍有的大有的小, * 需要根據不同時間範圍級別的資料刻劃不同的Y軸座標, * 因此需要根據最大的時間值來決定Y軸刻度怎麼切分。 * 跟隨最大值的時間單位,將秒數轉換成帶有縮寫時間單位的格式 * @param {number} second 要轉換單位的秒數 * @param {number} max 該 data 中的最大值 * @param {number} fixedNumber 小數點後幾位 * @returns {string} 轉換完的格式(ex: 1 d, 6.8 h) */ export function followTimeLabel(second, max, fixedNumber = 0) { const day = 24 * 60 * 60; const hour = 60 * 60; const minutes = 60; const dd = max / day; const hh = max / hour; const mm = max/ minutes; let maxUnit = ''; let result = ""; if (dd > 1) { maxUnit = 'd'; } else if (hh > 1) { maxUnit = 'h'; } else if (mm > 1) { maxUnit = 'm'; } else { maxUnit = 's'; } switch (maxUnit) { case 'd': if((second / day) === 0) { fixedNumber = 0; } result = (second / day).toFixed(fixedNumber) + 'd'; break; case 'h': if((second / hour) === 0) { fixedNumber = 0; } result = (second / hour).toFixed(fixedNumber) + 'h'; break; case 'm': if((second / minutes) === 0) { fixedNumber = 0; } result = (second / minutes).toFixed(fixedNumber) + 'm'; break; case 's': if(second === 0) { fixedNumber = 0; } result = second.toFixed(fixedNumber) + 's'; break; } return result; } /** * Select an appropriate time format based on the time difference. * 根據時間差距選擇適合的時間格式 * 舉例 月: 2022/06 * 舉例 日: 06/06 * 舉例 時: 03/05 12:00 * 舉例 分: 03/05 12:15 * 舉例 秒: 09:05:32 * @param {Array} timestamps - An array of timestamps. * @returns {string} - The suitable time format string. */ export const setTimeStringFormatBaseOnTimeDifference = (minTimeStamp, maxTimeStamp) => { const timeDifferenceInSeconds = maxTimeStamp - minTimeStamp; let dateFormat; if (timeDifferenceInSeconds < 60) { dateFormat = 'HH:mm:ss'; // 秒 } else if (timeDifferenceInSeconds < 3600) { dateFormat = 'MM/DD HH:mm'; // 分鐘 } else if (timeDifferenceInSeconds < 86400) { // 86400 秒 = 24 小時 dateFormat = 'MM/DD HH:mm'; // 小時 } else if (timeDifferenceInSeconds < 2592000) { // 2592000 秒 = 30 天 dateFormat = 'YYYY/MM/DD'; // 天 } else { dateFormat = 'YYYY/MM/DD'; // 月 } return dateFormat; }; /** * Converts an array of Unix timestamps to formatted date strings based on the * specified format for use as axis ticks. * 根據指定的格式將 Unix 時間戳數組轉換為軸標籤的格式化日期字符串。 * @param {Array} timeStampArr * @param {string} timeFormat For example, 'MM/DD' */ export const mapTimestampToAxisTicksByFormat = (timeStampArr, timeFormat) => { if (timeStampArr) { return timeStampArr.map(ts => moment(ts).format(timeFormat)); } };