First of all, your given sample features zero-padded 2-digit months and milliseconds which you currently don't reproduce.
The mentioned 'smell' is probably caused by
- the 'manual' zero-padding of the timezone offset and its many if-else branches
- the many hardcoded numbers and strings
- the long illegible string concatenation
We can get rid of the self-made zero-padding by using String.padStart() or - if compatibility is a concern - one of its many alternative implementations.
We can't really get rid of the many hardcoded constants, but we can name them to make them meaningful and less magic in appearance:
const seperators = ['/', '/', ' ', ':', ':', ':', ' ', '', '', ''];
We can then replace the large string concatenation expression by leveraging one of those array's reduce or map method:
function formatDate(date) {
const values = [
date.getMonth() + 1,
date.getDay(),
date.getFullYear(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds(),
date.getTimezoneOffset() > 0 ? '-' : '+',
Math.abs(date.getTimezoneOffset() / 60),
Math.abs(date.getTimezoneOffset() % 60)
];
const digits = [2, 2, 4, 2, 2, 2, 3, 0, 2, 2];
const seperators = ['/', '/', ' ', ':', ':', ':', ' ', '', '', ''];
return values.map((value, i) =>
value.toString().padStart(digits[i], '0') + seperators[i]
).join('');
}
console.log(formatDate(new Date()));
That's it. I don't see how we can leverage any other built-in method to shorten above task. Using JavaScript's built-in Date.toLocaleTimeString('en-US', options) gets us pretty far, but it is missing timezone offset and millisecond options and introduces unwanted separators:
const options = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
};
console.log(new Date().toLocaleString('en-US', options));