function isStandardFormat(varValue) {
const patterns = [
/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/,
/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/,
/^\d{4}-\d{2}-\d{2}$/,
/^\d{2}:\d{2}:\d{2}$/
];
return patterns.some(pattern => pattern.test(varValue));
}
function parseVarValue(varValue) {
if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(varValue)) {
return parseDateTime(varValue);
} else if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/.test(varValue)) {
return parseDateTimeHM(varValue);
} else if (/^\d{4}-\d{2}-\d{2}$/.test(varValue)) {
return parseDate(varValue);
} else if (/^\d{2}:\d{2}:\d{2}$/.test(varValue)) {
return parseTime(varValue);
}
return null;
}
function parseDateTime(varValue) {
const [datePart, timePart] = varValue.split(' ');
const date = parseDatePart(datePart);
if (!date) return null;
const time = parseTimePart(timePart, true);
if (!time) return null;
date.setHours(time.hours, time.minutes, time.seconds);
return date;
}
function parseDateTimeHM(varValue) {
const [datePart, timePart] = varValue.split(' ');
const date = parseDatePart(datePart);
if (!date) return null;
const time = parseTimePart(timePart, false);
if (!time) return null;
date.setHours(time.hours, time.minutes, 0);
return date;
}
function parseDatePart(datePart) {
const [yearStr, monthStr, dayStr] = datePart.split('-');
const year = parseInt(yearStr, 10);
const month = parseInt(monthStr, 10) - 1;
const day = parseInt(dayStr, 10);
if (month < 0 || month > 11) return null;
const date = new Date(year, month, day);
if (date.getFullYear() !== year || date.getMonth() !== month || date.getDate() !== day) {
return null;
}
return date;
}
function parseTimePart(timePart, includeSeconds) {
const parts = timePart.split(':');
if (includeSeconds && parts.length !== 3) return null;
if (!includeSeconds && parts.length !== 2) return null;
const hours = parseInt(parts[0], 10);
const minutes = parseInt(parts[1], 10);
const seconds = includeSeconds ? parseInt(parts[2], 10) : 0;
if (hours < 0 || hours >= 24) return null;
if (minutes < 0 || minutes >= 60) return null;
if (includeSeconds && (seconds < 0 || seconds >= 60)) return null;
return { hours, minutes, seconds };
}
function parseDate(varValue) {
const date = parseDatePart(varValue);
if (!date) return null;
date.setHours(0, 0, 0);
return date;
}
function parseTime(varValue) {
const time = parseTimePart(varValue, true);
if (!time) return null;
const now = new Date();
const date = new Date(now.getFullYear(), now.getMonth(), now.getDate(), time.hours, time.minutes, time.seconds);
return date;
}
function formatDate(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 format(varValue, formatString) {
if (typeof varValue === 'undefined' || varValue === null) {
return '';
}
if (/^\d+$/.test(formatString)) {
if (typeof varValue !== 'number' || isNaN(varValue)) {
return null;
}
var sign = varValue < 0 ? -1 : 1;
varValue = Math.abs(varValue);
var integerPart = Math.trunc(varValue);
var integerPartStr = integerPart.toString();
var resultStr = integerPartStr.length <= formatString ? integerPartStr : integerPartStr.substring(0, formatString);
var resultInt = parseInt(resultStr, 10) * sign;
return isFinite(resultInt) ? resultInt : null;
}
if (/^\d+\.\d+$/.test(formatString)) {
if (typeof varValue !== 'number' || isNaN(varValue)) {
return null;
}
const [integerLengthStr, decimalPlacesStr] = formatString.split('.');
const integerLength = parseInt(integerLengthStr, 10);
const decimalPlaces = parseInt(decimalPlacesStr, 10);
if (isNaN(integerLength) || isNaN(decimalPlaces) || integerLength <= 0 || decimalPlaces < 0) {
return '';
}
let var1Str = varValue.toFixed(decimalPlaces);
var1Str = var1Str.replace(/(\.\d*[1-9])\d*0+|\.\d+0+$/g, '$1').replace(/\.$/, '');
let absoluteVar1Str = var1Str.replace(/^-/, '').replace(/^\+/, '');
let [integerPart, decimalPart] = absoluteVar1Str.split('.');
let formattedDecimalPart = '';
if (decimalPart && decimalPlaces > 0) {
formattedDecimalPart = decimalPart.slice(0, decimalPlaces);
formattedDecimalPart = formattedDecimalPart.replace(/\.?0+$/, '');
if (formattedDecimalPart === '' && decimalPlaces > 0) {
formattedDecimalPart = '0';
}
}
let slicedIntegerPart = integerPart.slice(0, integerLength);
let result = slicedIntegerPart;
if (formattedDecimalPart) {
result += '.' + formattedDecimalPart;
}
result = (varValue >= 0 ? '' : '-') + result;
return result;
}
if (/^\$\d+(\.\d+)?$/.test(formatString)) {
const lengthMatch = formatString.match(/^\$(\d+)/);
if (!lengthMatch) {
throw new Error('Invalid format string. It should start with "$" followed by a number.');
}
const maxLength = parseInt(lengthMatch[1], 10);
let valueStr = varValue.toString();
if (valueStr.length <= maxLength) {
return valueStr;
}
return valueStr.slice(0, maxLength);
}
const allowedFormats = [
'yyyy-MM-dd',
'dd-MMM-yyyy',
'yyyy-MM-dd HH:mm',
'yyyy-MM-dd HH:mm:ss',
'dd-MMM-yyyy HH:mm',
'dd-MMM-yyyy HH:mm:ss',
'HH:mm:ss',
'HH:mm',
'yyyy-MM',
'MMM-yyyy',
'yyyy-MM-dd HH',
'dd-MMM-yyyy HH',
'HH'
];
if (!allowedFormats.includes(formatString)) {
return null;
}
if (typeof varValue !== 'string' || !isStandardFormat(varValue)) {
return null;
}
const date = parseVarValue(varValue);
if (!date || isNaN(date.getTime())) {
return null;
}
return formatDate(date, formatString);
}
console.log(format(21.2, 2));
console.log(format(-12345.67, 3));
console.log(format(123.456, 8));
console.log(format("abc", 5));
console.log(format(12345678901234567890, 5));
console.log(format('2017-09-11', 'yyyy-dd'));