Release v2.6.19
This commit is contained in:
@@ -75,36 +75,148 @@
|
||||
return text;
|
||||
}
|
||||
|
||||
function formatDateValue(value, pattern) {
|
||||
var date = value instanceof Date ? value : new Date(value);
|
||||
function getDefaultTimeZone() {
|
||||
try {
|
||||
return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
||||
} catch (_error) {
|
||||
return 'UTC';
|
||||
}
|
||||
}
|
||||
|
||||
function getDateValue(value) {
|
||||
return value instanceof Date ? value : new Date(value);
|
||||
}
|
||||
|
||||
function resolveTimeZone(value) {
|
||||
var raw = String(value || '').trim();
|
||||
if (!raw) {
|
||||
return getDefaultTimeZone();
|
||||
}
|
||||
|
||||
try {
|
||||
new Intl.DateTimeFormat('en-GB', { timeZone: raw }).format(new Date());
|
||||
return raw;
|
||||
} catch (_error) {
|
||||
return getDefaultTimeZone();
|
||||
}
|
||||
}
|
||||
|
||||
function getDatePartsFromLocalTime(date) {
|
||||
var dayPeriod = date.getHours() >= 12 ? 'PM' : 'AM';
|
||||
return {
|
||||
year: String(date.getFullYear()),
|
||||
month: padNumber(date.getMonth() + 1, 2),
|
||||
day: padNumber(date.getDate(), 2),
|
||||
hour24: padNumber(date.getHours(), 2),
|
||||
hour12: padNumber(date.getHours() % 12 || 12, 2),
|
||||
minute: padNumber(date.getMinutes(), 2),
|
||||
second: padNumber(date.getSeconds(), 2),
|
||||
weekdayLong: dayNamesLong[date.getDay()],
|
||||
weekdayShort: dayNamesShort[date.getDay()],
|
||||
monthLong: monthNamesLong[date.getMonth()],
|
||||
monthShort: monthNamesShort[date.getMonth()],
|
||||
dayPeriod: dayPeriod
|
||||
};
|
||||
}
|
||||
|
||||
function getDatePartsFromTimeZone(date, timeZone) {
|
||||
var resolvedTimeZone = resolveTimeZone(timeZone);
|
||||
var baseFormatter = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: resolvedTimeZone,
|
||||
hour12: false,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
});
|
||||
var weekdayLongFormatter = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: resolvedTimeZone,
|
||||
weekday: 'long'
|
||||
});
|
||||
var weekdayShortFormatter = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: resolvedTimeZone,
|
||||
weekday: 'short'
|
||||
});
|
||||
var monthLongFormatter = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: resolvedTimeZone,
|
||||
month: 'long'
|
||||
});
|
||||
var monthShortFormatter = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: resolvedTimeZone,
|
||||
month: 'short'
|
||||
});
|
||||
var ampmFormatter = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: resolvedTimeZone,
|
||||
hour12: true,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
var numericParts = baseFormatter.formatToParts(date);
|
||||
var weekdayLong = weekdayLongFormatter.formatToParts(date);
|
||||
var weekdayShort = weekdayShortFormatter.formatToParts(date);
|
||||
var monthLong = monthLongFormatter.formatToParts(date);
|
||||
var monthShort = monthShortFormatter.formatToParts(date);
|
||||
var ampm = ampmFormatter.formatToParts(date);
|
||||
|
||||
function getPart(parts, type) {
|
||||
var match = parts.find(function (part) {
|
||||
return part && part.type === type;
|
||||
});
|
||||
return match ? String(match.value || '') : '';
|
||||
}
|
||||
|
||||
var dayPeriod = getPart(ampm, 'dayPeriod');
|
||||
|
||||
return {
|
||||
year: getPart(numericParts, 'year'),
|
||||
month: getPart(numericParts, 'month'),
|
||||
day: getPart(numericParts, 'day'),
|
||||
hour24: getPart(numericParts, 'hour'),
|
||||
hour12: getPart(ampm, 'hour'),
|
||||
minute: getPart(numericParts, 'minute'),
|
||||
second: getPart(numericParts, 'second'),
|
||||
weekdayLong: getPart(weekdayLong, 'weekday'),
|
||||
weekdayShort: getPart(weekdayShort, 'weekday'),
|
||||
monthLong: getPart(monthLong, 'month'),
|
||||
monthShort: getPart(monthShort, 'month'),
|
||||
dayPeriod: String(dayPeriod || '').toUpperCase(),
|
||||
timeZone: resolvedTimeZone
|
||||
};
|
||||
}
|
||||
|
||||
function formatDateValue(value, pattern, timeZone) {
|
||||
var date = getDateValue(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var format = String(pattern || 'YYYY-MM-DD HH:mm').trim() || 'YYYY-MM-DD HH:mm';
|
||||
var hours24 = date.getHours();
|
||||
var hours12 = hours24 % 12 || 12;
|
||||
var parts = timeZone ? getDatePartsFromTimeZone(date, timeZone) : getDatePartsFromLocalTime(date);
|
||||
var hours24 = parts.hour24;
|
||||
var hours12 = parts.hour12;
|
||||
var tokenMap = {
|
||||
YYYY: String(date.getFullYear()),
|
||||
YY: String(date.getFullYear()).slice(-2),
|
||||
MMMM: monthNamesLong[date.getMonth()],
|
||||
MMM: monthNamesShort[date.getMonth()],
|
||||
MM: padNumber(date.getMonth() + 1, 2),
|
||||
M: String(date.getMonth() + 1),
|
||||
DD: padNumber(date.getDate(), 2),
|
||||
D: String(date.getDate()),
|
||||
dddd: dayNamesLong[date.getDay()],
|
||||
ddd: dayNamesShort[date.getDay()],
|
||||
HH: padNumber(hours24, 2),
|
||||
H: String(hours24),
|
||||
hh: padNumber(hours12, 2),
|
||||
h: String(hours12),
|
||||
mm: padNumber(date.getMinutes(), 2),
|
||||
m: String(date.getMinutes()),
|
||||
ss: padNumber(date.getSeconds(), 2),
|
||||
s: String(date.getSeconds()),
|
||||
A: hours24 >= 12 ? 'PM' : 'AM',
|
||||
a: hours24 >= 12 ? 'pm' : 'am'
|
||||
YYYY: parts.year,
|
||||
YY: parts.year.slice(-2),
|
||||
MMMM: parts.monthLong,
|
||||
MMM: parts.monthShort,
|
||||
MM: parts.month,
|
||||
M: String(Number(parts.month) || 0),
|
||||
DD: parts.day,
|
||||
D: String(Number(parts.day) || 0),
|
||||
dddd: parts.weekdayLong,
|
||||
ddd: parts.weekdayShort,
|
||||
HH: hours24,
|
||||
H: String(Number(hours24) || 0),
|
||||
hh: hours12,
|
||||
h: String(Number(hours12) || 0),
|
||||
mm: parts.minute,
|
||||
m: String(Number(parts.minute) || 0),
|
||||
ss: parts.second,
|
||||
s: String(Number(parts.second) || 0),
|
||||
A: parts.dayPeriod,
|
||||
a: String(parts.dayPeriod || '').toLowerCase()
|
||||
};
|
||||
|
||||
return format.replace(/\[([^\]]+)\]|YYYY|YY|MMMM|MMM|MM|M|DD|D|dddd|ddd|HH|H|hh|h|mm|m|ss|s|A|a/g, function (match, literal) {
|
||||
@@ -112,7 +224,32 @@
|
||||
});
|
||||
}
|
||||
|
||||
function applyTransform(value, transform) {
|
||||
function getTimeZoneShortName(value, timeZone) {
|
||||
var date = getDateValue(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var resolvedTimeZone = resolveTimeZone(timeZone);
|
||||
try {
|
||||
var parts = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: resolvedTimeZone,
|
||||
timeZoneName: 'short'
|
||||
}).formatToParts(date);
|
||||
var match = parts.find(function (part) {
|
||||
return part && part.type === 'timeZoneName';
|
||||
});
|
||||
return match ? String(match.value || '') : resolvedTimeZone;
|
||||
} catch (_error) {
|
||||
return resolvedTimeZone;
|
||||
}
|
||||
}
|
||||
|
||||
function getTransformTimeZone(args, options) {
|
||||
return resolveTimeZone((args && args[0]) || (options && options.timeZone) || '');
|
||||
}
|
||||
|
||||
function applyTransform(value, transform, options) {
|
||||
var text = String(value === undefined || value === null ? '' : value);
|
||||
var name = String(transform && transform.name || '').trim().toLowerCase();
|
||||
var args = Array.isArray(transform && transform.args) ? transform.args : [];
|
||||
@@ -132,18 +269,26 @@
|
||||
}
|
||||
|
||||
if (name === 'format' || name === 'date' || name === 'datetime' || name === 'time') {
|
||||
return formatDateValue(value, args[0] || (name === 'time' ? 'h:mm A' : name === 'date' ? 'MMM D, YYYY' : 'MMM D, YYYY h:mm A'));
|
||||
return formatDateValue(value, args[0] || (name === 'time' ? 'h:mm A' : name === 'date' ? 'MMM D, YYYY' : 'MMM D, YYYY h:mm A'), getTransformTimeZone(args.slice(1), options));
|
||||
}
|
||||
|
||||
if (name === 'tz') {
|
||||
return getTransformTimeZone(args, options);
|
||||
}
|
||||
|
||||
if (name === 'tz_short') {
|
||||
return getTimeZoneShortName(value, getTransformTimeZone(args, options));
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
function resolvePlaceholderExpression(value, expression) {
|
||||
function resolvePlaceholderExpression(value, expression, options) {
|
||||
var parsed = parsePlaceholderExpression(expression);
|
||||
var resolved = resolvePath(value, parsed.path);
|
||||
|
||||
parsed.transforms.forEach(function (transform) {
|
||||
resolved = applyTransform(resolved, transform);
|
||||
resolved = applyTransform(resolved, transform, options || {});
|
||||
});
|
||||
|
||||
return resolved;
|
||||
|
||||
@@ -2,47 +2,79 @@
|
||||
|
||||
(function () {
|
||||
var root = window;
|
||||
var PLACEHOLDERS = [
|
||||
{ token: 'h', label: 'h' },
|
||||
{ token: 'hh', label: 'hh' },
|
||||
{ token: 'm', label: 'm' },
|
||||
{ token: 'mm', label: 'mm' },
|
||||
{ token: 's', label: 's' },
|
||||
{ token: 'ss', label: 'ss' },
|
||||
{ token: 'd', label: 'd' },
|
||||
{ token: 'dd', label: 'dd' },
|
||||
{ token: 'M', label: 'M' },
|
||||
{ token: 'MM', label: 'MM' },
|
||||
{ token: 'y', label: 'y' },
|
||||
{ token: 'yyyy', label: 'yyyy' },
|
||||
{ token: 'yy', label: 'yy' },
|
||||
{ token: 'ddd', label: 'ddd' },
|
||||
{ token: 'dddd', label: 'dddd' },
|
||||
{ token: 'MMM', label: 'MMM' },
|
||||
{ token: 'MMMM', label: 'MMMM' },
|
||||
{ token: 'a', label: 'a' },
|
||||
{ token: 'tz', label: 'tz' },
|
||||
{ token: 'tz_short', label: 'tz_short' }
|
||||
var FORMAT_PLACEHOLDERS = [
|
||||
{ token: 'h', output: '1-12', description: 'The hour, 12-hour clock' },
|
||||
{ token: 'hh', output: '01-12', description: 'The hour, 12-hour clock, 2-digits' },
|
||||
{ token: 'm', output: '0-59', description: 'The minute' },
|
||||
{ token: 'mm', output: '00-59', description: 'The minute, 2-digits' },
|
||||
{ token: 's', output: '0-59', description: 'The second' },
|
||||
{ token: 'ss', output: '00-59', description: 'The second, 2-digits' },
|
||||
{ token: 'A', output: 'AM/PM', description: 'Uppercase day period' },
|
||||
{ token: 'a', output: 'am/pm', description: 'Lowercase day period' },
|
||||
{ token: 'D', output: '1-31', description: 'The day of the month' },
|
||||
{ token: 'DD', output: '01-31', description: 'The day of the month, 2-digits' },
|
||||
{ token: 'ddd', output: 'Mon', description: 'The abbreviated weekday name' },
|
||||
{ token: 'dddd', output: 'Monday', description: 'The full weekday name' },
|
||||
{ token: 'M', output: '1-12', description: 'The month, beginning at 1' },
|
||||
{ token: 'MM', output: '01-12', description: 'The month, 2-digits' },
|
||||
{ token: 'MMM', output: 'Jan-Dec', description: 'The abbreviated month name' },
|
||||
{ token: 'MMMM', output: 'January-December', description: 'The full month name' },
|
||||
{ token: 'YY', output: '18', description: 'The two-digit year' },
|
||||
{ token: 'YYYY', output: '2018', description: 'The four-digit year' }
|
||||
];
|
||||
|
||||
var HELPER_PLACEHOLDERS = [
|
||||
{ token: 'tz', output: 'Europe/London', description: 'The resolved time zone name' },
|
||||
{ token: 'tz_short', output: 'BST/GMT', description: 'The time zone abbreviation for the selected date' }
|
||||
];
|
||||
|
||||
var PLACEHOLDERS = FORMAT_PLACEHOLDERS.concat(HELPER_PLACEHOLDERS);
|
||||
|
||||
function getTokens() {
|
||||
return PLACEHOLDERS.slice();
|
||||
}
|
||||
|
||||
function renderChips() {
|
||||
if (root.placeholderChips && typeof root.placeholderChips.renderChips === 'function') {
|
||||
return root.placeholderChips.renderChips(PLACEHOLDERS.map(function (item) {
|
||||
return item.token;
|
||||
}));
|
||||
}
|
||||
function getFormatTokens() {
|
||||
return FORMAT_PLACEHOLDERS.slice();
|
||||
}
|
||||
|
||||
return PLACEHOLDERS.map(function (item) {
|
||||
return '<span class="chip">{{' + item.token + '}}</span>';
|
||||
}).join('');
|
||||
function renderTable() {
|
||||
return '' +
|
||||
'<div class="table-responsive">' +
|
||||
'<table class="table table-sm align-middle mb-0">' +
|
||||
'<thead>' +
|
||||
'<tr>' +
|
||||
'<th scope="col">Format</th>' +
|
||||
'<th scope="col">Output</th>' +
|
||||
'<th scope="col">Description</th>' +
|
||||
'</tr>' +
|
||||
'</thead>' +
|
||||
'<tbody>' +
|
||||
FORMAT_PLACEHOLDERS.map(function (item) {
|
||||
return '' +
|
||||
'<tr>' +
|
||||
'<td><code>' + item.token + '</code></td>' +
|
||||
'<td>' + escapeHtml(item.output || '') + '</td>' +
|
||||
'<td>' + escapeHtml(item.description || '') + '</td>' +
|
||||
'</tr>';
|
||||
}).join('') +
|
||||
'</tbody>' +
|
||||
'</table>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value === undefined || value === null ? '' : value)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
root.timeDatePlaceholders = {
|
||||
getTokens: getTokens,
|
||||
renderChips: renderChips
|
||||
getFormatTokens: getFormatTokens,
|
||||
renderTable: renderTable
|
||||
};
|
||||
}());
|
||||
Reference in New Issue
Block a user