| Index: intl/lib/src/intl/date_format_field.dart
|
| diff --git a/intl/lib/src/intl/date_format_field.dart b/intl/lib/src/intl/date_format_field.dart
|
| deleted file mode 100644
|
| index 8df11542920e771511d36787c058921cf028d487..0000000000000000000000000000000000000000
|
| --- a/intl/lib/src/intl/date_format_field.dart
|
| +++ /dev/null
|
| @@ -1,660 +0,0 @@
|
| -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -part of intl;
|
| -
|
| -/**
|
| - * This is a private class internal to DateFormat which is used for formatting
|
| - * particular fields in a template. e.g. if the format is hh:mm:ss then the
|
| - * fields would be "hh", ":", "mm", ":", and "ss". Each type of field knows
|
| - * how to format that portion of a date.
|
| - */
|
| -abstract class _DateFormatField {
|
| - /** The format string that defines us, e.g. "hh" */
|
| - String pattern;
|
| -
|
| - /** The DateFormat that we are part of.*/
|
| - DateFormat parent;
|
| -
|
| - _DateFormatField(this.pattern, this.parent);
|
| -
|
| - /**
|
| - * Return the width of [pattern]. Different widths represent different
|
| - * formatting options. See the comment for DateFormat for details.
|
| - */
|
| - int get width => pattern.length;
|
| -
|
| - String fullPattern() => pattern;
|
| -
|
| - String toString() => pattern;
|
| -
|
| - /** Format date according to our specification and return the result. */
|
| - String format(DateTime date) {
|
| - // Default implementation in the superclass, works for both types of
|
| - // literal patterns, and is overridden by _DateFormatPatternField.
|
| - return pattern;
|
| - }
|
| -
|
| - /** Abstract method for subclasses to implementing parsing for their format.*/
|
| - void parse(_Stream input, _DateBuilder dateFields);
|
| -
|
| - /**
|
| - * Abstract method for subclasses to implementing 'loose' parsing for
|
| - * their format, accepting input case-insensitively, and allowing some
|
| - * delimiters to be skipped.
|
| - */
|
| - void parseLoose(_Stream input, _DateBuilder dateFields);
|
| -
|
| - /** Parse a literal field. We just look for the exact input. */
|
| - void parseLiteral(_Stream input) {
|
| - var found = input.read(width);
|
| - if (found != pattern) {
|
| - throwFormatException(input);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Parse a literal field. We accept either an exact match, or an arbitrary
|
| - * amount of whitespace.
|
| - */
|
| - void parseLiteralLoose(_Stream input) {
|
| - var found = input.peek(width);
|
| - if (found == pattern) {
|
| - input.read(width);
|
| - }
|
| - while (!input.atEnd() && input.peek().trim().isEmpty) {
|
| - input.read();
|
| - }
|
| - }
|
| -
|
| - /** Throw a format exception with an error message indicating the position.*/
|
| - void throwFormatException(_Stream stream) {
|
| - throw new FormatException("Trying to read $this from ${stream.contents} "
|
| - "at position ${stream.index}");
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Represents a literal field - a sequence of characters that doesn't
|
| - * change according to the date's data. As such, the implementation
|
| - * is extremely simple.
|
| - */
|
| -class _DateFormatLiteralField extends _DateFormatField {
|
| - _DateFormatLiteralField(pattern, parent) : super(pattern, parent);
|
| -
|
| - parse(_Stream input, _DateBuilder dateFields) {
|
| - parseLiteral(input);
|
| - }
|
| -
|
| - parseLoose(_Stream input, _DateBuilder dateFields) =>
|
| - parseLiteralLoose(input);
|
| -}
|
| -
|
| -/**
|
| - * Represents a literal field with quoted characters in it. This is
|
| - * only slightly more complex than a _DateFormatLiteralField.
|
| - */
|
| -class _DateFormatQuotedField extends _DateFormatField {
|
| - String _fullPattern;
|
| -
|
| - String fullPattern() => _fullPattern;
|
| -
|
| - _DateFormatQuotedField(pattern, parent) : super(pattern, parent) {
|
| - _fullPattern = pattern;
|
| - patchQuotes();
|
| - }
|
| -
|
| - parse(_Stream input, _DateBuilder dateFields) {
|
| - parseLiteral(input);
|
| - }
|
| -
|
| - parseLoose(_Stream input, _DateBuilder dateFields) =>
|
| - parseLiteralLoose(input);
|
| -
|
| - void patchQuotes() {
|
| - if (pattern == "''") {
|
| - pattern = "'";
|
| - } else {
|
| - pattern = pattern.substring(1, pattern.length - 1);
|
| - var twoEscapedQuotes = new RegExp(r"''");
|
| - pattern = pattern.replaceAll(twoEscapedQuotes, "'");
|
| - }
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * A field that parses "loosely", meaning that we'll accept input that is
|
| - * missing delimiters, has upper/lower case mixed up, and might not strictly
|
| - * conform to the pattern, e.g. the pattern calls for Sep we might accept
|
| - * sep, september, sEPTember. Doesn't affect numeric fields.
|
| - */
|
| -class _LoosePatternField extends _DateFormatPatternField {
|
| - _LoosePatternField(String pattern, parent) : super(pattern, parent);
|
| -
|
| - /**
|
| - * Parse from a list of possibilities, but case-insensitively.
|
| - * Assumes that input is lower case.
|
| - */
|
| - int parseEnumeratedString(_Stream input, List possibilities) {
|
| - var lowercasePossibilities =
|
| - possibilities.map((x) => x.toLowerCase()).toList();
|
| - try {
|
| - return super.parseEnumeratedString(input, lowercasePossibilities);
|
| - } on FormatException {
|
| - return -1;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Parse a month name, case-insensitively, and set it in [dateFields].
|
| - * Assumes that [input] is lower case.
|
| - */
|
| - void parseMonth(input, dateFields) {
|
| - if (width <= 2) {
|
| - handleNumericField(input, dateFields.setMonth);
|
| - return;
|
| - }
|
| - var possibilities = [symbols.MONTHS, symbols.SHORTMONTHS];
|
| - for (var monthNames in possibilities) {
|
| - var month = parseEnumeratedString(input, monthNames);
|
| - if (month != -1) {
|
| - dateFields.month = month + 1;
|
| - return;
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Parse a standalone day name, case-insensitively.
|
| - * Assumes that input is lower case. Doesn't do anything
|
| - */
|
| - void parseStandaloneDay(input) {
|
| - // This is ignored, but we still have to skip over it the correct amount.
|
| - if (width <= 2) {
|
| - handleNumericField(input, (x) => x);
|
| - return;
|
| - }
|
| - var possibilities = [
|
| - symbols.STANDALONEWEEKDAYS,
|
| - symbols.STANDALONESHORTWEEKDAYS
|
| - ];
|
| - for (var dayNames in possibilities) {
|
| - var day = parseEnumeratedString(input, dayNames);
|
| - if (day != -1) {
|
| - return;
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Parse a standalone month name, case-insensitively.
|
| - * Assumes that input is lower case. Doesn't do anything
|
| - */
|
| - void parseStandaloneMonth(input, dateFields) {
|
| - if (width <= 2) {
|
| - handleNumericField(input, (x) => x);
|
| - return;
|
| - }
|
| - var possibilities = [
|
| - symbols.STANDALONEMONTHS,
|
| - symbols.STANDALONESHORTMONTHS
|
| - ];
|
| - for (var monthNames in possibilities) {
|
| - var month = parseEnumeratedString(input, monthNames);
|
| - if (month != -1) {
|
| - dateFields.month = month + 1;
|
| - return;
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Parse a day of the week name, case-insensitively.
|
| - * Assumes that input is lower case. Doesn't do anything
|
| - */
|
| - void parseDayOfWeek(_Stream input) {
|
| - // This is IGNORED, but we still have to skip over it the correct amount.
|
| - if (width <= 2) {
|
| - handleNumericField(input, (x) => x);
|
| - return;
|
| - }
|
| - var possibilities = [symbols.WEEKDAYS, symbols.SHORTWEEKDAYS];
|
| - for (var dayNames in possibilities) {
|
| - var day = parseEnumeratedString(input, dayNames);
|
| - if (day != -1) {
|
| - return;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -/*
|
| - * Represents a field in the pattern that formats some aspect of the
|
| - * date. Consists primarily of a switch on the particular pattern characters
|
| - * to determine what to do.
|
| - */
|
| -class _DateFormatPatternField extends _DateFormatField {
|
| - _DateFormatPatternField(pattern, parent) : super(pattern, parent);
|
| -
|
| - /** Format date according to our specification and return the result. */
|
| - String format(DateTime date) {
|
| - return formatField(date);
|
| - }
|
| -
|
| - /**
|
| - * Parse the date according to our specification and put the result
|
| - * into the correct place in dateFields.
|
| - */
|
| - void parse(_Stream input, _DateBuilder dateFields) {
|
| - parseField(input, dateFields);
|
| - }
|
| -
|
| - /**
|
| - * Parse the date according to our specification and put the result
|
| - * into the correct place in dateFields. Allow looser parsing, accepting
|
| - * case-insensitive input and skipped delimiters.
|
| - */
|
| - void parseLoose(_Stream input, _DateBuilder dateFields) {
|
| - new _LoosePatternField(pattern, parent).parse(input, dateFields);
|
| - }
|
| -
|
| - /**
|
| - * Parse a field representing part of a date pattern. Note that we do not
|
| - * return a value, but rather build up the result in [builder].
|
| - */
|
| - void parseField(_Stream input, _DateBuilder builder) {
|
| - try {
|
| - switch (pattern[0]) {
|
| - case 'a':
|
| - parseAmPm(input, builder);
|
| - break;
|
| - case 'c':
|
| - parseStandaloneDay(input);
|
| - break;
|
| - case 'd':
|
| - handleNumericField(input, builder.setDay);
|
| - break; // day
|
| - // Day of year. Setting month=January with any day of the year works
|
| - case 'D':
|
| - handleNumericField(input, builder.setDay);
|
| - break; // dayofyear
|
| - case 'E':
|
| - parseDayOfWeek(input);
|
| - break;
|
| - case 'G':
|
| - break; // era
|
| - case 'h':
|
| - parse1To12Hours(input, builder);
|
| - break;
|
| - case 'H':
|
| - handleNumericField(input, builder.setHour);
|
| - break; // hour 0-23
|
| - case 'K':
|
| - handleNumericField(input, builder.setHour);
|
| - break; //hour 0-11
|
| - case 'k':
|
| - handleNumericField(input, builder.setHour, -1);
|
| - break; //hr 1-24
|
| - case 'L':
|
| - parseStandaloneMonth(input, builder);
|
| - break;
|
| - case 'M':
|
| - parseMonth(input, builder);
|
| - break;
|
| - case 'm':
|
| - handleNumericField(input, builder.setMinute);
|
| - break; // minutes
|
| - case 'Q':
|
| - break; // quarter
|
| - case 'S':
|
| - handleNumericField(input, builder.setFractionalSecond);
|
| - break;
|
| - case 's':
|
| - handleNumericField(input, builder.setSecond);
|
| - break;
|
| - case 'v':
|
| - break; // time zone id
|
| - case 'y':
|
| - handleNumericField(input, builder.setYear);
|
| - break;
|
| - case 'z':
|
| - break; // time zone
|
| - case 'Z':
|
| - break; // time zone RFC
|
| - default:
|
| - return;
|
| - }
|
| - } catch (e) {
|
| - throwFormatException(input);
|
| - }
|
| - }
|
| -
|
| - /** Formatting logic if we are of type FIELD */
|
| - String formatField(DateTime date) {
|
| - switch (pattern[0]) {
|
| - case 'a':
|
| - return formatAmPm(date);
|
| - case 'c':
|
| - return formatStandaloneDay(date);
|
| - case 'd':
|
| - return formatDayOfMonth(date);
|
| - case 'D':
|
| - return formatDayOfYear(date);
|
| - case 'E':
|
| - return formatDayOfWeek(date);
|
| - case 'G':
|
| - return formatEra(date);
|
| - case 'h':
|
| - return format1To12Hours(date);
|
| - case 'H':
|
| - return format0To23Hours(date);
|
| - case 'K':
|
| - return format0To11Hours(date);
|
| - case 'k':
|
| - return format24Hours(date);
|
| - case 'L':
|
| - return formatStandaloneMonth(date);
|
| - case 'M':
|
| - return formatMonth(date);
|
| - case 'm':
|
| - return formatMinutes(date);
|
| - case 'Q':
|
| - return formatQuarter(date);
|
| - case 'S':
|
| - return formatFractionalSeconds(date);
|
| - case 's':
|
| - return formatSeconds(date);
|
| - case 'v':
|
| - return formatTimeZoneId(date);
|
| - case 'y':
|
| - return formatYear(date);
|
| - case 'z':
|
| - return formatTimeZone(date);
|
| - case 'Z':
|
| - return formatTimeZoneRFC(date);
|
| - default:
|
| - return '';
|
| - }
|
| - }
|
| -
|
| - /** Return the symbols for our current locale. */
|
| - DateSymbols get symbols => dateTimeSymbols[parent.locale];
|
| -
|
| - formatEra(DateTime date) {
|
| - var era = date.year > 0 ? 1 : 0;
|
| - return width >= 4 ? symbols.ERANAMES[era] : symbols.ERAS[era];
|
| - }
|
| -
|
| - formatYear(DateTime date) {
|
| - // TODO(alanknight): Proper handling of years <= 0
|
| - var year = date.year;
|
| - if (year < 0) {
|
| - year = -year;
|
| - }
|
| - return width == 2 ? padTo(2, year % 100) : padTo(width, year);
|
| - }
|
| -
|
| - /**
|
| - * We are given [input] as a stream from which we want to read a date. We
|
| - * can't dynamically build up a date, so we are given a list [dateFields] of
|
| - * the constructor arguments and an [position] at which to set it
|
| - * (year,month,day,hour,minute,second,fractionalSecond)
|
| - * then after all parsing is done we construct a date from the arguments.
|
| - * This method handles reading any of the numeric fields. The [offset]
|
| - * argument allows us to compensate for zero-based versus one-based values.
|
| - */
|
| - void handleNumericField(_Stream input, Function setter, [int offset = 0]) {
|
| - var result = input.nextInteger();
|
| - if (result == null) throwFormatException(input);
|
| - setter(result + offset);
|
| - }
|
| -
|
| - /**
|
| - * We are given [input] as a stream from which we want to read a date. We
|
| - * can't dynamically build up a date, so we are given a list [dateFields] of
|
| - * the constructor arguments and an [position] at which to set it
|
| - * (year,month,day,hour,minute,second,fractionalSecond)
|
| - * then after all parsing is done we construct a date from the arguments.
|
| - * This method handles reading any of string fields from an enumerated set.
|
| - */
|
| - int parseEnumeratedString(_Stream input, List possibilities) {
|
| - var results = new _Stream(possibilities)
|
| - .findIndexes((each) => input.peek(each.length) == each);
|
| - if (results.isEmpty) throwFormatException(input);
|
| - results.sort(
|
| - (a, b) => possibilities[a].length.compareTo(possibilities[b].length));
|
| - var longestResult = results.last;
|
| - input.read(possibilities[longestResult].length);
|
| - return longestResult;
|
| - }
|
| -
|
| - String formatMonth(DateTime date) {
|
| - switch (width) {
|
| - case 5:
|
| - return symbols.NARROWMONTHS[date.month - 1];
|
| - case 4:
|
| - return symbols.MONTHS[date.month - 1];
|
| - case 3:
|
| - return symbols.SHORTMONTHS[date.month - 1];
|
| - default:
|
| - return padTo(width, date.month);
|
| - }
|
| - }
|
| -
|
| - void parseMonth(input, dateFields) {
|
| - var possibilities;
|
| - switch (width) {
|
| - case 5:
|
| - possibilities = symbols.NARROWMONTHS;
|
| - break;
|
| - case 4:
|
| - possibilities = symbols.MONTHS;
|
| - break;
|
| - case 3:
|
| - possibilities = symbols.SHORTMONTHS;
|
| - break;
|
| - default:
|
| - return handleNumericField(input, dateFields.setMonth);
|
| - }
|
| - dateFields.month = parseEnumeratedString(input, possibilities) + 1;
|
| - }
|
| -
|
| - String format24Hours(DateTime date) {
|
| - return padTo(width, date.hour);
|
| - }
|
| -
|
| - String formatFractionalSeconds(DateTime date) {
|
| - // Always print at least 3 digits. If the width is greater, append 0s
|
| - var basic = padTo(3, date.millisecond);
|
| - if (width - 3 > 0) {
|
| - var extra = padTo(width - 3, 0);
|
| - return basic + extra;
|
| - } else {
|
| - return basic;
|
| - }
|
| - }
|
| -
|
| - String formatAmPm(DateTime date) {
|
| - var hours = date.hour;
|
| - var index = (date.hour >= 12) && (date.hour < 24) ? 1 : 0;
|
| - var ampm = symbols.AMPMS;
|
| - return ampm[index];
|
| - }
|
| -
|
| - void parseAmPm(input, dateFields) {
|
| - // If we see a "PM" note it in an extra field.
|
| - var ampm = parseEnumeratedString(input, symbols.AMPMS);
|
| - if (ampm == 1) dateFields.pm = true;
|
| - }
|
| -
|
| - String format1To12Hours(DateTime date) {
|
| - var hours = date.hour;
|
| - if (date.hour > 12) hours = hours - 12;
|
| - if (hours == 0) hours = 12;
|
| - return padTo(width, hours);
|
| - }
|
| -
|
| - void parse1To12Hours(_Stream input, _DateBuilder dateFields) {
|
| - handleNumericField(input, dateFields.setHour);
|
| - if (dateFields.hour == 12) dateFields.hour = 0;
|
| - }
|
| -
|
| - String format0To11Hours(DateTime date) {
|
| - return padTo(width, date.hour % 12);
|
| - }
|
| -
|
| - String format0To23Hours(DateTime date) {
|
| - return padTo(width, date.hour);
|
| - }
|
| -
|
| - String formatStandaloneDay(DateTime date) {
|
| - switch (width) {
|
| - case 5:
|
| - return symbols.STANDALONENARROWWEEKDAYS[date.weekday % 7];
|
| - case 4:
|
| - return symbols.STANDALONEWEEKDAYS[date.weekday % 7];
|
| - case 3:
|
| - return symbols.STANDALONESHORTWEEKDAYS[date.weekday % 7];
|
| - default:
|
| - return padTo(1, date.day);
|
| - }
|
| - }
|
| -
|
| - void parseStandaloneDay(_Stream input) {
|
| - // This is ignored, but we still have to skip over it the correct amount.
|
| - var possibilities;
|
| - switch (width) {
|
| - case 5:
|
| - possibilities = symbols.STANDALONENARROWWEEKDAYS;
|
| - break;
|
| - case 4:
|
| - possibilities = symbols.STANDALONEWEEKDAYS;
|
| - break;
|
| - case 3:
|
| - possibilities = symbols.STANDALONESHORTWEEKDAYS;
|
| - break;
|
| - default:
|
| - return handleNumericField(input, (x) => x);
|
| - }
|
| - parseEnumeratedString(input, possibilities);
|
| - }
|
| -
|
| - String formatStandaloneMonth(DateTime date) {
|
| - switch (width) {
|
| - case 5:
|
| - return symbols.STANDALONENARROWMONTHS[date.month - 1];
|
| - case 4:
|
| - return symbols.STANDALONEMONTHS[date.month - 1];
|
| - case 3:
|
| - return symbols.STANDALONESHORTMONTHS[date.month - 1];
|
| - default:
|
| - return padTo(width, date.month);
|
| - }
|
| - }
|
| -
|
| - void parseStandaloneMonth(input, dateFields) {
|
| - var possibilities;
|
| - switch (width) {
|
| - case 5:
|
| - possibilities = symbols.STANDALONENARROWMONTHS;
|
| - break;
|
| - case 4:
|
| - possibilities = symbols.STANDALONEMONTHS;
|
| - break;
|
| - case 3:
|
| - possibilities = symbols.STANDALONESHORTMONTHS;
|
| - break;
|
| - default:
|
| - return handleNumericField(input, dateFields.setMonth);
|
| - }
|
| - dateFields.month = parseEnumeratedString(input, possibilities) + 1;
|
| - }
|
| -
|
| - String formatQuarter(DateTime date) {
|
| - var quarter = ((date.month - 1) / 3).truncate();
|
| - if (width < 4) {
|
| - return symbols.SHORTQUARTERS[quarter];
|
| - } else {
|
| - return symbols.QUARTERS[quarter];
|
| - }
|
| - }
|
| - String formatDayOfMonth(DateTime date) {
|
| - return padTo(width, date.day);
|
| - }
|
| -
|
| - String formatDayOfYear(DateTime date) => padTo(width, dayNumberInYear(date));
|
| -
|
| - /** Return the ordinal day, i.e. the day number in the year. */
|
| - int dayNumberInYear(DateTime date) {
|
| - if (date.month == 1) return date.day;
|
| - if (date.month == 2) return date.day + 31;
|
| - return ordinalDayFromMarchFirst(date) + 59 + (isLeapYear(date) ? 1 : 0);
|
| - }
|
| -
|
| - /**
|
| - * Return the day of the year counting March 1st as 1, after which the
|
| - * number of days per month is constant, so it's easier to calculate.
|
| - * Formula from http://en.wikipedia.org/wiki/Ordinal_date
|
| - */
|
| - int ordinalDayFromMarchFirst(DateTime date) =>
|
| - ((30.6 * date.month) - 91.4).floor() + date.day;
|
| -
|
| - /**
|
| - * Return true if this is a leap year. Rely on [DateTime] to do the
|
| - * underlying calculation, even though it doesn't expose the test to us.
|
| - */
|
| - bool isLeapYear(DateTime date) {
|
| - var feb29 = new DateTime(date.year, 2, 29);
|
| - return feb29.month == 2;
|
| - }
|
| -
|
| - String formatDayOfWeek(DateTime date) {
|
| - // Note that Dart's weekday returns 1 for Monday and 7 for Sunday.
|
| - return (width >= 4
|
| - ? symbols.WEEKDAYS
|
| - : symbols.SHORTWEEKDAYS)[(date.weekday) % 7];
|
| - }
|
| -
|
| - void parseDayOfWeek(_Stream input) {
|
| - // This is IGNORED, but we still have to skip over it the correct amount.
|
| - var possibilities = width >= 4 ? symbols.WEEKDAYS : symbols.SHORTWEEKDAYS;
|
| - parseEnumeratedString(input, possibilities);
|
| - }
|
| -
|
| - String formatMinutes(DateTime date) {
|
| - return padTo(width, date.minute);
|
| - }
|
| -
|
| - String formatSeconds(DateTime date) {
|
| - return padTo(width, date.second);
|
| - }
|
| -
|
| - String formatTimeZoneId(DateTime date) {
|
| - // TODO(alanknight): implement time zone support
|
| - throw new UnimplementedError();
|
| - }
|
| -
|
| - String formatTimeZone(DateTime date) {
|
| - throw new UnimplementedError();
|
| - }
|
| -
|
| - String formatTimeZoneRFC(DateTime date) {
|
| - throw new UnimplementedError();
|
| - }
|
| -
|
| - /**
|
| - * Return a string representation of the object padded to the left with
|
| - * zeros. Primarily useful for numbers.
|
| - */
|
| - String padTo(int width, Object toBePrinted) {
|
| - var basicString = toBePrinted.toString();
|
| - if (basicString.length >= width) return basicString;
|
| - var buffer = new StringBuffer();
|
| - for (var i = 0; i < width - basicString.length; i++) {
|
| - buffer.write('0');
|
| - }
|
| - buffer.write(basicString);
|
| - return buffer.toString();
|
| - }
|
| -}
|
|
|