feat(common): Add ISO week-numbering year formats support to formatDate (#38828)

Add ISO 8601 week-numbering year formats ('r', 'rr', 'rrr', 'rrrr') support for formatDate function.

Issue:https://github.com/angular/angular/issues/38739

PR Close #38828
This commit is contained in:
Prashant Tholia 2020-09-12 20:21:49 +05:30 committed by Misko Hevery
parent 0c0c54d615
commit 984ed39195
3 changed files with 53 additions and 1 deletions

View File

@ -13,7 +13,7 @@ export const ISO8601_DATE_REGEX =
// 1 2 3 4 5 6 7 8 9 10 11 // 1 2 3 4 5 6 7 8 9 10 11
const NAMED_FORMATS: {[localeId: string]: {[format: string]: string}} = {}; const NAMED_FORMATS: {[localeId: string]: {[format: string]: string}} = {};
const DATE_FORMATS_SPLIT = const DATE_FORMATS_SPLIT =
/((?:[^GyMLwWdEabBhHmsSzZO']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/; /((?:[^GyrMLwWdEabBhHmsSzZO']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|r{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/;
enum ZoneWidth { enum ZoneWidth {
Short, Short,
@ -394,6 +394,18 @@ function weekGetter(size: number, monthBased = false): DateFormatter {
}; };
} }
/**
* Returns a date formatter that provides the week-numbering year for the input date.
*/
function weekNumberingYearGetter(size: number, trim = false): DateFormatter {
return function(date: Date, locale: string) {
const thisThurs = getThursdayThisWeek(date);
const weekNumberingYear = thisThurs.getFullYear();
return padNumber(
weekNumberingYear, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign), trim);
};
}
type DateFormatter = (date: Date, locale: string, offset: number) => string; type DateFormatter = (date: Date, locale: string, offset: number) => string;
const DATE_FORMATS: {[format: string]: DateFormatter} = {}; const DATE_FORMATS: {[format: string]: DateFormatter} = {};
@ -438,6 +450,25 @@ function getDateFormatter(format: string): DateFormatter|null {
formatter = dateGetter(DateType.FullYear, 4, 0, false, true); formatter = dateGetter(DateType.FullYear, 4, 0, false, true);
break; break;
// 1 digit representation of the week-numbering year, e.g. (AD 1 => 1, AD 199 => 199)
case 'r':
formatter = weekNumberingYearGetter(1);
break;
// 2 digit representation of the week-numbering year, padded (00-99). (e.g. AD 2001 => 01, AD
// 2010 => 10)
case 'rr':
formatter = weekNumberingYearGetter(2, true);
break;
// 3 digit representation of the week-numbering year, padded (000-999). (e.g. AD 1 => 001, AD
// 2010 => 2010)
case 'rrr':
formatter = weekNumberingYearGetter(3);
break;
// 4 digit representation of the week-numbering year (e.g. AD 1 => 0001, AD 2010 => 2010)
case 'rrrr':
formatter = weekNumberingYearGetter(4);
break;
// Month of the year (1-12), numeric // Month of the year (1-12), numeric
case 'M': case 'M':
case 'L': case 'L':

View File

@ -65,6 +65,10 @@ import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
* | | yy | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 | * | | yy | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 |
* | | yyy | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 | * | | yyy | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 |
* | | yyyy | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 | * | | yyyy | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 |
* | Week-numbering year| r | Numeric: minimum digits | 2, 20, 201, 2017, 20173 |
* | | rr | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 |
* | | rrr | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 |
* | | rrrr | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 |
* | Month | M | Numeric: 1 digit | 9, 12 | * | Month | M | Numeric: 1 digit | 9, 12 |
* | | MM | Numeric: 2 digits + zero padded | 09, 12 | * | | MM | Numeric: 2 digits + zero padded | 09, 12 |
* | | MMM | Abbreviated | Sep | * | | MMM | Abbreviated | Sep |

View File

@ -95,6 +95,10 @@ describe('Format date', () => {
yy: '15', yy: '15',
yyy: '2015', yyy: '2015',
yyyy: '2015', yyyy: '2015',
r: '2015',
rr: '15',
rrr: '2015',
rrrr: '2015',
M: '6', M: '6',
MM: '06', MM: '06',
MMM: 'Jun', MMM: 'Jun',
@ -153,6 +157,10 @@ describe('Format date', () => {
yy: '15', yy: '15',
yyy: '2015', yyy: '2015',
yyyy: '2015', yyyy: '2015',
r: '2015',
rr: '15',
rrr: '2015',
rrrr: '2015',
M: '1', M: '1',
MM: '01', MM: '01',
MMM: 'Jan', MMM: 'Jan',
@ -361,5 +369,14 @@ describe('Format date', () => {
expect(formatDate(3001, 'm:ss.SS', 'en')).toEqual('0:03.00'); expect(formatDate(3001, 'm:ss.SS', 'en')).toEqual('0:03.00');
expect(formatDate(3001, 'm:ss.SSS', 'en')).toEqual('0:03.001'); expect(formatDate(3001, 'm:ss.SSS', 'en')).toEqual('0:03.001');
}); });
// https://github.com/angular/angular/issues/38739
it('should return correct ISO 8601 week-numbering year for dates close to year end/beginning',
() => {
expect(formatDate('2013-12-27', 'rrrr', 'en')).toEqual('2013');
expect(formatDate('2013-12-29', 'rrrr', 'en')).toEqual('2014');
expect(formatDate('2010-01-02', 'rrrr', 'en')).toEqual('2009');
expect(formatDate('2010-01-04', 'rrrr', 'en')).toEqual('2010');
});
}); });
}); });