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

Side by Side Diff: lib/i18n/lib/date_format_field.dart

Issue 10827227: Start moving non-platform libraries from lib/ to pkg/ . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Start moving non-platform libraries from lib/ to pkg/ Created 8 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 | Annotate | Revision Log
« no previous file with comments | « lib/i18n/intl_message.dart ('k') | lib/i18n/lib/date_format_helpers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * This is a private class internal to DateFormat which is used for formatting
7 * particular fields in a template. e.g. if the format is hh:mm:ss then the
8 * fields would be "hh", ":", "mm", ":", and "ss". Each type of field knows
9 * how to format that portion of a date.
10 */
11 class _DateFormatField {
12 /** The format string that defines us, e.g. "hh" */
13 String pattern;
14
15 /** The DateFormat that we are part of.*/
16 DateFormat parent;
17
18 _DateFormatField(this.pattern, this.parent);
19
20 /**
21 * Return the width of [pattern]. Different widths represent different
22 * formatting options. See the comment for DateFormat for details.
23 */
24 int get width() => pattern.length;
25
26 String fullPattern() => pattern;
27
28 String toString() => pattern;
29
30 /** Format date according to our specification and return the result. */
31 String format(Date date) {
32 // Default implementation in the superclass, works for both types of
33 // literal patterns, and is overridden by _DateFormatPatternField.
34 return pattern;
35 }
36
37 abstract void parse(_Stream input, _DateBuilder dateFields);
38
39 /** Parse a literal field. We just look for the exact input. */
40 void parseLiteral(_Stream input) {
41 var found = input.read(width);
42 if (found != pattern) {
43 throwFormatException(input);
44 }
45 }
46
47 /** Throw a format exception with an error message indicating the position.*/
48 void throwFormatException(_Stream stream) {
49 throw new FormatException("Trying to read $this from ${stream.contents} "
50 "at position ${stream.index}");
51 }
52 }
53
54 /**
55 * Represents a literal field - a sequence of characters that doesn't
56 * change according to the date's data. As such, the implementation
57 * is extremely simple.
58 */
59 class _DateFormatLiteralField extends _DateFormatField {
60
61 _DateFormatLiteralField(pattern, parent): super(pattern, parent);
62
63 parse(_Stream input, _DateBuilder dateFields) {
64 return parseLiteral(input);
65 }
66 }
67
68 /**
69 * Represents a literal field with quoted characters in it. This is
70 * only slightly more complex than a _DateFormatLiteralField.
71 */
72 class _DateFormatQuotedField extends _DateFormatField {
73
74 String _fullPattern;
75
76 String fullPattern() => _fullPattern;
77
78 _DateFormatQuotedField(pattern, parent): super(pattern, parent) {
79 _fullPattern = pattern;
80 patchQuotes();
81 }
82
83 parse(_Stream input, _DateBuilder dateFields) {
84 return parseLiteral(input);
85 }
86
87 void patchQuotes() {
88 if (pattern == "''") {
89 pattern = "'";
90 } else {
91 pattern = pattern.substring(1, pattern.length - 1);
92 var twoEscapedQuotes = new RegExp(@"''");
93 pattern = pattern.replaceAll(twoEscapedQuotes, "'");
94 }
95 }
96 }
97
98 /*
99 * Represents a field in the pattern that formats some aspect of the
100 * date. Consists primarily of a switch on the particular pattern characters
101 * to determine what to do.
102 */
103 class _DateFormatPatternField extends _DateFormatField {
104
105 _DateFormatPatternField(pattern, parent): super(pattern, parent);
106
107 /** Format date according to our specification and return the result. */
108 String format(Date date) {
109 return formatField(date);
110 }
111
112 /**
113 * Parse the date according to our specification and put the result
114 * into the correct place in dateFields.
115 */
116 void parse(_Stream input, _DateBuilder dateFields) {
117 parseField(input, dateFields);
118 }
119
120 /**
121 * Parse a field representing part of a date pattern. Note that we do not
122 * return a value, but rather build up the result in [builder].
123 */
124 void parseField(_Stream input, _DateBuilder builder) {
125 try {
126 switch(pattern[0]) {
127 case 'a': parseAmPm(input, builder); break;
128 case 'c': parseStandaloneDay(input); break;
129 case 'd': handleNumericField(input, builder.setDay); break; // day
130 case 'E': parseDayOfWeek(input); break;
131 case 'G': break; // era
132 case 'h': parse1To12Hours(input, builder); break;
133 case 'H': handleNumericField(input, builder.setHour); break; // hour 0-23
134 case 'K': handleNumericField(input, builder.setHour); break; //hour 0-11
135 case 'k': handleNumericField(input, builder.setHour,-1); break; //hr 1-24
136 case 'L': parseStandaloneMonth(input, builder); break;
137 case 'M': parseMonth(input, builder); break;
138 case 'm': handleNumericField(input, builder.setMinute); break; // minutes
139 case 'Q': break; // quarter
140 case 'S': handleNumericField(input, builder.setFractionalSecond); break;
141 case 's': handleNumericField(input, builder.setSecond); break;
142 case 'v': break; // time zone id
143 case 'y': handleNumericField(input, builder.setYear); break;
144 case 'z': break; // time zone
145 case 'Z': break; // time zone RFC
146 default: return;
147 }
148 } catch (var e) { throwFormatException(input); }
149 }
150
151 /** Formatting logic if we are of type FIELD */
152 String formatField(Date date) {
153 switch (pattern[0]) {
154 case 'a': return formatAmPm(date);
155 case 'c': return formatStandaloneDay(date);
156 case 'd': return formatDayOfMonth(date);
157 case 'E': return formatDayOfWeek(date);
158 case 'G': return formatEra(date);
159 case 'h': return format1To12Hours(date);
160 case 'H': return format0To23Hours(date);
161 case 'K': return format0To11Hours(date);
162 case 'k': return format24Hours(date);
163 case 'L': return formatStandaloneMonth(date);
164 case 'M': return formatMonth(date);
165 case 'm': return formatMinutes(date);
166 case 'Q': return formatQuarter(date);
167 case 'S': return formatFractionalSeconds(date);
168 case 's': return formatSeconds(date);
169 case 'v': return formatTimeZoneId(date);
170 case 'y': return formatYear(date);
171 case 'z': return formatTimeZone(date);
172 case 'Z': return formatTimeZoneRFC(date);
173 default: return '';
174 }
175 }
176
177 /** Return the symbols for our current locale. */
178 DateSymbols get symbols() => dateTimeSymbols[parent.locale];
179
180 formatEra(Date date) {
181 var era = date.year > 0 ? 1 : 0;
182 return width >= 4 ? symbols.ERANAMES[era] :
183 symbols.ERAS[era];
184 }
185
186 formatYear(Date date) {
187 // TODO(alanknight): Proper handling of years <= 0
188 var year = date.year;
189 if (year < 0) {
190 year = -year;
191 }
192 return width == 2 ? padTo(2, year % 100) : year.toString();
193 }
194
195 /**
196 * We are given [input] as a stream from which we want to read a date. We
197 * can't dynamically build up a date, so we are given a list [dateFields] of
198 * the constructor arguments and an [position] at which to set it
199 * (year,month,day,hour,minute,second,fractionalSecond)
200 * then after all parsing is done we construct a date from the arguments.
201 * This method handles reading any of the numeric fields. The [offset]
202 * argument allows us to compensate for zero-based versus one-based values.
203 */
204 void handleNumericField(_Stream input, Function setter, [int offset = 0]) {
205 var result = input.nextInteger();
206 setter(result + offset);
207 }
208
209 /**
210 * We are given [input] as a stream from which we want to read a date. We
211 * can't dynamically build up a date, so we are given a list [dateFields] of
212 * the constructor arguments and an [position] at which to set it
213 * (year,month,day,hour,minute,second,fractionalSecond)
214 * then after all parsing is done we construct a date from the arguments.
215 * This method handles reading any of string fields from an enumerated set.
216 */
217 int parseEnumeratedString(_Stream input, List possibilities) {
218 var results = new _Stream(possibilities).findIndexes(
219 (each) => input.peek(each.length) == each);
220 if (results.isEmpty()) throwFormatException(input);
221 results.sort(
222 (a, b) => possibilities[a].length.compareTo(possibilities[b].length));
223 var longestResult = results.last();
224 input.read(possibilities[longestResult].length);
225 return longestResult;
226 }
227
228 String formatMonth(Date date) {
229 switch (width) {
230 case 5: return symbols.NARROWMONTHS[date.month-1];
231 case 4: return symbols.MONTHS[date.month-1];
232 case 3: return symbols.SHORTMONTHS[date.month-1];
233 default:
234 return padTo(width, date.month);
235 }
236 }
237
238 void parseMonth(input, dateFields) {
239 var possibilities;
240 switch(width) {
241 case 5: possibilities = symbols.NARROWMONTHS; break;
242 case 4: possibilities = symbols.MONTHS; break;
243 case 3: possibilities = symbols.SHORTMONTHS; break;
244 default: return handleNumericField(input, dateFields.setMonth);
245 }
246 dateFields.month = parseEnumeratedString(input, possibilities) + 1;
247 }
248
249 String format24Hours(Date date) {
250 return padTo(width, date.hour);
251 }
252
253 String formatFractionalSeconds(Date date) {
254 // Always print at least 3 digits. If the width is greater, append 0s
255 var basic = padTo(3, date.millisecond);
256 if (width - 3 > 0) {
257 var extra = padTo(width - 3, 0);
258 return basic.concat(extra);
259 } else {
260 return basic;
261 }
262 }
263
264 String formatAmPm(Date date) {
265 var hours = date.hour;
266 var index = (date.hour >= 12) && (date.hour < 24) ? 1 : 0;
267 var ampm = symbols.AMPMS;
268 return ampm[index];
269 }
270
271 void parseAmPm(input, dateFields) {
272 // If we see a "PM" note it in an extra field.
273 var ampm = parseEnumeratedString(input, symbols.AMPMS);
274 if (ampm == 1) dateFields.pm = true;
275 }
276
277 String format1To12Hours(Date date) {
278 var hours = date.hour;
279 if (date.hour > 12) hours = hours - 12;
280 if (hours == 0) hours = 12;
281 return padTo(width, hours);
282 }
283
284 void parse1To12Hours(_Stream input, _DateBuilder dateFields) {
285 handleNumericField(input, dateFields.setHour);
286 if (dateFields.hour == 12) dateFields.hour = 0;
287 }
288
289 String format0To11Hours(Date date) {
290 return padTo(width, date.hour % 12);
291 }
292
293 String format0To23Hours(Date date) {
294 return padTo(width, date.hour);
295 }
296
297 String formatStandaloneDay(Date date) {
298 switch (width) {
299 case 5: return symbols.STANDALONENARROWWEEKDAYS[date.weekday % 7];
300 case 4: return symbols.STANDALONEWEEKDAYS[date.weekday % 7];
301 case 3: return symbols.STANDALONESHORTWEEKDAYS[date.weekday % 7];
302 default:
303 return padTo(1, date.day);
304 }
305 }
306
307 void parseStandaloneDay(_Stream input) {
308 // This is ignored, but we still have to skip over it the correct amount.
309 var possibilities;
310 switch(width) {
311 case 5: possibilities = symbols.STANDALONENARROWWEEKDAYS; break;
312 case 4: possibilities = symbols.STANDALONEWEEKDAYS; break;
313 case 3: possibilities = symbols.STANDALONESHORTWEEKDAYS; break;
314 default: return handleNumericField(input, (x)=>x);
315 }
316 parseEnumeratedString(input, possibilities);
317 }
318
319 String formatStandaloneMonth(Date date) {
320 switch (width) {
321 case 5:
322 return symbols.STANDALONENARROWMONTHS[date.month-1];
323 case 4:
324 return symbols.STANDALONEMONTHS[date.month-1];
325 case 3:
326 return symbols.STANDALONESHORTMONTHS[date.month-1];
327 default:
328 return padTo(width, date.month);
329 }
330 }
331
332 void parseStandaloneMonth(input, dateFields) {
333 var possibilities;
334 switch(width) {
335 case 5: possibilities = symbols.STANDALONENARROWMONTHS; break;
336 case 4: possibilities = symbols.STANDALONEMONTHS; break;
337 case 3: possibilities = symbols.STANDALONESHORTMONTHS; break;
338 default: return handleNumericField(input, dateFields.setMonth);
339 }
340 dateFields.month = parseEnumeratedString(input, possibilities) + 1;
341 }
342
343 String formatQuarter(Date date) {
344 var quarter = (date.month / 3).truncate().toInt();
345 if (width < 4) {
346 return symbols.SHORTQUARTERS[quarter];
347 } else {
348 return symbols.QUARTERS[quarter];
349 }
350 }
351 String formatDayOfMonth(Date date) {
352 return padTo(width, date.day);
353 }
354
355 String formatDayOfWeek(Date date) {
356 // Note that Dart's weekday returns 1 for Monday and 7 for Sunday.
357 return (width >= 4 ? symbols.WEEKDAYS :
358 symbols.SHORTWEEKDAYS)[(date.weekday) % 7];
359 }
360
361 void parseDayOfWeek(_Stream input) {
362 // This is IGNORED, but we still have to skip over it the correct amount.
363 var possibilities = width >= 4 ? symbols.WEEKDAYS : symbols.SHORTWEEKDAYS;
364 parseEnumeratedString(input, possibilities);
365 }
366
367 String formatMinutes(Date date) {
368 return padTo(width, date.minute);
369 }
370
371 String formatSeconds(Date date) {
372 return padTo(width, date.second);
373 }
374
375 String formatTimeZoneId(Date date) {
376 // TODO(alanknight): implement time zone support
377 throw new NotImplementedException();
378 }
379
380 String formatTimeZone(Date date) {
381 throw new NotImplementedException();
382 }
383
384 String formatTimeZoneRFC(Date date) {
385 throw new NotImplementedException();
386 }
387
388 /**
389 * Return a string representation of the object padded to the left with
390 * zeros. Primarily useful for numbers.
391 */
392 String padTo(int width, Object toBePrinted) {
393 var basicString = toBePrinted.toString();
394 if (basicString.length >= width) return basicString;
395 var buffer = new StringBuffer();
396 for (var i = 0; i < width - basicString.length; i++) {
397 buffer.add('0');
398 }
399 buffer.add(basicString);
400 return buffer.toString();
401 }
402 }
OLDNEW
« no previous file with comments | « lib/i18n/intl_message.dart ('k') | lib/i18n/lib/date_format_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698