Skip to content

Instantly share code, notes, and snippets.

@marlun78
Last active March 3, 2023 08:09
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save marlun78/1351171 to your computer and use it in GitHub Desktop.
Save marlun78/1351171 to your computer and use it in GitHub Desktop.
A JavaScript date format inspired by the .NET framework
// Date Format function
//
// Format options inspired by the .NET framework's format.
// http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
//
// Non-formatting characters within the format string must be
// quoted (single (') or double (") quotes)! The same is true
// for two format specifiers that should apear together. Eg.
// if you want the date to be output with the date ordinal
// (9th), the format string must be "d''x" (or 'd""x').
//
// Copyright (c) Martin Lundgren, 2011
//
// Arguments:
// format {String} The format pattern to display the date in. See Format Patterns section below for options.
// settings {Object} Formatting settings.
//
// Settings:
// asUtc {Boolean} If the formatted date is to be returned as a UTC date.
// days {Array} The days of the week. Starting with Sunday.
// daysAbbr {Array} The days of the week, abbreviated. Starting with Sunday.
// designator {Array} Time designator. Starting with AM.
// format {String} The format pattern to format the date in.
// months {Array} The name of the months. Starting with January.
// monthsAbbr {Array} The name of the months, abbreviated. Starting with January.
//
// Format Patterns:
// d 1-31 The day of the month
// dd 01-31 The day of the month
// ddd Mon-Sun The abbreviated name of the day of the week
// dddd Monday-Sunday The full name of the day of the week
// f 6 The tenths of a second in a date and time value. The remaining digits are truncated.
// ff 61 The hundredths of a second in a date and time value. The remaining digits are truncated.
// fff 617 The milliseconds in a date and time value. The remaining digits are truncated.
// ffff 6170 The milliseconds in a date and time value, with a trailing zero. The remaining digits are truncated.
// fffff 61700 The milliseconds in a date and time value, with two trailing zeros. The remaining digits are truncated.
// ffffff 617000 The milliseconds in a date and time value, with three trailing zeros. The remaining digits are truncated.
// F 6 The tenths of a second in a date and time value. Trailing zeros or zero values are not displayed.
// FF 61 The hundredths of a second in a date and time value. Trailing zeros or zero values are not displayed.
// FFF 617 The milliseconds in a date and time value. Trailing zeros or zero values are not displayed.
// FFFF 617 The milliseconds in a date and time value. Trailing zeros or zero values are not displayed.
// FFFFF 617 The milliseconds in a date and time value. Trailing zeros or zero values are not displayed.
// FFFFFF 617 The milliseconds in a date and time value. Trailing zeros or zero values are not displayed.
// h 1-12 The hour, using a 12-hour clock
// hh 01-12 The hour, using a 12-hour clock
// H 0-23 The hour, using a 24-hour clock
// HH 00-23 The hour, using a 24-hour clock
// m 0-59 The minute
// mm 00-59 The minute
// M 1-12 The month
// MM 01-12 The month
// MMM Jan-Dec The abbreviated name of the month
// MMMM January-December The full name of the month
// s 0-59 The second
// ss 00-59 The second
// tt AM/PM The AM/PM designator
// x st, nd, rd, th The ordinal suffix of a number (NOTE! This does not exist in .NET!)
// y 0-99 The year
// yy 00-99 The year
// yyy 001-9999 The year, with a minimum of three digits
// yyyy 0001-9999 The year as a four-digit number
// z +1 Hours offset from UTC, with no leading zeros.
// zz +01 Hours offset from UTC, with a leading zero for a single-digit value.
// zzz +01:00 Hours and minutes offset from UTC.
//
// Example:
// The formatting method can be called in the following three ways:
// fn(format, settings) {String} The format string passed is used, any settings are stored.
// If the settings object contain a format property, it will override the format string.
// fn(settings) {String} Settings are stored and the stored format is used.
// fn() {String} Default settings are used.
//
(function () {
'use strict';
var _asUtc = false,
_days = 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '),
_daysAbbr = 'Sun Mon Tue Wed Thu Fri Sat'.split(' '),
_designator = 'AM PM'.split(' '),
_format = 'MMMM d""x "at" h:mm tt',
_months = 'January February March April May June July August September October November December'.split(' '),
_monthsAbbr = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '),
// The formatting function
_toFormat = function () {
var _this = this, dateMethod, find, format, methods, settings, str;
// Evaluate arguments
if (typeof arguments[0] === 'string') {
format = arguments[0];
settings = arguments[1];
}
else {
format = null;
settings = arguments[0];
}
// Store any passed settings
if (settings) {
if (typeof settings.asUtc !== 'undefined') _asUtc = settings.asUtc;
if (settings.days) _days = settings.days;
if (settings.daysAbbr) _daysAbbr = settings.daysAbbr;
if (settings.designator) _designator = settings.designator;
if (settings.format) _format = settings.format;
if (settings.getDateOrdinal) _getDateOrdinal = settings.getDateOrdinal;
if (settings.months) _months = settings.months;
if (settings.monthsAbbr) _monthsAbbr = settings.monthsAbbr;
}
if (!format) {
format = _format;
}
dateMethod = function (method) {
return 'get' + (_asUtc ? 'UTC' : '') + method;
};
methods = {
d: function () { return this[dateMethod('Date')](); },
dd: function () { return _pad(this[dateMethod('Date')]()); },
ddd: function () { return _getDayName.call(this, true); },
dddd: function () { return _getDayName.call(this); },
f: function () { return _pad(_pad(this[dateMethod('Milliseconds')](), 3), 6, true).substr(0, 1); },
ff: function () { return _pad(_pad(this[dateMethod('Milliseconds')](), 3), 6, true).substr(0, 2); },
fff: function () { return _pad(_pad(this[dateMethod('Milliseconds')](), 3), 6, true).substr(0, 3); },
ffff: function () { return _pad(_pad(this[dateMethod('Milliseconds')](), 3), 6, true).substr(0, 4); },
fffff: function () { return _pad(_pad(this[dateMethod('Milliseconds')](), 3), 6, true).substr(0, 5); },
ffffff: function () { return _pad(_pad(this[dateMethod('Milliseconds')](), 3), 6, true).substr(0, 6); },
F: function () { var r = _pad(this[dateMethod('Milliseconds')](), 3).substr(0, 1); return r === '0' ? '' : r; },
FF: function () { var r = _pad(this[dateMethod('Milliseconds')](), 3).substr(0, 2); return r === '00' ? '' : r; },
FFF: function () { return _pad(this[dateMethod('Milliseconds')](), 3).substr(0, 3); },
FFFF: function () { return methods.FFF.call(this); },
FFFFF: function () { return methods.FFF.call(this); },
FFFFFF: function () { return methods.FFF.call(this); },
h: function () { var h = this[dateMethod('Hours')](); return h > 12 ? h - 12 : h; },
hh: function () { var h = this[dateMethod('Hours')](); return _pad(h > 12 ? h - 12 : h); },
m: function () { return this[dateMethod('Minutes')](); },
mm: function () { return _pad(this[dateMethod('Minutes')]()); },
H: function () { return this[dateMethod('Hours')](); },
HH: function () { return _pad(this[dateMethod('Hours')]()); },
M: function () { return this[dateMethod('Month')]() + 1; },
MM: function () { return _pad(this[dateMethod('Month')]() + 1); },
MMM: function () { return _getMonthName.call(this, true); },
MMMM: function () { return _getMonthName.call(this); },
s: function () { return this[dateMethod('Seconds')](); },
ss: function () { return _pad(this[dateMethod('Seconds')]()); },
tt: function () { return _getTimeDesignator.call(this); },
x: function () { return _getDateOrdinal.call(this); },
y: function () { var y = this[dateMethod('FullYear')](), s = y.toString(); return y < 10 ? y : s.substr(s.length - 2); },
yy: function () { return _pad(this[dateMethod('FullYear')](), 2); },
yyy: function () { var y = this[dateMethod('FullYear')](), s = y.toString(); return y < 1000 ? _pad(y, 3) : s.substr(s.length - 4); },
yyyy: function () { return _pad(this[dateMethod('FullYear')](), 4); },
yyyyy: function () { return _pad(this[dateMethod('FullYear')](), 5); },
yyyyyy: function () { return _pad(this[dateMethod('FullYear')](), 6); },
z: function () { var t = this.getTimezoneOffset(); return (t > 0 ? '-' : '+') + Math.abs(t / 60); },
zz: function () { var t = this.getTimezoneOffset(); return (t > 0 ? '-' : '+') + _pad(Math.abs(t / 60)); },
zzz: function () { var t = this.getTimezoneOffset(); return (t > 0 ? '-' : '+') + _pad(Math.abs(t / 60)) + ':' + _pad((Math.abs(t / 60) % 1) * 60); }
};
find = /([dfFhmHMstxyz]+)(?=([^"']*["'][^"']*["'])*[^"']*$)/g;
str = format.replace(find, function (match, group1) {
var fn = methods[group1];
return typeof fn === 'function' ? fn.call(_this) : match;
});
return str.replace(/["']/g, '');
},
_getDayName = function (asAbbr) {
var n = this.getDay();
return asAbbr ? _daysAbbr[n] : _days[n];
},
_getDateOrdinal = (function () {
var sf = ['th', 'st', 'nd', 'rd', 'th'];
return function () {
var d = this.getDate();
return (d > 3 && d < 21) ? 'th' : sf[Math.min(d % 10, 4)];
};
} ()),
_getMonthName = function (asAbbr) {
var n = this.getMonth();
return asAbbr ? _monthsAbbr[n] : _months[n];
},
_getTimeDesignator = function () {
return this.getHours() >= 12 ? _designator[1] : _designator[0];
},
_pad = function (o, l, r) {
if (r) {
return (o + '000000').slice(0, l ? Math.min(l, 6) : 2);
}
else {
return ('000000' + o).slice(-(l ? Math.min(l, 6) : 2));
}
};
// Expose the formatting method
// As a global function
//window.formatDate = function (date, format, options) {
// if(isNaN(+date) || !date.getDate) throw new Error('Not a valid date');
// return _toFormat.call(date, format, options);
//};
// Or as a method on the Date object
Date.prototype.format = function (format, options) {
return _toFormat.call(this, format, options);
};
} ());
@DevidCIC
Copy link

Nice work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment