Files
lucia-frontend/src/module/timeLabel.js

298 lines
9.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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));
}
};