gantt/src/date_utils.js
2024-04-14 13:39:47 +05:30

252 lines
6.6 KiB
JavaScript

const YEAR = "year";
const MONTH = "month";
const DAY = "day";
const HOUR = "hour";
const MINUTE = "minute";
const SECOND = "second";
const MILLISECOND = "millisecond";
export default {
parse_duration(duration) {
const regex = /([0-9])+(y|m|d|h|min|s|ms)/gm;
const matches = regex.exec(duration);
if (matches !== null) {
if (matches[2] === "y") {
return { duration: parseInt(matches[1]), scale: `year` };
} else if (matches[2] === "m") {
return { duration: parseInt(matches[1]), scale: `month` };
} else if (matches[2] === "d") {
return { duration: parseInt(matches[1]), scale: `day` };
} else if (matches[2] === "h") {
return { duration: parseInt(matches[1]), scale: `hour` };
} else if (matches[2] === "min") {
return { duration: parseInt(matches[1]), scale: `minute` };
} else if (matches[2] === "s") {
return { duration: parseInt(matches[1]), scale: `second` };
} else if (matches[2] === "ms") {
return { duration: parseInt(matches[1]), scale: `millisecond` };
}
}
},
parse(date, date_separator = "-", time_separator = /[.:]/) {
if (date instanceof Date) {
return date;
}
if (typeof date === "string") {
let date_parts, time_parts;
const parts = date.split(" ");
date_parts = parts[0]
.split(date_separator)
.map((val) => parseInt(val, 10));
time_parts = parts[1] && parts[1].split(time_separator);
// month is 0 indexed
date_parts[1] = date_parts[1] ? date_parts[1] - 1 : 0;
let vals = date_parts;
if (time_parts && time_parts.length) {
if (time_parts.length === 4) {
time_parts[3] = "0." + time_parts[3];
time_parts[3] = parseFloat(time_parts[3]) * 1000;
}
vals = vals.concat(time_parts);
}
return new Date(...vals);
}
},
to_string(date, with_time = false) {
if (!(date instanceof Date)) {
throw new TypeError("Invalid argument type");
}
const vals = this.get_date_values(date).map((val, i) => {
if (i === 1) {
// add 1 for month
val = val + 1;
}
if (i === 6) {
return padStart(val + "", 3, "0");
}
return padStart(val + "", 2, "0");
});
const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`;
const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`;
return date_string + (with_time ? " " + time_string : "");
},
format(date, format_string = "YYYY-MM-DD HH:mm:ss.SSS", lang = "en") {
const dateTimeFormat = new Intl.DateTimeFormat(lang, {
month: "long",
});
const month_name = dateTimeFormat.format(date);
const month_name_capitalized =
month_name.charAt(0).toUpperCase() + month_name.slice(1);
const values = this.get_date_values(date).map((d) => padStart(d, 2, 0));
const format_map = {
YYYY: values[0],
MM: padStart(+values[1] + 1, 2, 0),
DD: values[2],
HH: values[3],
mm: values[4],
ss: values[5],
SSS: values[6],
D: values[2],
MMMM: month_name_capitalized,
MMM: month_name_capitalized,
};
let str = format_string;
const formatted_values = [];
Object.keys(format_map)
.sort((a, b) => b.length - a.length) // big string first
.forEach((key) => {
if (str.includes(key)) {
str = str.replaceAll(key, `$${formatted_values.length}`);
formatted_values.push(format_map[key]);
}
});
formatted_values.forEach((value, i) => {
str = str.replaceAll(`$${i}`, value);
});
return str;
},
diff(date_a, date_b, scale = DAY) {
let milliseconds, seconds, hours, minutes, days, months, years;
milliseconds = date_a - date_b;
seconds = milliseconds / 1000;
minutes = seconds / 60;
hours = minutes / 60;
days = hours / 24;
months = days / 30;
years = months / 12;
if (!scale.endsWith("s")) {
scale += "s";
}
return Math.floor(
{
milliseconds,
seconds,
minutes,
hours,
days,
months,
years,
}[scale],
);
},
today() {
const vals = this.get_date_values(new Date()).slice(0, 3);
return new Date(...vals);
},
now() {
return new Date();
},
add(date, qty, scale) {
qty = parseInt(qty, 10);
const vals = [
date.getFullYear() + (scale === YEAR ? qty : 0),
date.getMonth() + (scale === MONTH ? qty : 0),
date.getDate() + (scale === DAY ? qty : 0),
date.getHours() + (scale === HOUR ? qty : 0),
date.getMinutes() + (scale === MINUTE ? qty : 0),
date.getSeconds() + (scale === SECOND ? qty : 0),
date.getMilliseconds() + (scale === MILLISECOND ? qty : 0),
];
return new Date(...vals);
},
start_of(date, scale) {
const scores = {
[YEAR]: 6,
[MONTH]: 5,
[DAY]: 4,
[HOUR]: 3,
[MINUTE]: 2,
[SECOND]: 1,
[MILLISECOND]: 0,
};
function should_reset(_scale) {
const max_score = scores[scale];
return scores[_scale] <= max_score;
}
const vals = [
date.getFullYear(),
should_reset(YEAR) ? 0 : date.getMonth(),
should_reset(MONTH) ? 1 : date.getDate(),
should_reset(DAY) ? 0 : date.getHours(),
should_reset(HOUR) ? 0 : date.getMinutes(),
should_reset(MINUTE) ? 0 : date.getSeconds(),
should_reset(SECOND) ? 0 : date.getMilliseconds(),
];
return new Date(...vals);
},
clone(date) {
return new Date(...this.get_date_values(date));
},
get_date_values(date) {
return [
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds(),
];
},
get_days_in_month(date) {
const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const month = date.getMonth();
if (month !== 1) {
return no_of_days[month];
}
// Feb
const year = date.getFullYear();
if ((year % 4 === 0 && year % 100 != 0) || year % 400 === 0) {
return 29;
}
return 28;
},
};
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
function padStart(str, targetLength, padString) {
str = str + "";
targetLength = targetLength >> 0;
padString = String(typeof padString !== "undefined" ? padString : " ");
if (str.length > targetLength) {
return String(str);
} else {
targetLength = targetLength - str.length;
if (targetLength > padString.length) {
padString += padString.repeat(targetLength / padString.length);
}
return padString.slice(0, targetLength) + String(str);
}
}