function addYear(var1, years) {
let dateComponent = parseDateComponents(var1)
if( dateComponent == null || !dateComponent.format.includes("yyyy"))
return "null(日期格式错误或不支持计算)";
let date = new Date(dateComponent.year, dateComponent.month-1, dateComponent.day, dateComponent.hour, dateComponent.minute, dateComponent.second)
date.setFullYear(date.getFullYear() + years)
return recoverDateFormat(date, dateComponent.format);
}
function addMonth(var1,months) {
let dateComponent = parseDateComponents(var1)
if( dateComponent==null || !(dateComponent.format.includes("MM")
||dateComponent.format.includes("MMM")))
return "null(日期格式错误或不支持计算)";
let date = new Date(dateComponent.year, dateComponent.month-1, dateComponent.day, dateComponent.hour, dateComponent.minute, dateComponent.second)
date.setMonth(date.getMonth() + months)
return recoverDateFormat(date, dateComponent.format)
}
function addDay(var1,days) {
let dateComponent = parseDateComponents(var1)
if( dateComponent==null || !dateComponent.format.includes("dd"))
return "null(日期格式错误或不支持计算)";
let date = new Date(dateComponent.year, dateComponent.month-1, dateComponent.day, dateComponent.hour, dateComponent.minute, dateComponent.second)
date.setDate(date.getDate() + days)
return recoverDateFormat(date, dateComponent.format)
}
function addHour(var1,hours) {
if(isNaN(hours)) throw "参数hours必须为数字";
let dateComponent = parseDateComponents(var1)
if( dateComponent==null || !dateComponent.format.includes("HH"))
return "null(日期格式错误或不支持计算)";
let date = new Date(dateComponent.year, dateComponent.month-1, dateComponent.day, dateComponent.hour, dateComponent.minute, dateComponent.second)
date.setTime(date.getTime() + hours*60*60*1000)
return recoverDateFormat(date, dateComponent.format)
}
function addMinutes(var1,minutes) {
if(isNaN(minutes)) throw "参数minutes必须为数字";
let dateComponent = parseDateComponents(var1)
if( dateComponent==null || !dateComponent.format.includes("mm"))
return "null(日期格式错误或不支持计算)";
let date = new Date(dateComponent.year, dateComponent.month-1, dateComponent.day, dateComponent.hour, dateComponent.minute, dateComponent.second)
date.setTime(date.getTime() + minutes*60*1000)
return recoverDateFormat(date, dateComponent.format)
}
function addSeconds(var1,seconds) {
if(isNaN(seconds)) throw "参数seconds必须为数字";
let dateComponent = parseDateComponents(var1)
if(dateComponent==null || !dateComponent.format.includes("ss"))
return "null(日期格式错误或不支持计算)";
let date = new Date(dateComponent.year, dateComponent.month-1, dateComponent.day, dateComponent.hour, dateComponent.minute, dateComponent.second)
date.setTime(date.getTime() + seconds*1000)
return recoverDateFormat(date, dateComponent.format)
}
function yearSpan(var1, var2) {
dateComponent1 = parseDateComponents(var1);
dateComponent2 = parseDateComponents(var2);
if(dateComponent1==null || dateComponent2==null
|| dateComponent1.format!=dateComponent2.format || !dateComponent1.format.includes('yyyy'))
return "null(日期格式不一致或不支持运算)";
date1 = new Date(dateComponent1.year, dateComponent1.month-1, dateComponent1.day, dateComponent1.hour, dateComponent1.minute, dateComponent1.second)
date2 = new Date(dateComponent2.year, dateComponent2.month-1, dateComponent2.day, dateComponent2.hour, dateComponent2.minute, dateComponent2.second)
if(date1 > date2) { [date1, date2] = [date2, date1] }
yearDiff = date2.getFullYear() - date1.getFullYear();
date1.setFullYear(date2.getFullYear());
return date2 < date1 ? yearDiff-1 : yearDiff;
}
function monthSpan(var1, var2){
dateComponent1 = parseDateComponents(var1);
dateComponent2 = parseDateComponents(var2);
if(dateComponent1==null || dateComponent2==null
|| dateComponent1.format!=dateComponent2.format || !dateComponent1.format.includes('MM'))
return "null(日期格式不一致或不支持运算)";
date1 = new Date(dateComponent1.year, dateComponent1.month-1, dateComponent1.day, dateComponent1.hour, dateComponent1.minute, dateComponent1.second)
date2 = new Date(dateComponent2.year, dateComponent2.month-1, dateComponent2.day, dateComponent2.hour, dateComponent2.minute, dateComponent2.second)
if(date1 > date2) { [date1, date2] = [date2, date1] }
let monthDiff = (date2.getFullYear() - date1.getFullYear()) * 12
+ (date2.getMonth() - date1.getMonth());
date1.setMonth(date1.getMonth() + monthDiff)
return date2 < date1 ? --monthDiff : monthDiff;
}
function daySpan(var1, var2){
dateComponent1 = parseDateComponents(var1);
dateComponent2 = parseDateComponents(var2);
if(dateComponent1==null || dateComponent2==null
|| dateComponent1.format!=dateComponent2.format || !dateComponent1.format.includes('dd'))
return "null(日期格式不一致或不支持运算)";
date1 = new Date(dateComponent1.year, dateComponent1.month-1, dateComponent1.day, dateComponent1.hour, dateComponent1.minute, dateComponent1.second)
date2 = new Date(dateComponent2.year, dateComponent2.month-1, dateComponent2.day, dateComponent2.hour, dateComponent2.minute, dateComponent2.second)
if(date1 > date2) { [date1, date2] = [date2, date1] }
return Math.floor((date2 - date1)/(1000*60*60*24));
}
function minuteSpan(var1, var2){
dateComponent1 = parseDateComponents(var1);
dateComponent2 = parseDateComponents(var2);
if(dateComponent1==null || dateComponent2==null
|| dateComponent1.format!=dateComponent2.format || !dateComponent1.format.includes('mm'))
return "null(日期格式不一致或不支持运算)";
date1 = new Date(dateComponent1.year, dateComponent1.month-1, dateComponent1.day, dateComponent1.hour, dateComponent1.minute, dateComponent1.second)
date2 = new Date(dateComponent2.year, dateComponent2.month-1, dateComponent2.day, dateComponent2.hour, dateComponent2.minute, dateComponent2.second)
if(date1 > date2) { [date1, date2] = [date2, date1] }
return Math.floor((date2 - date1)/(1000*60));
}
function compareTime(var1, var2) {
const validFormat = [
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mm",
"yyyy-MM-dd HH",
"yyyy-MM-dd",
"yyyy-MM",
"yyyy",
"HH:mm:ss",
"HH:mm"
];
if( emptyVar(var1) && emptyVar(var2) ) return 0;
if( emptyVar(var1) || emptyVar(var2) ) throw "某个日期为空";
dateComponent1 = parseDateComponents(var1);
dateComponent2 = parseDateComponents(var2);
if(!validFormat.includes(dateComponent1.format) || !validFormat.includes(dateComponent2.format))
throw "不支持的格式";
date1 = new Date(dateComponent1.year, dateComponent1.month-1, dateComponent1.day, dateComponent1.hour, dateComponent1.minute, dateComponent1.second)
date2 = new Date(dateComponent2.year, dateComponent2.month-1, dateComponent2.day, dateComponent2.hour, dateComponent2.minute, dateComponent2.second)
let shortFormat = getShortFormat(dateComponent1.format, dateComponent2.format);
if(dateComponent1.format == dateComponent2.format){
return equalFormatCompare(date1, date2, dateComponent1.format)
}else if(shortFormat != null){
let result = equalFormatCompare(date1, date2, shortFormat);
if(result != 0)
return result;
else
throw "格式不一致时,不可得出相等";
}else{
throw "不可比较";
}
}
function textDateTime(dateStr1, dateStr2, format1, format2) {
const monthAbbr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
function parseDate(str, format) {
const patterns = {
'yyyy': { regex: /^(\d{4})$/, parts: ['year'] },
'MM': { regex: /^(\d{2})$/, parts: ['month'] },
'MMM': { regex: /^([A-Za-z]{3})$/, parts: ['monthAbbr'] },
'dd': { regex: /^(\d{2})$/, parts: ['day'] },
'yyyy-MM-dd': { regex: /^(\d{4})-(\d{2})-(\d{2})$/, parts: ['year', 'month', 'day'] },
'MM-dd': { regex: /^(\d{2})-(\d{2})$/, parts: ['month', 'day'] },
'dd-MMM-yyyy': { regex: /^(\d{2})-([A-Za-z]{3})-(\d{4})$/, parts: ['day', 'monthAbbr', 'year'] },
'dd-MMM': { regex: /^(\d{2})-([A-Za-z]{3})$/, parts: ['day', 'monthAbbr'] },
'MMM-yyyy': { regex: /^([A-Za-z]{3})-(\d{4})$/, parts: ['monthAbbr', 'year'] },
'yyyy-MM': { regex: /^(\d{4})-(\d{2})$/, parts: ['year', 'month'] },
'yyyy-MM-dd HH:mm': { regex: /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})$/, parts: ['year', 'month', 'day', 'hour', 'minute'] },
'yyyy-MM-dd HH': { regex: /^(\d{4})-(\d{2})-(\d{2}) (\d{2})$/, parts: ['year', 'month', 'day', 'hour'] },
'HH': { regex: /^(\d{2})$/, parts: ['hour'] },
'mm': { regex: /^(\d{2})$/, parts: ['minute'] },
'ss': { regex: /^(\d{2})$/, parts: ['second'] },
'HH:mm': { regex: /^(\d{2}):(\d{2})$/, parts: ['hour', 'minute'] },
'HH:mm:ss': { regex: /^(\d{2}):(\d{2}):(\d{2})$/, parts: ['hour', 'minute', 'second'] },
'mm:ss': { regex: /^(\d{2}):(\d{2})$/, parts: ['minute', 'second'] },
'dd-MMM-yyyy HH:mm': { regex: /^(\d{2})-([A-Za-z]{3})-(\d{4}) (\d{2}):(\d{2})$/, parts: ['day', 'monthAbbr', 'year', 'hour', 'minute'] },
'dd-MMM-yyyy HH': { regex: /^(\d{2})-([A-Za-z]{3})-(\d{4}) (\d{2})$/, parts: ['day', 'monthAbbr', 'year', 'hour'] }
};
const { regex, parts } = patterns[format];
const match = str.match(regex);
if (!match) throw new Error('Invalid format');
const result = {};
parts.forEach((part, index) => {
const value = match[index + 1];
switch(part) {
case 'year':
result.year = parseInt(value);
break;
case 'month':
result.month = parseInt(value) - 1;
break;
case 'monthAbbr':
result.month = monthAbbr.findIndex(m => m === value);
if (result.month === -1) throw new Error('Invalid month');
break;
case 'day':
result.day = parseInt(value);
break;
case 'hour':
result.hour = parseInt(value);
break;
case 'minute':
result.minute = parseInt(value);
break;
case 'second':
result.second = parseInt(value);
break;
}
});
if (result.month !== undefined && (result.month < 0 || result.month > 11)) throw new Error('Invalid month');
if (result.day !== undefined && (result.day < 1 || result.day > 31)) throw new Error('Invalid day');
if (result.hour !== undefined && (result.hour < 0 || result.hour > 23)) throw new Error('Invalid hour');
if (result.minute !== undefined && (result.minute < 0 || result.minute > 59)) throw new Error('Invalid minute');
if (result.second !== undefined && (result.second < 0 || result.second > 59)) throw new Error('Invalid second');
return result;
}
const date1 = parseDate(dateStr1, format1);
const date2 = parseDate(dateStr2, format2);
const merged = { ...date1, ...date2 };
const finalDate = new Date(
merged.year,
merged.month,
merged.day || 1,
merged.hour || 0,
merged.minute || 0,
merged.second || 0
);
if (isNaN(finalDate)) throw new Error('Invalid combined date');
if (finalDate.getDate() !== (merged.day || 1)) throw new Error('Invalid day');
if (merged.year !== undefined && finalDate.getFullYear() !== merged.year) throw new Error('Invalid year');
if (merged.month !== undefined && finalDate.getMonth() !== merged.month) throw new Error('Invalid month');
return `${finalDate.getFullYear()}-${String(finalDate.getMonth() + 1).padStart(2, '0')}-${String(finalDate.getDate()).padStart(2, '0')} ` +
`${String(finalDate.getHours()).padStart(2, '0')}:${String(finalDate.getMinutes()).padStart(2, '0')}:${String(finalDate.getSeconds()).padStart(2, '0')}`;
}
function formatDate(var1, format) {
const isValidFormats = [
'yyyy',
'yyyy-MM',
'yyyy-MM-dd',
'dd-MMM-yyyy',
'yyyy-MM-dd HH',
'dd-MMM-yyyy HH',
'yyyy-MM-dd HH:mm',
'dd-MMM-yyyy HH:mm',
'HH:mm',
'HH:mm:ss'
];
dateComponent = parseDateComponents(var1);
if(dateComponent==null || !isValidFormats.includes(format) || !dateComponent.format.includes(format))
return null;
date = new Date(dateComponent.year, dateComponent.month-1, dateComponent.day, dateComponent.hour, dateComponent.minute, dateComponent.second)
return recoverDateFormat(date, format)
}
function parseDateComponents(dateStr) {
let result = { format: null, year: null, month: null, day: null, hour: null, minute: null, second: null};
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const patterns = [
{ regex: /^(\d{2})-([A-Za-z]{3})-(\d{4})$/, format: "dd-MMM-yyyy" },
{ regex: /^(\d{2})-([A-Za-z]{3})-(\d{4}) (\d{2})$/, format: "dd-MMM-yyyy HH" },
{ regex: /^(\d{2})-([A-Za-z]{3})-(\d{4}) (\d{2}):(\d{2})$/, format: "dd-MMM-yyyy HH:mm" },
{ regex: /^(\d{2})-([A-Za-z]{3})-(\d{4}) (\d{2}):(\d{2}):(\d{2})$/, format: "dd-MMM-yyyy HH:mm:ss" },
{ regex: /^([A-Za-z]{3})-(\d{4})$/, format: "MMM-yyyy" },
{ regex: /^(\d{4})-(\d{2})-(\d{2})$/, format: "yyyy-MM-dd" },
{ regex: /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})$/, format: "yyyy-MM-dd HH:mm" },
{ regex: /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/, format: "yyyy-MM-dd HH:mm:ss" },
{ regex: /^(\d{4})-(\d{2})$/, format: "yyyy-MM" },
{ regex: /^(\d{4})$/, format: "yyyy" },
{ regex: /^(\d{2}):(\d{2}):(\d{2})$/, format: "HH:mm:ss" },
{ regex: /^(\d{2}):(\d{2})$/, format: "HH:mm" },
{ regex: /^(\d{2})$/, format: "HH" }
];
for (let pattern of patterns) {
let match = dateStr.match(pattern.regex);
if (match) {
switch (pattern.format) {
case "dd-MMM-yyyy":
result = {format: pattern.format, year: +match[3], month: monthNames.indexOf(match[2])+1, day: +match[1], hour: null, minute: null, second: null };
break;
case "dd-MMM-yyyy HH":
result = {format: pattern.format, year: +match[3], month: monthNames.indexOf(match[2])+1, day: +match[1], hour: +match[4], minute: null, second: null };
break;
case "dd-MMM-yyyy HH:mm":
result = {format: pattern.format, year: +match[3], month: monthNames.indexOf(match[2])+1, day: +match[1], hour: +match[4], minute: +match[5], second: null };
break;
case "dd-MMM-yyyy HH:mm:ss":
result = {format: pattern.format, year: +match[3], month: monthNames.indexOf(match[2])+1, day: +match[1], hour: +match[4], minute: +match[5], second: +match[6] };
break;
case "MMM-yyyy":
result = {format: pattern.format, year: +match[2], month: monthNames.indexOf(match[1])+1, day: 1, hour: null, minute: null, second: null };
break;
case "yyyy-MM-dd":
result = {format: pattern.format, year: +match[1], month: +match[2], day: +match[3], hour: null, minute: null, second: null };
break;
case "yyyy-MM-dd HH:mm":
result = {format: pattern.format, year: +match[1], month: +match[2], day: +match[3], hour: +match[4], minute: +match[5], second: null };
break;
case "yyyy-MM-dd HH:mm:ss":
result = {format: pattern.format, year: +match[1], month: +match[2], day: +match[3], hour: +match[4], minute: +match[5], second: +match[6] };
break;
case "yyyy-MM":
result = {format: pattern.format, year: +match[1], month: +match[2], day: 1, hour: null, minute: null, second: null };
break;
case "yyyy":
result = {format: pattern.format, year: +match[1], month: 1, day: 1, hour: null, minute: null, second: null };
break;
case "HH:mm:ss":
result = {format: pattern.format, year: null, month: null, day: null, hour: +match[1], minute: +match[2], second: +match[3] };
break;
case "HH:mm":
result = {format: pattern.format, year: null, month: null, day: null, hour: +match[1], minute: +match[2], second: null };
break;
case "HH":
result = {format: pattern.format, year: null, month: null, day: null, hour: +match[1], minute: null, second: null };
break;
}
return result;
}
}
return null;;
}
function recoverDateFormat(date, formatString) {
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const pad = (n) => n.toString().padStart(2, '0');
const year = date.getFullYear();
const month = date.getMonth();
const day = date.getDate();
const hours = date.getHours();
const minutes = date.getMinutes();
const seconds = date.getSeconds();
const monthStr = months[month];
const replacements = {
'yyyy': year,
'MMM': monthStr,
'MM': pad(month + 1),
'dd': pad(day),
'HH': pad(hours),
'mm': pad(minutes),
'ss': pad(seconds)
};
let result = formatString;
result = result.replace(/yyyy/g, replacements['yyyy']);
result = result.replace(/MMM/g, replacements['MMM']);
result = result.replace(/MM/g, replacements['MM']);
result = result.replace(/dd/g, replacements['dd']);
result = result.replace(/HH/g, replacements['HH']);
result = result.replace(/mm/g, replacements['mm']);
result = result.replace(/ss/g, replacements['ss']);
return result;
}
function emptyVar(value) {
return (
value == null ||
(typeof value === "string" && value.trim() === "")
);
}
function getShortFormat(format1, format2){
if(format1.includes(format2))
return format2;
else if(format2.includes(format1))
return format1;
else
return null;
}
function equalFormatCompare(date1, date2, formatStr){
const normalizeDate = (date, formatStr) => {
let year = formatStr.includes('yyyy') ? date.getFullYear() : undefined;
let month = formatStr.includes('MM') ? date.getMonth() : undefined;
let day = formatStr.includes('dd') ? date.getDate() : undefined;
let hour = formatStr.includes('HH') ? date.getHours() : undefined;
let minute = formatStr.includes('mm') ? date.getMinutes() : undefined;
let second = formatStr.includes('ss') ? date.getSeconds() : undefined;
return new Date(year||1970, month||0, day||1, hour||0, minute||0, second||0);
}
const normalizeDate1 = normalizeDate(date1, formatStr);
const normalizeDate2 = normalizeDate(date2, formatStr);
if(normalizeDate1 < normalizeDate2 )
return 1;
else if(normalizeDate1 > normalizeDate2)
return -1;
else
return 0;
}
console.log(addYear('2024-04-01 20:30:21', 1));
console.log(addYear('20-Dec-2024', 1));
console.log(addYear('2024 20:30:21', 1));
console.log(addMonth('2024 00:00:00',2));
console.log(addMonth('20-Dec-2024 00:00:00',2));
console.log(addDay('2024-02-20 00:00:00',12));
console.log(addDay('01-Oct-2021 00:00:10',12));
console.log(addDay('2024-02',11));
console.log(addHour('2024-02-01 20:40:00','1.2'));
console.log(addHour('2024-02-01 20:40:00',2));
console.log(addHour('01-Dec-2025 20:40:00',2));
console.log(addHour('2025 20:40:00',2));
console.log(addHour('20:40:00',5.5));
console.log(addMinutes('20:40:00',5.5));
console.log(addMinutes('2024-02-29 23:40:00',20.5));
console.log(addMinutes('2024 23:40:00',20.5));
console.log(addMinutes('2024-02-29 23:40:00','37'));
console.log(addSeconds('2024-02-29 23:40:00',20));
console.log(addSeconds('2024-02-29 23:40:00',20.5));
console.log(addSeconds('2024-02-29 23:40:00','20.5'));
console.log(addSeconds('2024 23:40:00','20.5'));
console.log(yearSpan('2024/02/29 23:40:00','2024-02-01 00:00:00'));
console.log(yearSpan('2024-02-28 01:00:00','2025-02-28 01:02:20'));
console.log(yearSpan('28-Oct-2024 01:02:20','01-Dec-2025 01:00:00'));
console.log(yearSpan('01:00:00','01:02:20'));
console.log(monthSpan('2024-02-29','2025-02-28'));
console.log(monthSpan('2025-02-28','2025-06-01'));
console.log(monthSpan('2025-28 09:00:00','2020-01 00:00:00'));
console.log(monthSpan('Oct-2024','Dec-2024'));
console.log(daySpan('2025-02-28','2025-06-01'));
console.log(daySpan('2025-02','2025-06'));
console.log(daySpan('01-Oct-2025','01-Dec-2025'));
console.log(daySpan('2025-01-28 20:00:00','2025-01-29 10:00:00'));
console.log(minuteSpan('2025-02-28 20:00:00','2025-02-28 10:00:01'));
console.log(minuteSpan('2025-02-28 20','2025-02-28 10'));
console.log(minuteSpan('01-Dec-2024 20:00:00','01-Dec-2024 20:10:12'));
console.log(compareTime('2025-02-28 20:00:00','2025-02-28 20:00:00'));
console.log(compareTime('2025-05-01 20:00:00','2025-02-28 20:00:00'));
console.log(compareTime('2025-01-28 20:00:00','2025-03-28'));
console.log(formatDate("2024-02-01 20:00:00", "yyyy-MM-dd HH:mm"));
console.log(formatDate("01-Dec-2024 20:00:00", "dd-MMM-yyyy"));
console.log(formatDate("2024-02-01 20:00:00", "dd-MMM-yyyy HH:mm"));
console.log(formatDate("2024-02-01 20:00:00", "HH:mm:ss"));