Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 3af1e7c

Browse files
Di PengIgorMinar
Di Peng
authored andcommitted
feat(filter.date): add support for default datetime formats in en
- add support for full,long, medium, short datetime formats in en Breaks MMMMM. now we don't support MMMMM anymore as old implementation differs from Unicode Locale Data format we are following. - removed support for fullDateTime and fullTime as it means too much trouble with full timeZone names - added docs for the new features
1 parent 0fbaa2f commit 3af1e7c

File tree

4 files changed

+133
-27
lines changed

4 files changed

+133
-27
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<a name="0.9.18"><a/>
22
# <angular/> 0.9.18 jiggling-armfat (in-progress) #
3-
3+
### Breaking changes
4+
- no longer support MMMMM in filter.date as we need to follow UNICODE LOCALE DATA formats.
45

56

67

src/filters.js

+59-10
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,17 @@ function dateStrGetter(name, shortForm) {
184184
};
185185
}
186186

187+
function timeZoneGetter(numFormat) {
188+
return function(date) {
189+
var timeZone;
190+
if (numFormat || !(timeZone = GET_TIME_ZONE.exec(date.toString()))) {
191+
var offset = date.getTimezoneOffset();
192+
return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);
193+
}
194+
return timeZone[0];
195+
};
196+
}
197+
187198
var DAY = 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(',');
188199

189200
var MONTH = 'January,February,March,April,May,June,July,August,September,October,November,December'.
@@ -192,7 +203,8 @@ var MONTH = 'January,February,March,April,May,June,July,August,September,October
192203
var DATE_FORMATS = {
193204
yyyy: dateGetter('FullYear', 4),
194205
yy: dateGetter('FullYear', 2, 0, true),
195-
MMMMM: dateStrGetter('Month'),
206+
y: dateGetter('FullYear', 1),
207+
MMMM: dateStrGetter('Month'),
196208
MMM: dateStrGetter('Month', true),
197209
MM: dateGetter('Month', 2, 1),
198210
M: dateGetter('Month', 1, 1),
@@ -209,14 +221,26 @@ var DATE_FORMATS = {
209221
EEEE: dateStrGetter('Day'),
210222
EEE: dateStrGetter('Day', true),
211223
a: function(date){return date.getHours() < 12 ? 'am' : 'pm';},
212-
Z: function(date){
213-
var offset = date.getTimezoneOffset();
214-
return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);
215-
}
224+
z: timeZoneGetter(false),
225+
Z: timeZoneGetter(true)
216226
};
217227

228+
var DEFAULT_DATETIME_FORMATS = {
229+
long: 'MMMM d, y h:mm:ss a z',
230+
medium: 'MMM d, y h:mm:ss a',
231+
short: 'M/d/yy h:mm a',
232+
fullDate: 'EEEE, MMMM d, y',
233+
longDate: 'MMMM d, y',
234+
mediumDate: 'MMM d, y',
235+
shortDate: 'M/d/yy',
236+
longTime: 'h:mm:ss a z',
237+
mediumTime: 'h:mm:ss a',
238+
shortTime: 'h:mm a'
239+
};
218240

219-
var DATE_FORMATS_SPLIT = /([^yMdHhmsaZE]*)(E+|y+|M+|d+|H+|h+|m+|s+|a|Z)(.*)/;
241+
var GET_TIME_ZONE = /[A-Z]{3}(?![+\-])/;
242+
var DATE_FORMATS_SPLIT = /([^yMdHhmsazZE]*)(E+|y+|M+|d+|H+|h+|m+|s+|a|Z|z)(.*)/;
243+
var OPERA_TOSTRING_PATTERN = /^[\d].*Z$/;
220244
var NUMBER_STRING = /^\d+$/;
221245

222246

