| OLD | NEW |
| 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 // TODO(efortuna): Customized pattern system -- suggested by i18n needs | 7 // TODO(efortuna): Customized pattern system -- suggested by i18n needs |
| 8 // feedback on appropriateness. | 8 // feedback on appropriateness. |
| 9 /** | 9 /** |
| 10 * DateFormat is for formatting and parsing dates in a locale-sensitive | 10 * DateFormat is for formatting and parsing dates in a locale-sensitive |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 var result = new StringBuffer(); | 230 var result = new StringBuffer(); |
| 231 _formatFields.forEach((field) => result.write(field.format(date))); | 231 _formatFields.forEach((field) => result.write(field.format(date))); |
| 232 return result.toString(); | 232 return result.toString(); |
| 233 } | 233 } |
| 234 | 234 |
| 235 /** | 235 /** |
| 236 * Returns a date string indicating how long ago (3 hours, 2 minutes) | 236 * Returns a date string indicating how long ago (3 hours, 2 minutes) |
| 237 * something has happened or how long in the future something will happen | 237 * something has happened or how long in the future something will happen |
| 238 * given a [reference] DateTime relative to the current time. | 238 * given a [reference] DateTime relative to the current time. |
| 239 */ | 239 */ |
| 240 String formatDuration(DateTime reference) { | 240 String formatDuration(DateTime reference) => ''; |
| 241 return ''; | |
| 242 } | |
| 243 | 241 |
| 244 /** | 242 /** |
| 245 * Formats a string indicating how long ago (negative [duration]) or how far | 243 * Formats a string indicating how long ago (negative [duration]) or how far |
| 246 * in the future (positive [duration]) some time is with respect to a | 244 * in the future (positive [duration]) some time is with respect to a |
| 247 * reference [date]. | 245 * reference [date]. |
| 248 */ | 246 */ |
| 249 String formatDurationFrom(Duration duration, DateTime date) { | 247 String formatDurationFrom(Duration duration, DateTime date) => ''; |
| 250 return ''; | |
| 251 } | |
| 252 | 248 |
| 253 /** | 249 /** |
| 254 * Given user input, attempt to parse the [inputString] into the anticipated | 250 * Given user input, attempt to parse the [inputString] into the anticipated |
| 255 * format, treating it as being in the local timezone. If [inputString] does | 251 * format, treating it as being in the local timezone. If [inputString] does |
| 256 * not match our format, throws a [FormatException]. | 252 * not match our format, throws a [FormatException]. |
| 257 */ | 253 */ |
| 258 DateTime parse(String inputString, [utc = false]) { | 254 DateTime parse(String inputString, [utc = false]) { |
| 259 // TODO(alanknight): The Closure code refers to special parsing of numeric | 255 // TODO(alanknight): The Closure code refers to special parsing of numeric |
| 260 // values with no delimiters, which we currently don't do. Should we? | 256 // values with no delimiters, which we currently don't do. Should we? |
| 261 var dateFields = new _DateBuilder(); | 257 var dateFields = new _DateBuilder(); |
| 262 if (utc) dateFields.utc=true; | 258 if (utc) dateFields.utc = true; |
| 263 var stream = new _Stream(inputString); | 259 var stream = new _Stream(inputString); |
| 264 _formatFields.forEach( | 260 _formatFields.forEach((f) => f.parse(stream, dateFields)); |
| 265 (each) => each.parse(stream, dateFields)); | |
| 266 return dateFields.asDate(); | 261 return dateFields.asDate(); |
| 267 } | 262 } |
| 268 | 263 |
| 269 /** | 264 /** |
| 270 * Given user input, attempt to parse the [inputString] into the anticipated | 265 * Given user input, attempt to parse the [inputString] into the anticipated |
| 271 * format, treating it as being in UTC. | 266 * format, treating it as being in UTC. |
| 272 */ | 267 */ |
| 273 DateTime parseUTC(String inputString) { | 268 DateTime parseUTC(String inputString) => parse(inputString, true); |
| 274 return parse(inputString, true); | |
| 275 } | |
| 276 | 269 |
| 277 /** | 270 /** |
| 278 * Return the locale code in which we operate, e.g. 'en_US' or 'pt'. | 271 * Return the locale code in which we operate, e.g. 'en_US' or 'pt'. |
| 279 */ | 272 */ |
| 280 String get locale => _locale; | 273 String get locale => _locale; |
| 281 | 274 |
| 282 /** | 275 /** |
| 283 * Returns a list of all locales for which we have date formatting | 276 * Returns a list of all locales for which we have date formatting |
| 284 * information. | 277 * information. |
| 285 */ | 278 */ |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 // Everything else - A sequence that is not quotes or field characters. | 483 // Everything else - A sequence that is not quotes or field characters. |
| 491 // e.g. in "hh:mm:ss" will match the colons. | 484 // e.g. in "hh:mm:ss" will match the colons. |
| 492 new RegExp("^[^\'GyMkSEahKHcLQdDmsvzZ]+") | 485 new RegExp("^[^\'GyMkSEahKHcLQdDmsvzZ]+") |
| 493 ]; | 486 ]; |
| 494 | 487 |
| 495 /** | 488 /** |
| 496 * Set our pattern, appending it to any existing patterns. Also adds a single | 489 * Set our pattern, appending it to any existing patterns. Also adds a single |
| 497 * space to separate the two. | 490 * space to separate the two. |
| 498 */ | 491 */ |
| 499 _appendPattern(String inputPattern, [String separator = ' ']) { | 492 _appendPattern(String inputPattern, [String separator = ' ']) { |
| 500 if (_pattern == null) { | 493 _pattern = _pattern == null ? |
| 501 _pattern = inputPattern; | 494 inputPattern : |
| 502 } else { | 495 "$_pattern$separator$inputPattern"; |
| 503 _pattern = "$_pattern$separator$inputPattern"; | |
| 504 } | |
| 505 } | 496 } |
| 506 | 497 |
| 507 /** | 498 /** |
| 508 * Add [inputPattern] to this instance as a pattern. If there was a previous | 499 * Add [inputPattern] to this instance as a pattern. If there was a previous |
| 509 * pattern, then this appends to it, separating the two by [separator]. | 500 * pattern, then this appends to it, separating the two by [separator]. |
| 510 * [inputPattern] is first looked up in our list of known skeletons. | 501 * [inputPattern] is first looked up in our list of known skeletons. |
| 511 * If it's found there, then use the corresponding pattern for this locale. | 502 * If it's found there, then use the corresponding pattern for this locale. |
| 512 * If it's not, then treat [inputPattern] as an explicit pattern. | 503 * If it's not, then treat [inputPattern] as an explicit pattern. |
| 513 */ | 504 */ |
| 514 DateFormat addPattern(String inputPattern, [String separator = ' ']) { | 505 DateFormat addPattern(String inputPattern, [String separator = ' ']) { |
| 515 // TODO(alanknight): This is an expensive operation. Caching recently used | 506 // TODO(alanknight): This is an expensive operation. Caching recently used |
| 516 // formats, or possibly introducing an entire "locale" object that would | 507 // formats, or possibly introducing an entire "locale" object that would |
| 517 // cache patterns for that locale could be a good optimization. | 508 // cache patterns for that locale could be a good optimization. |
| 518 // If we have already parsed the format fields, reset them. | 509 // If we have already parsed the format fields, reset them. |
| 519 _formatFieldsPrivate = null; | 510 _formatFieldsPrivate = null; |
| 520 if (inputPattern == null) return this; | 511 if (inputPattern == null) return this; |
| 521 if (!_availableSkeletons.containsKey(inputPattern)) { | 512 if (!_availableSkeletons.containsKey(inputPattern)) { |
| 522 _appendPattern(inputPattern, separator); | 513 _appendPattern(inputPattern, separator); |
| 523 } else { | 514 } else { |
| 524 _appendPattern(_availableSkeletons[inputPattern], separator); | 515 _appendPattern(_availableSkeletons[inputPattern], separator); |
| 525 } | 516 } |
| 526 return this; | 517 return this; |
| 527 } | 518 } |
| 528 | 519 |
| 529 /** Return the pattern that we use to format dates.*/ | 520 /** Return the pattern that we use to format dates.*/ |
| 530 get pattern => _pattern; | 521 get pattern => _pattern; |
| 531 | 522 |
| 532 /** Return the skeletons for our current locale. */ | 523 /** Return the skeletons for our current locale. */ |
| 533 Map get _availableSkeletons { | 524 Map get _availableSkeletons => dateTimePatterns[locale]; |
| 534 return dateTimePatterns[locale]; | |
| 535 } | |
| 536 | 525 |
| 537 /** | 526 /** |
| 538 * Return the [DateSymbol] information for the locale. This can be useful | 527 * Return the [DateSymbol] information for the locale. This can be useful |
| 539 * to find lists like the names of weekdays or months in a locale, but | 528 * to find lists like the names of weekdays or months in a locale, but |
| 540 * the structure of this data may change, and it's generally better to go | 529 * the structure of this data may change, and it's generally better to go |
| 541 * through the [format] and [parse] APIs. If the locale isn't present, or | 530 * through the [format] and [parse] APIs. If the locale isn't present, or |
| 542 * is uninitialized, returns null; | 531 * is uninitialized, returns null; |
| 543 */ | 532 */ |
| 544 DateSymbols get dateSymbols => dateTimeSymbols[_locale]; | 533 DateSymbols get dateSymbols => dateTimeSymbols[_locale]; |
| 545 | 534 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 575 } | 564 } |
| 576 | 565 |
| 577 /** Recursive helper for parsing the template pattern. */ | 566 /** Recursive helper for parsing the template pattern. */ |
| 578 List _parsePatternHelper(String pattern) { | 567 List _parsePatternHelper(String pattern) { |
| 579 if (pattern.isEmpty) return []; | 568 if (pattern.isEmpty) return []; |
| 580 | 569 |
| 581 var matched = _match(pattern); | 570 var matched = _match(pattern); |
| 582 if (matched == null) return []; | 571 if (matched == null) return []; |
| 583 | 572 |
| 584 var parsed = _parsePatternHelper( | 573 var parsed = _parsePatternHelper( |
| 585 pattern.substring(matched.fullPattern().length)); | 574 pattern.substring(matched.fullPattern().length)); |
| 586 parsed.add(matched); | 575 parsed.add(matched); |
| 587 return parsed; | 576 return parsed; |
| 588 } | 577 } |
| 589 | 578 |
| 590 /** Find elements in a string that are patterns for specific fields.*/ | 579 /** Find elements in a string that are patterns for specific fields.*/ |
| 591 _DateFormatField _match(String pattern) { | 580 _DateFormatField _match(String pattern) { |
| 592 for (var i = 0; i < _matchers.length; i++) { | 581 for (var i = 0; i < _matchers.length; i++) { |
| 593 var regex = _matchers[i]; | 582 var regex = _matchers[i]; |
| 594 var match = regex.firstMatch(pattern); | 583 var match = regex.firstMatch(pattern); |
| 595 if (match != null) { | 584 if (match != null) { |
| 596 return _fieldConstructors[i](match.group(0), this); | 585 return _fieldConstructors[i](match.group(0), this); |
| 597 } | 586 } |
| 598 } | 587 } |
| 599 } | 588 } |
| 600 } | 589 } |
| OLD | NEW |