Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit d846e2d

Browse files
committed
fix(dateparser): correctly format with literals
- Fix formatting of dates with literal usage Closes #6055 Fixes #5620 Fixes #5802
1 parent 409b7aa commit d846e2d

File tree

2 files changed

+91
-42
lines changed

2 files changed

+91
-42
lines changed

src/dateparser/dateparser.js

+70-21
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ angular.module('ui.bootstrap.dateparser', [])
234234

235235
this.init();
236236

237-
function createParser(format, func) {
237+
function createParser(format) {
238238
var map = [], regex = format.split('');
239239

240240
// check for literal values
@@ -283,7 +283,7 @@ angular.module('ui.bootstrap.dateparser', [])
283283
map.push({
284284
index: index,
285285
key: data.key,
286-
apply: data[func],
286+
apply: data.apply,
287287
matcher: data.regex
288288
});
289289
}
@@ -295,6 +295,70 @@ angular.module('ui.bootstrap.dateparser', [])
295295
};
296296
}
297297

298+
function createFormatter(format) {
299+
var formatters = [];
300+
var i = 0;
301+
var formatter, literalIdx;
302+
while (i < format.length) {
303+
if (angular.isNumber(literalIdx)) {
304+
if (format.charAt(i) === '\'') {
305+
if (i + 1 >= format.length || format.charAt(i + 1) !== '\'') {
306+
formatters.push(constructLiteralFormatter(format, literalIdx, i));
307+
literalIdx = null;
308+
}
309+
} else if (i === format.length) {
310+
while (literalIdx < format.length) {
311+
formatter = constructFormatterFromIdx(format, literalIdx);
312+
formatters.push(formatter);
313+
literalIdx = formatter.endIdx;
314+
}
315+
}
316+
317+
i++;
318+
continue;
319+
}
320+
321+
if (format.charAt(i) === '\'') {
322+
literalIdx = i;
323+
i++;
324+
continue;
325+
}
326+
327+
formatter = constructFormatterFromIdx(format, i);
328+
329+
formatters.push(formatter.parser);
330+
i = formatter.endIdx;
331+
}
332+
333+
return formatters;
334+
}
335+
336+
function constructLiteralFormatter(format, literalIdx, endIdx) {
337+
return function() {
338+
return format.substr(literalIdx + 1, endIdx - literalIdx - 1);
339+
};
340+
}
341+
342+
function constructFormatterFromIdx(format, i) {
343+
var currentPosStr = format.substr(i);
344+
for (var j = 0; j < formatCodeToRegex.length; j++) {
345+
if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) {
346+
var data = formatCodeToRegex[j];
347+
return {
348+
endIdx: i + data.key.length,
349+
parser: data.formatter
350+
};
351+
}
352+
}
353+
354+
return {
355+
endIdx: i + 1,
356+
parser: function() {
357+
return currentPosStr.charAt(0);
358+
}
359+
};
360+
}
361+
298362
this.filter = function(date, format) {
299363
if (!angular.isDate(date) || isNaN(date) || !format) {
300364
return '';
@@ -307,28 +371,13 @@ angular.module('ui.bootstrap.dateparser', [])
307371
}
308372

309373
if (!this.formatters[format]) {
310-
this.formatters[format] = createParser(format, 'formatter');
374+
this.formatters[format] = createFormatter(format);
311375
}
312376

313-
var parser = this.formatters[format],
314-
map = parser.map;
315-
316-
var _format = format;
317-
318-
return map.reduce(function(str, mapper, i) {
319-
var match = _format.match(new RegExp('(.*)' + mapper.key));
320-
if (match && angular.isString(match[1])) {
321-
str += match[1];
322-
_format = _format.replace(match[1] + mapper.key, '');
323-
}
324-
325-
var endStr = i === map.length - 1 ? _format : '';
326-
327-
if (mapper.apply) {
328-
return str + mapper.apply.call(null, date) + endStr;
329-
}
377+
var formatters = this.formatters[format];
330378

331-
return str + endStr;
379+
return formatters.reduce(function(str, formatter) {
380+
return str + formatter(date);
332381
}, '');
333382
};
334383

src/dateparser/test/dateparser.spec.js

+21-21
Original file line numberDiff line numberDiff line change
@@ -565,27 +565,27 @@ describe('date parser', function() {
565565
});
566566

567567
describe('with value literals', function() {
568-
// describe('filter', function() {
569-
// it('should work with multiple literals', function() {
570-
// expect(dateParser.filter(new Date(2013, 0, 29), 'd \'de\' MMMM \'de\' y')).toEqual('29 de January de 2013');
571-
// });
572-
//
573-
// it('should work with escaped single quote', function() {
574-
// expect(dateParser.filter(new Date(2015, 2, 22, 12), 'd.MMMM.yy h \'o\'\'clock\'')).toEqual('22.March.15 12 o\'clock');
575-
// });
576-
//
577-
// it('should work with only a single quote', function() {
578-
// expect(dateParser.filter(new Date(2015, 2, 22), 'd.MMMM.yy \'\'\'')).toEqual('22.March.15 \'');
579-
// });
580-
//
581-
// it('should work with trailing literal', function() {
582-
// expect(dateParser.filter(new Date(2013, 0, 1), '\'year\' y')).toEqual('year 2013');
583-
// });
584-
//
585-
// it('should work without whitespace', function() {
586-
// expect(dateParser.filter(new Date(2013, 0, 1), '\'year:\'y')).toEqual('year:2013');
587-
// });
588-
// });
568+
describe('filter', function() {
569+
it('should work with multiple literals', function() {
570+
expect(dateParser.filter(new Date(2013, 0, 29), 'd \'de\' MMMM \'de\' y')).toEqual('29 de January de 2013');
571+
});
572+
573+
it('should work with escaped single quote', function() {
574+
expect(dateParser.filter(new Date(2015, 2, 22, 12), 'd.MMMM.yy h \'o\'\'clock\'')).toEqual('22.March.15 12 o\'clock');
575+
});
576+
577+
it('should work with only a single quote', function() {
578+
expect(dateParser.filter(new Date(2015, 2, 22), 'd.MMMM.yy \'\'\'')).toEqual('22.March.15 \'');
579+
});
580+
581+
it('should work with trailing literal', function() {
582+
expect(dateParser.filter(new Date(2013, 0, 1), '\'year\' y')).toEqual('year 2013');
583+
});
584+
585+
it('should work without whitespace', function() {
586+
expect(dateParser.filter(new Date(2013, 0, 1), '\'year:\'y')).toEqual('year:2013');
587+
});
588+
});
589589

590590
describe('parse', function() {
591591
it('should work with multiple literals', function() {

0 commit comments

Comments
 (0)