Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: packages/intl/lib/src/intl/date_format_field.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of intl; 5 part of intl;
6 6
7 /** 7 /// This is a private class internal to DateFormat which is used for formatting
8 * This is a private class internal to DateFormat which is used for formatting 8 /// particular fields in a template. e.g. if the format is hh:mm:ss then the
9 * particular fields in a template. e.g. if the format is hh:mm:ss then the 9 /// fields would be "hh", ":", "mm", ":", and "ss". Each type of field knows
10 * fields would be "hh", ":", "mm", ":", and "ss". Each type of field knows 10 /// how to format that portion of a date.
11 * how to format that portion of a date.
12 */
13 abstract class _DateFormatField { 11 abstract class _DateFormatField {
14 /** The format string that defines us, e.g. "hh" */ 12 /// The format string that defines us, e.g. "hh"
15 String pattern; 13 final String pattern;
16 14
17 /** The DateFormat that we are part of.*/ 15 /// The DateFormat that we are part of.
18 DateFormat parent; 16 DateFormat parent;
19 17
20 _DateFormatField(this.pattern, this.parent); 18 /// Trimmed version of [pattern].
19 String _trimmedPattern;
21 20
22 /** 21 _DateFormatField(this.pattern, this.parent) {
23 * Return the width of [pattern]. Different widths represent different 22 _trimmedPattern = pattern.trim();
24 * formatting options. See the comment for DateFormat for details. 23 }
25 */ 24
25 /// Return the width of [pattern]. Different widths represent different
26 /// formatting options. See the comment for DateFormat for details.
26 int get width => pattern.length; 27 int get width => pattern.length;
27 28
28 String fullPattern() => pattern; 29 String fullPattern() => pattern;
29 30
30 String toString() => pattern; 31 String toString() => pattern;
31 32
32 /** Format date according to our specification and return the result. */ 33 /// Format date according to our specification and return the result.
33 String format(DateTime date) { 34 String format(DateTime date) {
34 // Default implementation in the superclass, works for both types of 35 // Default implementation in the superclass, works for both types of
35 // literal patterns, and is overridden by _DateFormatPatternField. 36 // literal patterns, and is overridden by _DateFormatPatternField.
36 return pattern; 37 return pattern;
37 } 38 }
38 39
39 /** Abstract method for subclasses to implementing parsing for their format.*/ 40 /// Abstract method for subclasses to implementing parsing for their format.
40 void parse(_Stream input, _DateBuilder dateFields); 41 void parse(_Stream input, _DateBuilder dateFields);
41 42
42 /** 43 /// Abstract method for subclasses to implementing 'loose' parsing for
43 * Abstract method for subclasses to implementing 'loose' parsing for 44 /// their format, accepting input case-insensitively, and allowing some
44 * their format, accepting input case-insensitively, and allowing some 45 /// delimiters to be skipped.
45 * delimiters to be skipped.
46 */
47 void parseLoose(_Stream input, _DateBuilder dateFields); 46 void parseLoose(_Stream input, _DateBuilder dateFields);
48 47
49 /** Parse a literal field. We just look for the exact input. */ 48 /// Parse a literal field. We just look for the exact input.
50 void parseLiteral(_Stream input) { 49 void parseLiteral(_Stream input) {
51 var found = input.read(width); 50 var found = input.read(width);
52 if (found != pattern) { 51 if (found != pattern) {
53 throwFormatException(input); 52 throwFormatException(input);
54 } 53 }
55 } 54 }
56 55
57 /** 56 /// Parse a literal field. We accept either an exact match, or an arbitrary
58 * Parse a literal field. We accept either an exact match, or an arbitrary 57 /// amount of whitespace.
59 * amount of whitespace. 58 ///
60 */ 59 /// Any whitespace which occurs before or after the literal field is trimmed
60 /// from the input stream. Any leading or trailing whitespace in the literal
61 /// field's format specification is also trimmed before matching is
62 /// attempted. Therefore, leading and trailing whitespace is optional, and
63 /// arbitrary additional whitespace may be added before/after the literal.
61 void parseLiteralLoose(_Stream input) { 64 void parseLiteralLoose(_Stream input) {
62 var found = input.peek(width); 65 _trimWhitespace(input);
63 if (found == pattern) { 66
64 input.read(width); 67 var found = input.peek(_trimmedPattern.length);
68 if (found == _trimmedPattern) {
69 input.read(_trimmedPattern.length);
65 } 70 }
71
72 _trimWhitespace(input);
73 }
74
75 void _trimWhitespace(_Stream input) {
66 while (!input.atEnd() && input.peek().trim().isEmpty) { 76 while (!input.atEnd() && input.peek().trim().isEmpty) {
67 input.read(); 77 input.read();
68 } 78 }
69 } 79 }
70 80
71 /** Throw a format exception with an error message indicating the position.*/ 81 /// Throw a format exception with an error message indicating the position.
72 void throwFormatException(_Stream stream) { 82 void throwFormatException(_Stream stream) {
73 throw new FormatException("Trying to read $this from ${stream.contents} " 83 throw new FormatException("Trying to read $this from ${stream.contents} "
74 "at position ${stream.index}"); 84 "at position ${stream.index}");
75 } 85 }
76 } 86 }
77 87
78 /** 88 /// Represents a literal field - a sequence of characters that doesn't
79 * Represents a literal field - a sequence of characters that doesn't 89 /// change according to the date's data. As such, the implementation
80 * change according to the date's data. As such, the implementation 90 /// is extremely simple.
81 * is extremely simple.
82 */
83 class _DateFormatLiteralField extends _DateFormatField { 91 class _DateFormatLiteralField extends _DateFormatField {
84 _DateFormatLiteralField(pattern, parent) : super(pattern, parent); 92 _DateFormatLiteralField(pattern, parent) : super(pattern, parent);
85 93
86 parse(_Stream input, _DateBuilder dateFields) { 94 parse(_Stream input, _DateBuilder dateFields) {
87 parseLiteral(input); 95 parseLiteral(input);
88 } 96 }
89 97
90 parseLoose(_Stream input, _DateBuilder dateFields) => 98 parseLoose(_Stream input, _DateBuilder dateFields) =>
91 parseLiteralLoose(input); 99 parseLiteralLoose(input);
92 } 100 }
93 101
94 /** 102 /// Represents a literal field with quoted characters in it. This is
95 * Represents a literal field with quoted characters in it. This is 103 /// only slightly more complex than a _DateFormatLiteralField.
96 * only slightly more complex than a _DateFormatLiteralField.
97 */
98 class _DateFormatQuotedField extends _DateFormatField { 104 class _DateFormatQuotedField extends _DateFormatField {
99 String _fullPattern; 105 String _fullPattern;
100 106
101 String fullPattern() => _fullPattern; 107 String fullPattern() => _fullPattern;
102 108
103 _DateFormatQuotedField(pattern, parent) : super(pattern, parent) { 109 _DateFormatQuotedField(pattern, parent)
110 : super(_patchQuotes(pattern), parent) {
104 _fullPattern = pattern; 111 _fullPattern = pattern;
105 patchQuotes();
106 } 112 }
107 113
108 parse(_Stream input, _DateBuilder dateFields) { 114 parse(_Stream input, _DateBuilder dateFields) {
109 parseLiteral(input); 115 parseLiteral(input);
110 } 116 }
111 117
112 parseLoose(_Stream input, _DateBuilder dateFields) => 118 parseLoose(_Stream input, _DateBuilder dateFields) =>
113 parseLiteralLoose(input); 119 parseLiteralLoose(input);
114 120
115 void patchQuotes() { 121 static final _twoEscapedQuotes = new RegExp(r"''");
122
123 static String _patchQuotes(String pattern) {
116 if (pattern == "''") { 124 if (pattern == "''") {
117 pattern = "'"; 125 return "'";
118 } else { 126 } else {
119 pattern = pattern.substring(1, pattern.length - 1); 127 return pattern
120 var twoEscapedQuotes = new RegExp(r"''"); 128 .substring(1, pattern.length - 1)
121 pattern = pattern.replaceAll(twoEscapedQuotes, "'"); 129 .replaceAll(_twoEscapedQuotes, "'");
122 } 130 }
123 } 131 }
124 } 132 }
125 133
126 /** 134 /// A field that parses "loosely", meaning that we'll accept input that is
127 * A field that parses "loosely", meaning that we'll accept input that is 135 /// missing delimiters, has upper/lower case mixed up, and might not strictly
128 * missing delimiters, has upper/lower case mixed up, and might not strictly 136 /// conform to the pattern, e.g. the pattern calls for Sep we might accept
129 * conform to the pattern, e.g. the pattern calls for Sep we might accept 137 /// sep, september, sEPTember. Doesn't affect numeric fields.
130 * sep, september, sEPTember. Doesn't affect numeric fields.
131 */
132 class _LoosePatternField extends _DateFormatPatternField { 138 class _LoosePatternField extends _DateFormatPatternField {
133 _LoosePatternField(String pattern, parent) : super(pattern, parent); 139 _LoosePatternField(String pattern, parent) : super(pattern, parent);
134 140
135 /** 141 /// Parse from a list of possibilities, but case-insensitively.
136 * Parse from a list of possibilities, but case-insensitively. 142 /// Assumes that input is lower case.
137 * Assumes that input is lower case.
138 */
139 int parseEnumeratedString(_Stream input, List possibilities) { 143 int parseEnumeratedString(_Stream input, List possibilities) {
140 var lowercasePossibilities = 144 var lowercasePossibilities =
141 possibilities.map((x) => x.toLowerCase()).toList(); 145 possibilities.map((x) => x.toLowerCase()).toList();
142 try { 146 try {
143 return super.parseEnumeratedString(input, lowercasePossibilities); 147 return super.parseEnumeratedString(input, lowercasePossibilities);
144 } on FormatException { 148 } on FormatException {
145 return -1; 149 return -1;
146 } 150 }
147 } 151 }
148 152
149 /** 153 /// Parse a month name, case-insensitively, and set it in [dateFields].
150 * Parse a month name, case-insensitively, and set it in [dateFields]. 154 /// Assumes that [input] is lower case.
151 * Assumes that [input] is lower case.
152 */
153 void parseMonth(input, dateFields) { 155 void parseMonth(input, dateFields) {
154 if (width <= 2) { 156 if (width <= 2) {
155 handleNumericField(input, dateFields.setMonth); 157 handleNumericField(input, dateFields.setMonth);
156 return; 158 return;
157 } 159 }
158 var possibilities = [symbols.MONTHS, symbols.SHORTMONTHS]; 160 var possibilities = [symbols.MONTHS, symbols.SHORTMONTHS];
159 for (var monthNames in possibilities) { 161 for (var monthNames in possibilities) {
160 var month = parseEnumeratedString(input, monthNames); 162 var month = parseEnumeratedString(input, monthNames);
161 if (month != -1) { 163 if (month != -1) {
162 dateFields.month = month + 1; 164 dateFields.month = month + 1;
163 return; 165 return;
164 } 166 }
165 } 167 }
168 throwFormatException(input);
166 } 169 }
167 170
168 /** 171 /// Parse a standalone day name, case-insensitively.
169 * Parse a standalone day name, case-insensitively. 172 /// Assumes that input is lower case. Doesn't do anything
170 * Assumes that input is lower case. Doesn't do anything
171 */
172 void parseStandaloneDay(input) { 173 void parseStandaloneDay(input) {
173 // This is ignored, but we still have to skip over it the correct amount. 174 // This is ignored, but we still have to skip over it the correct amount.
174 if (width <= 2) { 175 if (width <= 2) {
175 handleNumericField(input, (x) => x); 176 handleNumericField(input, (x) => x);
176 return; 177 return;
177 } 178 }
178 var possibilities = [ 179 var possibilities = [
179 symbols.STANDALONEWEEKDAYS, 180 symbols.STANDALONEWEEKDAYS,
180 symbols.STANDALONESHORTWEEKDAYS 181 symbols.STANDALONESHORTWEEKDAYS
181 ]; 182 ];
182 for (var dayNames in possibilities) { 183 for (var dayNames in possibilities) {
183 var day = parseEnumeratedString(input, dayNames); 184 var day = parseEnumeratedString(input, dayNames);
184 if (day != -1) { 185 if (day != -1) {
185 return; 186 return;
186 } 187 }
187 } 188 }
188 } 189 }
189 190
190 /** 191 /// Parse a standalone month name, case-insensitively, and set it in
191 * Parse a standalone month name, case-insensitively. 192 /// [dateFields]. Assumes that input is lower case.
192 * Assumes that input is lower case. Doesn't do anything
193 */
194 void parseStandaloneMonth(input, dateFields) { 193 void parseStandaloneMonth(input, dateFields) {
195 if (width <= 2) { 194 if (width <= 2) {
196 handleNumericField(input, (x) => x); 195 handleNumericField(input, dateFields.setMonth);
197 return; 196 return;
198 } 197 }
199 var possibilities = [ 198 var possibilities = [
200 symbols.STANDALONEMONTHS, 199 symbols.STANDALONEMONTHS,
201 symbols.STANDALONESHORTMONTHS 200 symbols.STANDALONESHORTMONTHS
202 ]; 201 ];
203 for (var monthNames in possibilities) { 202 for (var monthNames in possibilities) {
204 var month = parseEnumeratedString(input, monthNames); 203 var month = parseEnumeratedString(input, monthNames);
205 if (month != -1) { 204 if (month != -1) {
206 dateFields.month = month + 1; 205 dateFields.month = month + 1;
207 return; 206 return;
208 } 207 }
209 } 208 }
209 throwFormatException(input);
210 } 210 }
211 211
212 /** 212 /// Parse a day of the week name, case-insensitively.
213 * Parse a day of the week name, case-insensitively. 213 /// Assumes that input is lower case. Doesn't do anything
214 * Assumes that input is lower case. Doesn't do anything
215 */
216 void parseDayOfWeek(_Stream input) { 214 void parseDayOfWeek(_Stream input) {
217 // This is IGNORED, but we still have to skip over it the correct amount. 215 // This is IGNORED, but we still have to skip over it the correct amount.
218 if (width <= 2) { 216 if (width <= 2) {
219 handleNumericField(input, (x) => x); 217 handleNumericField(input, (x) => x);
220 return; 218 return;
221 } 219 }
222 var possibilities = [symbols.WEEKDAYS, symbols.SHORTWEEKDAYS]; 220 var possibilities = [symbols.WEEKDAYS, symbols.SHORTWEEKDAYS];
223 for (var dayNames in possibilities) { 221 for (var dayNames in possibilities) {
224 var day = parseEnumeratedString(input, dayNames); 222 var day = parseEnumeratedString(input, dayNames);
225 if (day != -1) { 223 if (day != -1) {
226 return; 224 return;
227 } 225 }
228 } 226 }
229 } 227 }
230 } 228 }
231 229
232 /* 230 /*
233 * Represents a field in the pattern that formats some aspect of the 231 * Represents a field in the pattern that formats some aspect of the
234 * date. Consists primarily of a switch on the particular pattern characters 232 * date. Consists primarily of a switch on the particular pattern characters
235 * to determine what to do. 233 * to determine what to do.
236 */ 234 */
237 class _DateFormatPatternField extends _DateFormatField { 235 class _DateFormatPatternField extends _DateFormatField {
238 _DateFormatPatternField(pattern, parent) : super(pattern, parent); 236 _DateFormatPatternField(pattern, parent) : super(pattern, parent);
239 237
240 /** Format date according to our specification and return the result. */ 238 /// Format date according to our specification and return the result.
241 String format(DateTime date) { 239 String format(DateTime date) {
242 return formatField(date); 240 return formatField(date);
243 } 241 }
244 242
245 /** 243 /// Parse the date according to our specification and put the result
246 * Parse the date according to our specification and put the result 244 /// into the correct place in dateFields.
247 * into the correct place in dateFields.
248 */
249 void parse(_Stream input, _DateBuilder dateFields) { 245 void parse(_Stream input, _DateBuilder dateFields) {
250 parseField(input, dateFields); 246 parseField(input, dateFields);
251 } 247 }
252 248
253 /** 249 /// Parse the date according to our specification and put the result
254 * Parse the date according to our specification and put the result 250 /// into the correct place in dateFields. Allow looser parsing, accepting
255 * into the correct place in dateFields. Allow looser parsing, accepting 251 /// case-insensitive input and skipped delimiters.
256 * case-insensitive input and skipped delimiters.
257 */
258 void parseLoose(_Stream input, _DateBuilder dateFields) { 252 void parseLoose(_Stream input, _DateBuilder dateFields) {
259 new _LoosePatternField(pattern, parent).parse(input, dateFields); 253 new _LoosePatternField(pattern, parent).parse(input, dateFields);
260 } 254 }
261 255
262 /** 256 /// Parse a field representing part of a date pattern. Note that we do not
263 * Parse a field representing part of a date pattern. Note that we do not 257 /// return a value, but rather build up the result in [builder].
264 * return a value, but rather build up the result in [builder].
265 */
266 void parseField(_Stream input, _DateBuilder builder) { 258 void parseField(_Stream input, _DateBuilder builder) {
267 try { 259 try {
268 switch (pattern[0]) { 260 switch (pattern[0]) {
269 case 'a': 261 case 'a':
270 parseAmPm(input, builder); 262 parseAmPm(input, builder);
271 break; 263 break;
272 case 'c': 264 case 'c':
273 parseStandaloneDay(input); 265 parseStandaloneDay(input);
274 break; 266 break;
275 case 'd': 267 case 'd':
276 handleNumericField(input, builder.setDay); 268 handleNumericField(input, builder.setDay);
277 break; // day 269 break; // day
278 // Day of year. Setting month=January with any day of the year works 270 // Day of year. Setting month=January with any day of the year works
279 case 'D': 271 case 'D':
280 handleNumericField(input, builder.setDay); 272 handleNumericField(input, builder.setDay);
281 break; // dayofyear 273 break; // dayofyear
282 case 'E': 274 case 'E':
283 parseDayOfWeek(input); 275 parseDayOfWeek(input);
284 break; 276 break;
285 case 'G': 277 case 'G':
278 parseEra(input);
286 break; // era 279 break; // era
287 case 'h': 280 case 'h':
288 parse1To12Hours(input, builder); 281 parse1To12Hours(input, builder);
289 break; 282 break;
290 case 'H': 283 case 'H':
291 handleNumericField(input, builder.setHour); 284 handleNumericField(input, builder.setHour);
292 break; // hour 0-23 285 break; // hour 0-23
293 case 'K': 286 case 'K':
294 handleNumericField(input, builder.setHour); 287 handleNumericField(input, builder.setHour);
295 break; //hour 0-11 288 break; //hour 0-11
(...skipping 27 matching lines...) Expand all
323 case 'Z': 316 case 'Z':
324 break; // time zone RFC 317 break; // time zone RFC
325 default: 318 default:
326 return; 319 return;
327 } 320 }
328 } catch (e) { 321 } catch (e) {
329 throwFormatException(input); 322 throwFormatException(input);
330 } 323 }
331 } 324 }
332 325
333 /** Formatting logic if we are of type FIELD */ 326 /// Formatting logic if we are of type FIELD
334 String formatField(DateTime date) { 327 String formatField(DateTime date) {
335 switch (pattern[0]) { 328 switch (pattern[0]) {
336 case 'a': 329 case 'a':
337 return formatAmPm(date); 330 return formatAmPm(date);
338 case 'c': 331 case 'c':
339 return formatStandaloneDay(date); 332 return formatStandaloneDay(date);
340 case 'd': 333 case 'd':
341 return formatDayOfMonth(date); 334 return formatDayOfMonth(date);
342 case 'D': 335 case 'D':
343 return formatDayOfYear(date); 336 return formatDayOfYear(date);
(...skipping 27 matching lines...) Expand all
371 return formatYear(date); 364 return formatYear(date);
372 case 'z': 365 case 'z':
373 return formatTimeZone(date); 366 return formatTimeZone(date);
374 case 'Z': 367 case 'Z':
375 return formatTimeZoneRFC(date); 368 return formatTimeZoneRFC(date);
376 default: 369 default:
377 return ''; 370 return '';
378 } 371 }
379 } 372 }
380 373
381 /** Return the symbols for our current locale. */ 374 /// Return the symbols for our current locale.
382 DateSymbols get symbols => dateTimeSymbols[parent.locale]; 375 DateSymbols get symbols => parent.dateSymbols;
383 376
384 formatEra(DateTime date) { 377 formatEra(DateTime date) {
385 var era = date.year > 0 ? 1 : 0; 378 var era = date.year > 0 ? 1 : 0;
386 return width >= 4 ? symbols.ERANAMES[era] : symbols.ERAS[era]; 379 return width >= 4 ? symbols.ERANAMES[era] : symbols.ERAS[era];
387 } 380 }
388 381
389 formatYear(DateTime date) { 382 formatYear(DateTime date) {
390 // TODO(alanknight): Proper handling of years <= 0 383 // TODO(alanknight): Proper handling of years <= 0
391 var year = date.year; 384 var year = date.year;
392 if (year < 0) { 385 if (year < 0) {
393 year = -year; 386 year = -year;
394 } 387 }
395 return width == 2 ? padTo(2, year % 100) : padTo(width, year); 388 return width == 2 ? padTo(2, year % 100) : padTo(width, year);
396 } 389 }
397 390
398 /** 391 /// We are given [input] as a stream from which we want to read a date. We
399 * We are given [input] as a stream from which we want to read a date. We 392 /// can't dynamically build up a date, so we are given a list [dateFields] of
400 * can't dynamically build up a date, so we are given a list [dateFields] of 393 /// the constructor arguments and an [position] at which to set it
401 * the constructor arguments and an [position] at which to set it 394 /// (year,month,day,hour,minute,second,fractionalSecond)
402 * (year,month,day,hour,minute,second,fractionalSecond) 395 /// then after all parsing is done we construct a date from the arguments.
403 * then after all parsing is done we construct a date from the arguments. 396 /// This method handles reading any of the numeric fields. The [offset]
404 * This method handles reading any of the numeric fields. The [offset] 397 /// argument allows us to compensate for zero-based versus one-based values.
405 * argument allows us to compensate for zero-based versus one-based values.
406 */
407 void handleNumericField(_Stream input, Function setter, [int offset = 0]) { 398 void handleNumericField(_Stream input, Function setter, [int offset = 0]) {
408 var result = input.nextInteger(); 399 var result = input.nextInteger();
409 if (result == null) throwFormatException(input); 400 if (result == null) throwFormatException(input);
410 setter(result + offset); 401 setter(result + offset);
411 } 402 }
412 403
413 /** 404 /// We are given [input] as a stream from which we want to read a date. We
414 * We are given [input] as a stream from which we want to read a date. We 405 /// can't dynamically build up a date, so we are given a list [dateFields] of
415 * can't dynamically build up a date, so we are given a list [dateFields] of 406 /// the constructor arguments and an [position] at which to set it
416 * the constructor arguments and an [position] at which to set it 407 /// (year,month,day,hour,minute,second,fractionalSecond)
417 * (year,month,day,hour,minute,second,fractionalSecond) 408 /// then after all parsing is done we construct a date from the arguments.
418 * then after all parsing is done we construct a date from the arguments. 409 /// This method handles reading any of string fields from an enumerated set.
419 * This method handles reading any of string fields from an enumerated set.
420 */
421 int parseEnumeratedString(_Stream input, List possibilities) { 410 int parseEnumeratedString(_Stream input, List possibilities) {
422 var results = new _Stream(possibilities) 411 var results = new _Stream(possibilities)
423 .findIndexes((each) => input.peek(each.length) == each); 412 .findIndexes((each) => input.peek(each.length) == each);
424 if (results.isEmpty) throwFormatException(input); 413 if (results.isEmpty) throwFormatException(input);
425 results.sort( 414 results.sort(
426 (a, b) => possibilities[a].length.compareTo(possibilities[b].length)); 415 (a, b) => possibilities[a].length.compareTo(possibilities[b].length));
427 var longestResult = results.last; 416 var longestResult = results.last;
428 input.read(possibilities[longestResult].length); 417 input.read(possibilities[longestResult].length);
429 return longestResult; 418 return longestResult;
430 } 419 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 if (width - 3 > 0) { 459 if (width - 3 > 0) {
471 var extra = padTo(width - 3, 0); 460 var extra = padTo(width - 3, 0);
472 return basic + extra; 461 return basic + extra;
473 } else { 462 } else {
474 return basic; 463 return basic;
475 } 464 }
476 } 465 }
477 466
478 String formatAmPm(DateTime date) { 467 String formatAmPm(DateTime date) {
479 var hours = date.hour; 468 var hours = date.hour;
480 var index = (date.hour >= 12) && (date.hour < 24) ? 1 : 0; 469 var index = (hours >= 12) && (hours < 24) ? 1 : 0;
481 var ampm = symbols.AMPMS; 470 var ampm = symbols.AMPMS;
482 return ampm[index]; 471 return ampm[index];
483 } 472 }
484 473
485 void parseAmPm(input, dateFields) { 474 void parseAmPm(input, dateFields) {
486 // If we see a "PM" note it in an extra field. 475 // If we see a "PM" note it in an extra field.
487 var ampm = parseEnumeratedString(input, symbols.AMPMS); 476 var ampm = parseEnumeratedString(input, symbols.AMPMS);
488 if (ampm == 1) dateFields.pm = true; 477 if (ampm == 1) dateFields.pm = true;
489 } 478 }
490 479
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 possibilities = symbols.STANDALONESHORTMONTHS; 555 possibilities = symbols.STANDALONESHORTMONTHS;
567 break; 556 break;
568 default: 557 default:
569 return handleNumericField(input, dateFields.setMonth); 558 return handleNumericField(input, dateFields.setMonth);
570 } 559 }
571 dateFields.month = parseEnumeratedString(input, possibilities) + 1; 560 dateFields.month = parseEnumeratedString(input, possibilities) + 1;
572 } 561 }
573 562
574 String formatQuarter(DateTime date) { 563 String formatQuarter(DateTime date) {
575 var quarter = ((date.month - 1) / 3).truncate(); 564 var quarter = ((date.month - 1) / 3).truncate();
576 if (width < 4) { 565 switch (width) {
577 return symbols.SHORTQUARTERS[quarter]; 566 case 4:
578 } else { 567 return symbols.QUARTERS[quarter];
579 return symbols.QUARTERS[quarter]; 568 case 3:
569 return symbols.SHORTQUARTERS[quarter];
570 default:
571 return padTo(width, quarter + 1);
580 } 572 }
581 } 573 }
574
582 String formatDayOfMonth(DateTime date) { 575 String formatDayOfMonth(DateTime date) {
583 return padTo(width, date.day); 576 return padTo(width, date.day);
584 } 577 }
585 578
586 String formatDayOfYear(DateTime date) => padTo(width, dayNumberInYear(date)); 579 String formatDayOfYear(DateTime date) => padTo(width, dayNumberInYear(date));
587 580
588 /** Return the ordinal day, i.e. the day number in the year. */ 581 /// Return the ordinal day, i.e. the day number in the year.
589 int dayNumberInYear(DateTime date) { 582 int dayNumberInYear(DateTime date) {
590 if (date.month == 1) return date.day; 583 if (date.month == 1) return date.day;
591 if (date.month == 2) return date.day + 31; 584 if (date.month == 2) return date.day + 31;
592 return ordinalDayFromMarchFirst(date) + 59 + (isLeapYear(date) ? 1 : 0); 585 return ordinalDayFromMarchFirst(date) + 59 + (isLeapYear(date) ? 1 : 0);
593 } 586 }
594 587
595 /** 588 /// Return the day of the year counting March 1st as 1, after which the
596 * Return the day of the year counting March 1st as 1, after which the 589 /// number of days per month is constant, so it's easier to calculate.
597 * number of days per month is constant, so it's easier to calculate. 590 /// Formula from http://en.wikipedia.org/wiki/Ordinal_date
598 * Formula from http://en.wikipedia.org/wiki/Ordinal_date
599 */
600 int ordinalDayFromMarchFirst(DateTime date) => 591 int ordinalDayFromMarchFirst(DateTime date) =>
601 ((30.6 * date.month) - 91.4).floor() + date.day; 592 ((30.6 * date.month) - 91.4).floor() + date.day;
602 593
603 /** 594 /// Return true if this is a leap year. Rely on [DateTime] to do the
604 * Return true if this is a leap year. Rely on [DateTime] to do the 595 /// underlying calculation, even though it doesn't expose the test to us.
605 * underlying calculation, even though it doesn't expose the test to us.
606 */
607 bool isLeapYear(DateTime date) { 596 bool isLeapYear(DateTime date) {
608 var feb29 = new DateTime(date.year, 2, 29); 597 var feb29 = new DateTime(date.year, 2, 29);
609 return feb29.month == 2; 598 return feb29.month == 2;
610 } 599 }
611 600
612 String formatDayOfWeek(DateTime date) { 601 String formatDayOfWeek(DateTime date) {
613 // Note that Dart's weekday returns 1 for Monday and 7 for Sunday. 602 // Note that Dart's weekday returns 1 for Monday and 7 for Sunday.
614 return (width >= 4 603 return (width >= 4 ? symbols.WEEKDAYS : symbols.SHORTWEEKDAYS)[
615 ? symbols.WEEKDAYS 604 (date.weekday) % 7];
616 : symbols.SHORTWEEKDAYS)[(date.weekday) % 7];
617 } 605 }
618 606
619 void parseDayOfWeek(_Stream input) { 607 void parseDayOfWeek(_Stream input) {
620 // This is IGNORED, but we still have to skip over it the correct amount. 608 // This is IGNORED, but we still have to skip over it the correct amount.
621 var possibilities = width >= 4 ? symbols.WEEKDAYS : symbols.SHORTWEEKDAYS; 609 var possibilities = width >= 4 ? symbols.WEEKDAYS : symbols.SHORTWEEKDAYS;
622 parseEnumeratedString(input, possibilities); 610 parseEnumeratedString(input, possibilities);
623 } 611 }
624 612
613 void parseEra(_Stream input) {
614 var possibilities = width >= 4 ? symbols.ERANAMES : symbols.ERAS;
615 parseEnumeratedString(input, possibilities);
616 }
617
625 String formatMinutes(DateTime date) { 618 String formatMinutes(DateTime date) {
626 return padTo(width, date.minute); 619 return padTo(width, date.minute);
627 } 620 }
628 621
629 String formatSeconds(DateTime date) { 622 String formatSeconds(DateTime date) {
630 return padTo(width, date.second); 623 return padTo(width, date.second);
631 } 624 }
632 625
633 String formatTimeZoneId(DateTime date) { 626 String formatTimeZoneId(DateTime date) {
634 // TODO(alanknight): implement time zone support 627 // TODO(alanknight): implement time zone support
635 throw new UnimplementedError(); 628 throw new UnimplementedError();
636 } 629 }
637 630
638 String formatTimeZone(DateTime date) { 631 String formatTimeZone(DateTime date) {
639 throw new UnimplementedError(); 632 throw new UnimplementedError();
640 } 633 }
641 634
642 String formatTimeZoneRFC(DateTime date) { 635 String formatTimeZoneRFC(DateTime date) {
643 throw new UnimplementedError(); 636 throw new UnimplementedError();
644 } 637 }
645 638
646 /** 639 /// Return a string representation of the object padded to the left with
647 * Return a string representation of the object padded to the left with 640 /// zeros. Primarily useful for numbers.
648 * zeros. Primarily useful for numbers. 641 static String padTo(int width, Object toBePrinted) =>
649 */ 642 '$toBePrinted'.padLeft(width, '0');
650 String padTo(int width, Object toBePrinted) {
651 var basicString = toBePrinted.toString();
652 if (basicString.length >= width) return basicString;
653 var buffer = new StringBuffer();
654 for (var i = 0; i < width - basicString.length; i++) {
655 buffer.write('0');
656 }
657 buffer.write(basicString);
658 return buffer.toString();
659 }
660 } 643 }
OLDNEW
« no previous file with comments | « packages/intl/lib/src/intl/date_format.dart ('k') | packages/intl/lib/src/intl/date_format_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698