298 lines
9.4 KiB
JavaScript
298 lines
9.4 KiB
JavaScript
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;
|
||
resultStepSize = (timeValue * (1.125) / 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 {
|
||
console.log('less than one minutes final case timeValue:', secondToDecide, dd, hh, mm);
|
||
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";
|
||
}
|
||
|
||
/** UNUSED
|
||
* Converts seconds into a formatted string with time units.
|
||
* 將秒數轉換成帶有時間單位的格式
|
||
*
|
||
* @param {number} second - Total seconds
|
||
* 總秒數
|
||
* @param {number} fixedNumber - Number of decimal places
|
||
* 小數點後幾位
|
||
* @returns {string} - The formatted time string (e.g., 1 day, 6.8 hrs)
|
||
* 轉換完的格式(ex: 1 day, 6.8 hrs)
|
||
*/
|
||
|
||
/**
|
||
* 將秒數轉換成帶有縮寫時間單位的格式
|
||
* @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 % day) / hour);
|
||
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 % day) / 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;
|
||
}
|
||
|
||
|
||
/** UNUSED
|
||
* 將時間轉換成不同日期單位的格式
|
||
* @param { string } date 日期
|
||
* @param { string } maxX 該 data 最大的日期,格式是 timestamp
|
||
* @param { string } minX 該 data 最小的日期,格式是 timestamp
|
||
*/
|
||
export function getDateLabelByMinMaxDate(date, maxDate, minDate) {
|
||
// 將時間字串轉換為時間物件
|
||
// new Date(time) 之後不用 getTime(),因為在JavaScript中,
|
||
// 日期物件是以時間戳記(timestamp)的形式存儲的。當創建一個新的日期物件時,
|
||
// 它內部會自動轉換時間字串為時間戳記。
|
||
date = new Date(date);
|
||
maxDate = new Date(maxDate);
|
||
minDate = new Date(minDate);
|
||
|
||
// 計算時間差距
|
||
let timeDiff = maxDate - minDate;
|
||
|
||
// 計算相差的月份
|
||
let diffMonths = (maxDate.getFullYear() - minDate.getFullYear()) * 12;
|
||
diffMonths -= minDate.getMonth();
|
||
diffMonths += maxDate.getMonth();
|
||
|
||
// 計算相差的日期,要取整數才能接續下方的邏輯判斷 `diffDays > 0`
|
||
// 秒 * 分鐘 * 小時 = 一天的時間量
|
||
const diffDays = Math.floor(timeDiff / ( 60 * 60 * 24));
|
||
|
||
// 計算相差的小時、分鐘、秒
|
||
const diffHours = Math.floor(timeDiff / (60 * 60));
|
||
const diffMinutes = Math.floor(timeDiff / 60);
|
||
const diffSeconds = Math.floor(timeDiff);
|
||
|
||
// 顯示結果
|
||
if (diffMonths > 1) {
|
||
return moment(date).format('YYYY/MM/DD');
|
||
}
|
||
else if (diffDays > 1) {
|
||
return moment(date).format('MM/DD');
|
||
}
|
||
else if (diffHours > 1) {
|
||
return moment(date).format('MM/DD hh:00');
|
||
}
|
||
else if (diffMinutes > 1) {
|
||
return moment(date).format('MM/DD hh:mm');
|
||
}
|
||
else {
|
||
return moment(date).format('hh:mm:ss');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 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<number>} 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'; // 月
|
||
}
|
||
|
||
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<number>} timeStampArr
|
||
* @param {string} timeFormat For example, 'MM/DD'
|
||
*/
|
||
export const mapTimestampToAxisTicksByFormat = (timeStampArr, timeFormat) => {
|
||
if (timeStampArr) {
|
||
return timeStampArr.map(ts => moment(ts).format(timeFormat));
|
||
}
|
||
}; |