@@ -231,9 +255,10 @@ var NUMBER_STRING = /^\d+$/;
231255
*
232256
* `format` string can be composed of the following elements:
233257
*
234-
* * `'yyyy'`: 4 digit representation of year e.g. 2010
235-
* * `'yy'`: 2 digit representation of year, padded (00-99)
236-
* * `'MMMMM'`: Month in year (January‒December)
258+
* * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
259+
* * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
260+
* * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
261+
* * `'MMMM'`: Month in year (January‒December)
237262
* * `'MMM'`: Month in year (Jan - Dec)
238263
* * `'MM'`: Month in year, padded (01‒12)
239264
* * `'M'`: Month in year (1‒12)
@@ -251,22 +276,45 @@ var NUMBER_STRING = /^\d+$/;
251276
* * `'s'`: Second in minute (0‒59)
252277
* * `'a'`: am/pm marker
253278
* * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200‒1200)
279+
* * `'z'`: short form of current timezone name (e.g. PDT)
280+
*
281+
* `format` string can also be the following default formats for `en_US` locale (support for other
282+
* locales will be added in the future versions):
283+
*
284+
* * `'long'`: equivalent to `'MMMM d, y h:mm:ss a z'` for en_US locale
285+
* (e.g. September 3, 2010 12:05:08 pm PDT)
286+
* * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
287+
* (e.g. Sep 3, 2010 12:05:08 pm)
288+
* * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 pm)
289+
* * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US locale
290+
* (e.g. Friday, September 3, 2010)
291+
* * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010
292+
* * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
293+
* * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
294+
* * `'longTime'`: equivalent to `'h:mm:ss a z'` for en_US locale (e.g. 12:05:08 pm PDT)
295+
* * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)
296+
* * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)
254297
*
255298
* @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
256299
* number) or ISO 8601 extended datetime string (yyyy-MM-ddTHH:mm:ss.SSSZ).
257-
* @param {string=} format Formatting rules. If not specified, Date#toLocaleDateString is used.
300+
* @param {string=} format Formatting rules (see Description). If not specified,
301+
* Date#toLocaleDateString is used.
258302
* @returns {string} Formatted string or the input if input is not recognized as date/millis.
259303
*
260304
* @example
261305
<doc:example>
262306
<doc:source>
307+
<span ng:non-bindable>{{1288323623006 | date:'medium'}}</span>:
308+
{{1288323623006 | date:'medium'}}<br/>
263309
<span ng:non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
264310
{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br/>
265311
<span ng:non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
266312
{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br/>
267313
</doc:source>
268314
<doc:scenario>
269315
it('should format date', function(){
316+
expect(binding("1288323623006 | date:'medium'")).
317+
toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} pm/);
270318
expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).
271319
toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/);
272320
expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
@@ -276,6 +324,7 @@ var NUMBER_STRING = /^\d+$/;
276324
</doc:example>
277325
*/
278326
angularFilter.date = function(date, format) {
327+
format = DEFAULT_DATETIME_FORMATS[format] || format;
279328
if (isString(date)) {
280329
if (NUMBER_STRING.test(date)) {
281330
date = parseInt(date, 10);

test/FiltersSpec.js

+69-9
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ describe('filter', function() {
111111
});
112112

113113
it('should handle mailto:', function() {
114-
expect(linky("mailto:[email protected]").html).toEqual('<a href="mailto:[email protected]">[email protected]</a>');
115-
expect(linky("[email protected]").html).toEqual('<a href="mailto:[email protected]">[email protected]</a>');
114+
expect(linky("mailto:[email protected]").html).
115+
toEqual('<a href="mailto:[email protected]">[email protected]</a>');
116+
expect(linky("[email protected]").html).
117+
toEqual('<a href="mailto:[email protected]">[email protected]</a>');
116118
expect(linky("send email to [email protected], but").html).
117119
toEqual('send email to <a href="mailto:[email protected]">[email protected]</a>, but');
118120
});
@@ -123,6 +125,9 @@ describe('filter', function() {
123125
var morning = new TzDate(+5, '2010-09-03T12:05:08.000Z'); //7am
124126
var noon = new TzDate(+5, '2010-09-03T17:05:08.000Z'); //12pm
125127
var midnight = new TzDate(+5, '2010-09-03T05:05:08.000Z'); //12am
128+
var earlyDate = new TzDate(+5, '0001-09-03T05:05:08.000Z');
129+
var timZoneDate = new TzDate(+5, '2010-09-03T05:05:08.000Z',
130+
'Mon Sep 3 2010 00:05:08 GMT+0500 (XYZ)'); //12am
126131

127132
it('should ignore falsy inputs', function() {
128133
expect(filter.date(null)).toBeNull();
@@ -141,24 +146,79 @@ describe('filter', function() {
141146

142147
it('should accept various format strings', function() {
143148
expect(filter.date(morning, "yy-MM-dd HH:mm:ss")).
144-
toEqual('10-09-03 07:05:08');
149+
toEqual('10-09-03 07:05:08');
145150

146151
expect(filter.date(midnight, "yyyy-M-d h=H:m:saZ")).
147-
toEqual('2010-9-3 12=0:5:8am0500');
152+
toEqual('2010-9-3 12=0:5:8am0500');
148153

149154
expect(filter.date(midnight, "yyyy-MM-dd hh=HH:mm:ssaZ")).
150-
toEqual('2010-09-03 12=00:05:08am0500');
155+
toEqual('2010-09-03 12=00:05:08am0500');
151156

152157
expect(filter.date(noon, "yyyy-MM-dd hh=HH:mm:ssaZ")).
153-
toEqual('2010-09-03 12=12:05:08pm0500');
158+
toEqual('2010-09-03 12=12:05:08pm0500');
159+
160+
expect(filter.date(timZoneDate, "yyyy-MM-dd hh=HH:mm:ss a z")).
161+
toEqual('2010-09-03 12=00:05:08 am XYZ');
154162

155163
expect(filter.date(noon, "EEE, MMM d, yyyy")).
156-
toEqual('Fri, Sep 3, 2010');
164+
toEqual('Fri, Sep 3, 2010');
165+
166+
expect(filter.date(noon, "EEEE, MMMM dd, yyyy")).
167+
toEqual('Friday, September 03, 2010');
168+
169+
expect(filter.date(earlyDate, "MMMM dd, y")).
170+
toEqual('September 03, 1');
171+
});
172+
173+
it('should accept default formats', function() {
174+
175+
expect(filter.date(timZoneDate, "long")).
176+
toEqual('September 3, 2010 12:05:08 am XYZ');
177+
178+
expect(filter.date(noon, "medium")).
179+
toEqual('Sep 3, 2010 12:05:08 pm');
180+
181+
expect(filter.date(noon, "short")).
182+
toEqual('9/3/10 12:05 pm');
183+
184+
expect(filter.date(noon, "fullDate")).
185+
toEqual('Friday, September 3, 2010');
186+
187+
expect(filter.date(noon, "longDate")).
188+
toEqual('September 3, 2010');
157189

158-
expect(filter.date(noon, "EEEE, MMMMM dd, yyyy")).
159-
toEqual('Friday, September 03, 2010');
190+
expect(filter.date(noon, "mediumDate")).
191+
toEqual('Sep 3, 2010');
192+
193+
expect(filter.date(noon, "shortDate")).
194+
toEqual('9/3/10');
195+
196+
expect(filter.date(timZoneDate, "longTime")).
197+
toEqual('12:05:08 am XYZ');
198+
199+
expect(filter.date(noon, "mediumTime")).
200+
toEqual('12:05:08 pm');
201+
202+
expect(filter.date(noon, "shortTime")).
203+
toEqual('12:05 pm');
204+
});
205+
206+
207+
it('should parse timezone identifier from various toString values', function() {
208+
//chrome and firefox format
209+
expect(filter.date(new TzDate(+5, '2010-09-03T17:05:08.000Z',
210+
'Mon Sep 3 2010 17:05:08 GMT+0500 (XYZ)'), "z")).toBe('XYZ');
211+
212+
//opera format
213+
expect(filter.date(new TzDate(+5, '2010-09-03T17:05:08.000Z',
214+
'2010-09-03T17:05:08Z'), "z")).toBe('0500');
215+
216+
//ie 8 format
217+
expect(filter.date(new TzDate(+5, '2010-09-03T17:05:08.000Z',
218+
'Mon Sep 3 17:05:08 XYZ 2010'), "z")).toBe('XYZ');
160219
});
161220

221+
162222
it('should be able to parse ISO 8601 dates/times using', function() {
163223
var isoString = '2010-09-03T05:05:08.872Z';
164224
expect(filter.date(isoString)).

test/angular-mocksSpec.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,9 @@ describe('mocks', function(){
130130

131131

132132
it('should throw error when no third param but toString called', function() {
133-
var t = new TzDate(0, 0);
134-
try {
135-
t.toString();
136-
} catch(err) {
137-
expect(err.name).toBe('MethodNotImplemented');
138-
}
139-
})
133+
expect(function() { new TzDate(0,0).toString() }).
134+
toThrow('Method \'toString\' is not implemented in the TzDate mock');
135+
});
140136
});
141137

142138
describe('$log mock', function() {

0 commit comments

Comments
 (0)