Dart API ReferenceintlDateFormat

DateFormat class

DateFormat is for formatting and parsing dates in a locale-sensitive manner. It allows the user to choose from a set of standard date time formats as well as specify a customized pattern under certain locales. Date elements that vary across locales include month name, week name, field order, etc. <!-- TODO(efortuna): Customized pattern system -- suggested by i18n needs feedback on appropriateness. --> We also allow the user to use any customized pattern to parse or format date-time strings under certain locales. Date elements that vary across locales include month name, weekname, field, order, etc.

This library uses the ICU/JDK date/time pattern specification both for complete format specifications and also the abbreviated "skeleton" form which can also adapt to different locales and is preferred where available.

Skeletons: These can be specified either as the ICU constant name or as the skeleton to which it resolves. The supported set of skeletons is as follows

 ICU Name                   Skeleton
 --------                   --------
 DAY                          d
 ABBR_WEEKDAY                 E
 WEEKDAY                      EEEE
 ABBR_STANDALONE_MONTH        LLL
 STANDALONE_MONTH             LLLL
 NUM_MONTH                    M
 NUM_MONTH_DAY                Md
 NUM_MONTH_WEEKDAY_DAY        MEd
 ABBR_MONTH                   MMM
 ABBR_MONTH_DAY               MMMd
 ABBR_MONTH_WEEKDAY_DAY       MMMEd
 MONTH                        MMMM
 MONTH_DAY                    MMMMd
 MONTH_WEEKDAY_DAY            MMMMEEEEd
 ABBR_QUARTER                 QQQ
 QUARTER                      QQQQ
 YEAR                         y
 YEAR_NUM_MONTH               yM
 YEAR_NUM_MONTH_DAY           yMd
 YEAR_NUM_MONTH_WEEKDAY_DAY   yMEd
 YEAR_ABBR_MONTH              yMMM
 YEAR_ABBR_MONTH_DAY          yMMMd
 YEAR_ABBR_MONTH_WEEKDAY_DAY  yMMMEd
 YEAR_MONTH                   yMMMM
 YEAR_MONTH_DAY               yMMMMd
 YEAR_MONTH_WEEKDAY_DAY       yMMMMEEEEd
 YEAR_ABBR_QUARTER            yQQQ
 YEAR_QUARTER                 yQQQQ
 HOUR24                       H
 HOUR24_MINUTE                Hm
 HOUR24_MINUTE_SECOND         Hms
 HOUR                         j
 HOUR_MINUTE                  jm
 HOUR_MINUTE_SECOND           jms
 HOUR_MINUTE_GENERIC_TZ       jmv
 HOUR_MINUTE_TZ               jmz
 HOUR_GENERIC_TZ              jv
 HOUR_TZ                      jz
 MINUTE                       m
 MINUTE_SECOND                ms
 SECOND                       s

Examples Using the US Locale:

 Pattern                           Result
 ----------------                  -------
 new DateFormat.yMd()             -> 07/10/1996
 new DateFormat("yMd")            -> 07/10/1996
 new DateFormat.yMMMMd("en_US")   -> July 10, 1996
 new DateFormat("Hm", "en_US")    -> 12:08 PM
 new DateFormat.yMd().Hm()        -> 07/10/1996 12:08 PM

Explicit Pattern Syntax: Formats can also be specified with a pattern string. The skeleton forms will resolve to explicit patterns of this form, but will also adapt to different patterns in different locales. The following characters are reserved:

Symbol   Meaning                Presentation        Example
------   -------                ------------        -------
G        era designator         (Text)              AD
y        year                   (Number)            1996
M        month in year          (Text & Number)     July & 07
L        standalone month       (Text & Number)     July & 07
d        day in month           (Number)            10
c        standalone day         (Number)            10
h        hour in am/pm (1~12)   (Number)            12
H        hour in day (0~23)     (Number)            0
m        minute in hour         (Number)            30
s        second in minute       (Number)            55
S        fractional second      (Number)            978
E        day of week            (Text)              Tuesday
D        day in year            (Number)            189
a        am/pm marker           (Text)              PM
k        hour in day (1~24)     (Number)            24
K        hour in am/pm (0~11)   (Number)            0
z        time zone              (Text)              Pacific Standard Time
Z        time zone (RFC 822)    (Number)            -0800
v        time zone (generic)    (Text)              Pacific Time
Q        quarter                (Text)              Q3
'        escape for text        (Delimiter)         'Date='
''       single quote           (Literal)           'o''clock'

The count of pattern letters determine the format.

Text: 5 pattern letters--use narrow form for standalone. Otherwise does not apply 4 or more pattern letters--use full form, 3 pattern letters--use short or abbreviated form if one exists less than 3--use numeric form if one exists

Number: the minimum number of digits. Shorter numbers are zero-padded to this amount (e.g. if "m" produces "6", "mm" produces "06"). Year is handled specially; that is, if the count of 'y' is 2, the Year will be truncated to 2 digits. (e.g., if "yyyy" produces "1997", "yy" produces "97".) Unlike other fields, fractional seconds are padded on the right with zero.

(Text & Number): 3 or over, use text, otherwise use number.

Any characters not in the pattern will be treated as quoted text. For instance, characters like ':', '.', ' ', '#' and '@' will appear in the resulting text even though they are not enclosed in single quotes. In our current pattern usage, not all letters have meanings. But those unused letters are strongly discouraged to be used as quoted text without quotes, because we may use other letters as pattern characters in the future.

Examples Using the US Locale:

Format Pattern                     Result
--------------                     -------
"yyyy.MM.dd G 'at' HH:mm:ss vvvv"  1996.07.10 AD at 15:08:56 Pacific Time
"EEE, MMM d, ''yy"                 Wed, July 10, '96
"h:mm a"                           12:08 PM
"hh 'o''clock' a, zzzz"            12 o'clock PM, Pacific Daylight Time
"K:mm a, vvv"                      0:00 PM, PT
"yyyyy.MMMMM.dd GGG hh:mm aaa"     01996.July.10 AD 12:08 PM

When parsing a date string using the abbreviated year pattern ("yy"), DateFormat must interpret the abbreviated year relative to some century. It does this by adjusting dates to be within 80 years before and 20 years after the time the parse function is called. For example, using a pattern of "MM/dd/yy" and a DateTimeParse instance created on Jan 1, 1997, the string "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64" would be interpreted as May 4, 1964. During parsing, only strings consisting of exactly two digits, as defined by {@link java.lang.Character#isDigit(char)}, will be parsed into the default century. Any other numeric string, such as a one digit string, a three or more digit string will be interpreted as its face value.

If the year pattern does not have exactly two 'y' characters, the year is interpreted literally, regardless of the number of digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.

class DateFormat {

  /**
   * Creates a new DateFormat, using the format specified by [newPattern]. For
   * forms that match one of our predefined skeletons, we look up the
   * corresponding pattern in [locale] (or in the default locale if none is
   * specified) and use the resulting full format string. This is the
   * preferred usage, but if [newPattern] does not match one of the skeletons,
   * then it is used as a format directly, but will not be adapted to suit
   * the locale.
   *
   * For example, in an en_US locale, specifying the skeleton
   *     new DateFormat('yMEd');
   * or the explicit
   *     new DateFormat('EEE, M/d/y');
   * would produce the same result, a date of the form
   *     Wed, 6/27/2012
   * The first version would produce a different format string if used in
   * another locale, but the second format would always be the same.
   *
   * If [locale] does not exist in our set of supported locales then an
   * [ArgumentError] is thrown.
   */
  DateFormat([String newPattern, String locale]) {
    // TODO(alanknight): It should be possible to specify multiple skeletons eg
    // date, time, timezone all separately. Adding many or named parameters to
    // the constructor seems awkward, especially with the possibility of
    // confusion with the locale. A "fluent" interface with cascading on an
    // instance might work better? A list of patterns is also possible.
    _locale = Intl.verifiedLocale(locale, localeExists);
    addPattern(newPattern);
  }

  /**
   * Return a string representing [date] formatted according to our locale
   * and internal format.
   */
  String format(Date date) {
    // TODO(efortuna): read optional TimeZone argument (or similar)?
    var result = new StringBuffer();
    _formatFields.forEach((field) => result.add(field.format(date)));
    return result.toString();
  }

  /**
   * Returns a date string indicating how long ago (3 hours, 2 minutes)
   * something has happened or how long in the future something will happen
   * given a [reference] Date relative to the current time.
   */
  String formatDuration(Date reference) {
    return '';
  }

  /**
   * Formats a string indicating how long ago (negative [duration]) or how far
   * in the future (positive [duration]) some time is with respect to a
   * reference [date].
   */
  String formatDurationFrom(Duration duration, Date date) {
    return '';
  }

  /**
   * Given user input, attempt to parse the [inputString] into the anticipated
   * format, treating it as being in the local timezone.
   */
  Date parse(String inputString, [utc = false]) {
    // TODO(alanknight): The Closure code refers to special parsing of numeric
    // values with no delimiters, which we currently don't do. Should we?
    var dateFields = new _DateBuilder();
    if (utc) dateFields.utc=true;
    var stream = new _Stream(inputString);
    _formatFields.forEach(
        (each) => each.parse(stream, dateFields));
    return dateFields.asDate();
  }

  /**
   * Given user input, attempt to parse the [inputString] into the anticipated
   * format, treating it as being in UTC.
   */
  Date parseUTC(String inputString) {
    return parse(inputString, true);
  }

  /**
   * Return the locale code in which we operate, e.g. 'en_US' or 'pt'.
   */
  String get locale => _locale;

  /**
   * Returns a list of all locales for which we have date formatting
   * information.
   */
  static List<String> allLocalesWithSymbols() => dateTimeSymbols.getKeys();

  /**
   * The named constructors for this class are all conveniences for creating
   * instances using one of the known "skeleton" formats, and having code
   * completion support for discovering those formats.
   * So,
   *     new DateFormat.yMd("en_US")
   * is equivalent to
   *     new DateFormat("yMd", "en_US")
   * To create a compound format you can use these constructors in combination
   * with the add_ methods below. e.g.
   *     new DateFormat.yMd().add_Hms();
   * If the optional [locale] is omitted, the format will be created using the
   * default locale in [Intl.systemLocale].
   */
  DateFormat.d([locale]) : this("d", locale);
  DateFormat.E([locale]) : this("E", locale);
  DateFormat.EEEE([locale]) : this("EEEE", locale);
  DateFormat.LLL([locale]) : this("LLL", locale);
  DateFormat.LLLL([locale]) : this("LLLL", locale);
  DateFormat.M([locale]) : this("M", locale);
  DateFormat.Md([locale]) : this("Md", locale);
  DateFormat.MEd([locale]) : this("MEd", locale);
  DateFormat.MMM([locale]) : this("MMM", locale);
  DateFormat.MMMd([locale]) : this("MMMd", locale);
  DateFormat.MMMEd([locale]) : this("MMMEd", locale);
  DateFormat.MMMM([locale]) : this("MMMM", locale);
  DateFormat.MMMMd([locale]) : this("MMMMd", locale);
  DateFormat.MMMMEEEEd([locale]) : this("MMMMEEEEd", locale);
  DateFormat.QQQ([locale]) : this("QQQ", locale);
  DateFormat.QQQQ([locale]) : this("QQQQ", locale);
  DateFormat.y([locale]) : this("y", locale);
  DateFormat.yM([locale]) : this("yM", locale);
  DateFormat.yMd([locale]) : this("yMd", locale);
  DateFormat.yMEd([locale]) : this("yMEd", locale);
  DateFormat.yMMM([locale]) : this("yMMM", locale);
  DateFormat.yMMMd([locale]) : this("yMMMd", locale);
  DateFormat.yMMMEd([locale]) : this("yMMMEd", locale);
  DateFormat.yMMMM([locale]) : this("yMMMM", locale);
  DateFormat.yMMMMd([locale]) : this("yMMMMd", locale);
  DateFormat.yMMMMEEEEd([locale]) : this("yMMMMEEEEd", locale);
  DateFormat.yQQQ([locale]) : this("yQQQ", locale);
  DateFormat.yQQQQ([locale]) : this("yQQQQ", locale);
  DateFormat.H([locale]) : this("H", locale);
  DateFormat.Hm([locale]) : this("Hm", locale);
  DateFormat.Hms([locale]) : this("Hms", locale);
  DateFormat.j([locale]) : this("j", locale);
  DateFormat.jm([locale]) : this("jm", locale);
  DateFormat.jms([locale]) : this("jms", locale);
  DateFormat.jmv([locale]) : this("jmv", locale);
  DateFormat.jmz([locale]) : this("jmz", locale);
  DateFormat.jv([locale]) : this("jv", locale);
  DateFormat.jz([locale]) : this("jz", locale);
  DateFormat.m([locale]) : this("m", locale);
  DateFormat.ms([locale]) : this("ms", locale);
  DateFormat.s([locale]) : this("s", locale);

  /**
   * The "add_*" methods append a particular skeleton to the format, or set
   * it as the only format if none was previously set. These are primarily
   * useful for creating compound formats. For example
   *       new DateFormat.yMd().add_Hms();
   * would create a date format that prints both the date and the time.
   */
  DateFormat add_d() => addPattern("d");
  DateFormat add_E() => addPattern("E");
  DateFormat add_EEEE() => addPattern("EEEE");
  DateFormat add_LLL() => addPattern("LLL");
  DateFormat add_LLLL() => addPattern("LLLL");
  DateFormat add_M() => addPattern("M");
  DateFormat add_Md() => addPattern("Md");
  DateFormat add_MEd() => addPattern("MEd");
  DateFormat add_MMM() => addPattern("MMM");
  DateFormat add_MMMd() => addPattern("MMMd");
  DateFormat add_MMMEd() => addPattern("MMMEd");
  DateFormat add_MMMM() => addPattern("MMMM");
  DateFormat add_MMMMd() => addPattern("MMMMd");
  DateFormat add_MMMMEEEEd() => addPattern("MMMMEEEEd");
  DateFormat add_QQQ() => addPattern("QQQ");
  DateFormat add_QQQQ() => addPattern("QQQQ");
  DateFormat add_y() => addPattern("y");
  DateFormat add_yM() => addPattern("yM");
  DateFormat add_yMd() => addPattern("yMd");
  DateFormat add_yMEd() => addPattern("yMEd");
  DateFormat add_yMMM() => addPattern("yMMM");
  DateFormat add_yMMMd() => addPattern("yMMMd");
  DateFormat add_yMMMEd() => addPattern("yMMMEd");
  DateFormat add_yMMMM() => addPattern("yMMMM");
  DateFormat add_yMMMMd() => addPattern("yMMMMd");
  DateFormat add_yMMMMEEEEd() => addPattern("yMMMMEEEEd");
  DateFormat add_yQQQ() => addPattern("yQQQ");
  DateFormat add_yQQQQ() => addPattern("yQQQQ");
  DateFormat add_H() => addPattern("H");
  DateFormat add_Hm() => addPattern("Hm");
  DateFormat add_Hms() => addPattern("Hms");
  DateFormat add_j() => addPattern("j");
  DateFormat add_jm() => addPattern("jm");
  DateFormat add_jms() => addPattern("jms");
  DateFormat add_jmv() => addPattern("jmv");
  DateFormat add_jmz() => addPattern("jmz");
  DateFormat add_jv() => addPattern("jv");
  DateFormat add_jz() => addPattern("jz");
  DateFormat add_m() => addPattern("m");
  DateFormat add_ms() => addPattern("ms");
  DateFormat add_s() => addPattern("s");

  /**
   * For each of the skeleton formats we also allow the use of the corresponding
   * ICU constant names.
   */
  static const String ABBR_MONTH = 'MMM';
  static const String DAY = 'd';
  static const String ABBR_WEEKDAY = 'E';
  static const String WEEKDAY = 'EEEE';
  static const String ABBR_STANDALONE_MONTH = 'LLL';
  static const String STANDALONE_MONTH = 'LLLL';
  static const String NUM_MONTH = 'M';
  static const String NUM_MONTH_DAY = 'Md';
  static const String NUM_MONTH_WEEKDAY_DAY = 'MEd';
  static const String ABBR_MONTH_DAY = 'MMMd';
  static const String ABBR_MONTH_WEEKDAY_DAY = 'MMMEd';
  static const String MONTH = 'MMMM';
  static const String MONTH_DAY = 'MMMMd';
  static const String MONTH_WEEKDAY_DAY = 'MMMMEEEEd';
  static const String ABBR_QUARTER = 'QQQ';
  static const String QUARTER = 'QQQQ';
  static const String YEAR = 'y';
  static const String YEAR_NUM_MONTH = 'yM';
  static const String YEAR_NUM_MONTH_DAY = 'yMd';
  static const String YEAR_NUM_MONTH_WEEKDAY_DAY = 'yMEd';
  static const String YEAR_ABBR_MONTH = 'yMMM';
  static const String YEAR_ABBR_MONTH_DAY = 'yMMMd';
  static const String YEAR_ABBR_MONTH_WEEKDAY_DAY = 'yMMMEd';
  static const String YEAR_MONTH = 'yMMMM';
  static const String YEAR_MONTH_DAY = 'yMMMMd';
  static const String YEAR_MONTH_WEEKDAY_DAY = 'yMMMMEEEEd';
  static const String YEAR_ABBR_QUARTER = 'yQQQ';
  static const String YEAR_QUARTER = 'yQQQQ';
  static const String HOUR24 = 'H';
  static const String HOUR24_MINUTE = 'Hm';
  static const String HOUR24_MINUTE_SECOND = 'Hms';
  static const String HOUR = 'j';
  static const String HOUR_MINUTE = 'jm';
  static const String HOUR_MINUTE_SECOND = 'jms';
  static const String HOUR_MINUTE_GENERIC_TZ = 'jmv';
  static const String HOUR_MINUTE_TZ = 'jmz';
  static const String HOUR_GENERIC_TZ = 'jv';
  static const String HOUR_TZ = 'jz';
  static const String MINUTE = 'm';
  static const String MINUTE_SECOND = 'ms';
  static const String SECOND = 's';

  /** The locale in which we operate, e.g. 'en_US', or 'pt'. */
  String _locale;

  /**
   * The full template string. This may have been specified directly, or
   * it may have been derived from a skeleton and the locale information
   * on how to interpret that skeleton.
   */
  String _pattern;

  /**
   * We parse the format string into individual [_DateFormatField] objects
   * that are used to do the actual formatting and parsing. Do not use
   * this variable directly, use the getter [_formatFields].
   */
  List<_DateFormatField> _formatFieldsPrivate;

  /**
   * Getter for [_formatFieldsPrivate] that lazily initializes it.
   */
  get _formatFields {
    if (_formatFieldsPrivate == null) {
      if (_pattern == null) _useDefaultPattern();
      _formatFieldsPrivate = parsePattern(_pattern);
    }
    return _formatFieldsPrivate;
  }

  /**
   * We are being asked to do formatting without having set any pattern.
   * Use a default.
   */
  _useDefaultPattern() {
    add_yMMMMd();
    add_jms();
  }

  /**
   * A series of regular expressions used to parse a format string into its
   * component fields.
   */
  static var _matchers = const [
      // Quoted String - anything between single quotes, with escaping
      //   of single quotes by doubling them.
      // e.g. in the pattern "hh 'o''clock'" will match 'o''clock'
      const RegExp("^\'(?:[^\']|\'\')*\'"),
      // Fields - any sequence of 1 or more of the same field characters.
      // e.g. in "hh:mm:ss" will match hh, mm, and ss. But in "hms" would
      // match each letter individually.
      const RegExp(
        "^(?:G+|y+|M+|k+|S+|E+|a+|h+|K+|H+|c+|L+|Q+|d+|m+|s+|v+|z+|Z+)"),
      // Everything else - A sequence that is not quotes or field characters.
      // e.g. in "hh:mm:ss" will match the colons.
      const RegExp("^[^\'GyMkSEahKHcLQdmsvzZ]+")
  ];

  /**
   * Set our pattern, appending it to any existing patterns. Also adds a single
   * space to separate the two.
   */
  _appendPattern(String inputPattern, [String separator = ' ']) {
    if (_pattern == null) {
      _pattern = inputPattern;
    } else {
      _pattern = "$_pattern$separator$inputPattern";
    }
  }

  /**
   * Add [inputPattern] to this instance as a pattern. If there was a previous
   * pattern, then this appends to it, separating the two by [separator].
   * [inputPattern] is first looked up in our list of known skeletons.
   * If it's found there, then use the corresponding pattern for this locale.
   * If it's not, then treat [inputPattern] as an explicit pattern.
   */
  DateFormat addPattern(String inputPattern, [String separator = ' ']) {
    // TODO(alanknight): This is an expensive operation. Caching recently used
    // formats, or possibly introducing an entire "locale" object that would
    // cache patterns for that locale could be a good optimization.
    // If we have already parsed the format fields, reset them.
    _formatFieldsPrivate = null;
    if (inputPattern == null) return this;
    if (!_availableSkeletons.containsKey(inputPattern)) {
      _appendPattern(inputPattern, separator);
    } else {
      _appendPattern(_availableSkeletons[inputPattern], separator);
    }
    return this;
  }

  /** Return the pattern that we use to format dates.*/
  get pattern => _pattern;

  /** Return the skeletons for our current locale. */
  Map get _availableSkeletons {
    return dateTimePatterns[locale];
  }

  /**
   * Set the locale. If the locale can't be found, we also look up
   * based on alternative versions, e.g. if we have no 'en_CA' we will
   * look for 'en' as a fallback. It will also translate en-ca into en_CA.
   * Null is also considered a valid value for [newLocale], indicating
   * to use the default.
   */
  _setLocale(String newLocale) {
    _locale = Intl.verifiedLocale(newLocale, localeExists);
  }

  /**
   * Return true if the locale exists, or if it is null. The null case
   * is interpreted to mean that we use the default locale.
   */
  static bool localeExists(localeName) {
    if (localeName == null) return false;
    return dateTimeSymbols.containsKey(localeName);
  }

  static List get _fieldConstructors => [
      (pattern, parent) => new _DateFormatQuotedField(pattern, parent),
      (pattern, parent) => new _DateFormatPatternField(pattern, parent),
      (pattern, parent) => new _DateFormatLiteralField(pattern, parent)];

  /** Parse the template pattern and return a list of field objects.*/
  List parsePattern(String pattern) {
    if (pattern == null) return null;
    return _reverse(_parsePatternHelper(pattern));
  }

  /** Recursive helper for parsing the template pattern. */
  List _parsePatternHelper(String pattern) {
    if (pattern.isEmpty()) return [];

    var matched = _match(pattern);
    if (matched == null) return [];

    var parsed = _parsePatternHelper(
                      pattern.substring(matched.fullPattern().length));
    parsed.add(matched);
    return parsed;
  }

  /** Find elements in a string that are patterns for specific fields.*/
  _DateFormatField _match(String pattern) {
    for (var i = 0; i < _matchers.length; i++) {
      var regex = _matchers[i];
      var match = regex.firstMatch(pattern);
      if (match != null) {
        return _fieldConstructors[i](match.group(0), this);
      }
    }
  }

  /** Polyfill for missing library function. */
  List _reverse(List list) {
    // TODO(alanknight): Use standardized list reverse when implemented.
    // See Issue 2804.
    var result = new List();
    for (var i = list.length-1; i >= 0; i--) {
      result.addLast(list[i]);
    }
    return result;
  }
}

Static Properties

const String ABBR_MONTH #

For each of the skeleton formats we also allow the use of the corresponding ICU constant names.

static const String ABBR_MONTH = 'MMM';

const String ABBR_MONTH_DAY #

static const String ABBR_MONTH_DAY = 'MMMd';

const String ABBR_MONTH_WEEKDAY_DAY #

static const String ABBR_MONTH_WEEKDAY_DAY = 'MMMEd';

const String ABBR_QUARTER #

static const String ABBR_QUARTER = 'QQQ';

const String ABBR_STANDALONE_MONTH #

static const String ABBR_STANDALONE_MONTH = 'LLL';

const String ABBR_WEEKDAY #

static const String ABBR_WEEKDAY = 'E';

const String DAY #

static const String DAY = 'd';

const String HOUR #

static const String HOUR = 'j';

const String HOUR24 #

static const String HOUR24 = 'H';

const String HOUR24_MINUTE #

static const String HOUR24_MINUTE = 'Hm';

const String HOUR24_MINUTE_SECOND #

static const String HOUR24_MINUTE_SECOND = 'Hms';

const String HOUR_GENERIC_TZ #

static const String HOUR_GENERIC_TZ = 'jv';

const String HOUR_MINUTE #

static const String HOUR_MINUTE = 'jm';

const String HOUR_MINUTE_GENERIC_TZ #

static const String HOUR_MINUTE_GENERIC_TZ = 'jmv';

const String HOUR_MINUTE_SECOND #

static const String HOUR_MINUTE_SECOND = 'jms';

const String HOUR_MINUTE_TZ #

static const String HOUR_MINUTE_TZ = 'jmz';

const String HOUR_TZ #

static const String HOUR_TZ = 'jz';

const String MINUTE #

static const String MINUTE = 'm';

const String MINUTE_SECOND #

static const String MINUTE_SECOND = 'ms';

const String MONTH #

static const String MONTH = 'MMMM';

const String MONTH_DAY #

static const String MONTH_DAY = 'MMMMd';

const String MONTH_WEEKDAY_DAY #

static const String MONTH_WEEKDAY_DAY = 'MMMMEEEEd';

const String NUM_MONTH #

static const String NUM_MONTH = 'M';

const String NUM_MONTH_DAY #

static const String NUM_MONTH_DAY = 'Md';

const String NUM_MONTH_WEEKDAY_DAY #

static const String NUM_MONTH_WEEKDAY_DAY = 'MEd';

const String QUARTER #

static const String QUARTER = 'QQQQ';

const String SECOND #

static const String SECOND = 's';

const String STANDALONE_MONTH #

static const String STANDALONE_MONTH = 'LLLL';

const String WEEKDAY #

static const String WEEKDAY = 'EEEE';

const String YEAR #

static const String YEAR = 'y';

const String YEAR_ABBR_MONTH #

static const String YEAR_ABBR_MONTH = 'yMMM';

const String YEAR_ABBR_MONTH_DAY #

static const String YEAR_ABBR_MONTH_DAY = 'yMMMd';

const String YEAR_ABBR_MONTH_WEEKDAY_DAY #

static const String YEAR_ABBR_MONTH_WEEKDAY_DAY = 'yMMMEd';

const String YEAR_ABBR_QUARTER #

static const String YEAR_ABBR_QUARTER = 'yQQQ';

const String YEAR_MONTH #

static const String YEAR_MONTH = 'yMMMM';

const String YEAR_MONTH_DAY #

static const String YEAR_MONTH_DAY = 'yMMMMd';

const String YEAR_MONTH_WEEKDAY_DAY #

static const String YEAR_MONTH_WEEKDAY_DAY = 'yMMMMEEEEd';

const String YEAR_NUM_MONTH #

static const String YEAR_NUM_MONTH = 'yM';

const String YEAR_NUM_MONTH_DAY #

static const String YEAR_NUM_MONTH_DAY = 'yMd';

const String YEAR_NUM_MONTH_WEEKDAY_DAY #

static const String YEAR_NUM_MONTH_WEEKDAY_DAY = 'yMEd';

const String YEAR_QUARTER #

static const String YEAR_QUARTER = 'yQQQQ';

Static Methods

List<String> allLocalesWithSymbols() #

Returns a list of all locales for which we have date formatting information.

static List<String> allLocalesWithSymbols() => dateTimeSymbols.getKeys();

bool localeExists(localeName) #

Return true if the locale exists, or if it is null. The null case is interpreted to mean that we use the default locale.

static bool localeExists(localeName) {
  if (localeName == null) return false;
  return dateTimeSymbols.containsKey(localeName);
}

Constructors

new DateFormat([String newPattern, String locale]) #

Creates a new DateFormat, using the format specified by newPattern. For forms that match one of our predefined skeletons, we look up the corresponding pattern in locale (or in the default locale if none is specified) and use the resulting full format string. This is the preferred usage, but if newPattern does not match one of the skeletons, then it is used as a format directly, but will not be adapted to suit the locale.

For example, in an en_US locale, specifying the skeleton

new DateFormat('yMEd');

or the explicit

new DateFormat('EEE, M/d/y');

would produce the same result, a date of the form

Wed, 6/27/2012

The first version would produce a different format string if used in another locale, but the second format would always be the same.

If locale does not exist in our set of supported locales then an ArgumentError is thrown.

DateFormat([String newPattern, String locale]) {
  // TODO(alanknight): It should be possible to specify multiple skeletons eg
  // date, time, timezone all separately. Adding many or named parameters to
  // the constructor seems awkward, especially with the possibility of
  // confusion with the locale. A "fluent" interface with cascading on an
  // instance might work better? A list of patterns is also possible.
  _locale = Intl.verifiedLocale(locale, localeExists);
  addPattern(newPattern);
}

new DateFormat.d([locale]) #

The named constructors for this class are all conveniences for creating instances using one of the known "skeleton" formats, and having code completion support for discovering those formats. So,

new DateFormat.yMd("en_US")

is equivalent to

new DateFormat("yMd", "en_US")

To create a compound format you can use these constructors in combination with the add_ methods below. e.g.

new DateFormat.yMd().add_Hms();

If the optional locale is omitted, the format will be created using the default locale in Intl.systemLocale.

DateFormat.d([locale]) : this("d", locale);

new DateFormat.E([locale]) #

DateFormat.E([locale]) : this("E", locale);

new DateFormat.EEEE([locale]) #

DateFormat.EEEE([locale]) : this("EEEE", locale);

new DateFormat.H([locale]) #

DateFormat.H([locale]) : this("H", locale);

new DateFormat.Hm([locale]) #

DateFormat.Hm([locale]) : this("Hm", locale);

new DateFormat.Hms([locale]) #

DateFormat.Hms([locale]) : this("Hms", locale);

new DateFormat.j([locale]) #

DateFormat.j([locale]) : this("j", locale);

new DateFormat.jm([locale]) #

DateFormat.jm([locale]) : this("jm", locale);

new DateFormat.jms([locale]) #

DateFormat.jms([locale]) : this("jms", locale);

new DateFormat.jmv([locale]) #

DateFormat.jmv([locale]) : this("jmv", locale);

new DateFormat.jmz([locale]) #

DateFormat.jmz([locale]) : this("jmz", locale);

new DateFormat.jv([locale]) #

DateFormat.jv([locale]) : this("jv", locale);

new DateFormat.jz([locale]) #

DateFormat.jz([locale]) : this("jz", locale);

new DateFormat.LLL([locale]) #

DateFormat.LLL([locale]) : this("LLL", locale);

new DateFormat.LLLL([locale]) #

DateFormat.LLLL([locale]) : this("LLLL", locale);

new DateFormat.M([locale]) #

DateFormat.M([locale]) : this("M", locale);

new DateFormat.m([locale]) #

DateFormat.m([locale]) : this("m", locale);

new DateFormat.Md([locale]) #

DateFormat.Md([locale]) : this("Md", locale);

new DateFormat.MEd([locale]) #

DateFormat.MEd([locale]) : this("MEd", locale);

new DateFormat.MMM([locale]) #

DateFormat.MMM([locale]) : this("MMM", locale);

new DateFormat.MMMd([locale]) #

DateFormat.MMMd([locale]) : this("MMMd", locale);

new DateFormat.MMMEd([locale]) #

DateFormat.MMMEd([locale]) : this("MMMEd", locale);

new DateFormat.MMMM([locale]) #

DateFormat.MMMM([locale]) : this("MMMM", locale);

new DateFormat.MMMMd([locale]) #

DateFormat.MMMMd([locale]) : this("MMMMd", locale);

new DateFormat.MMMMEEEEd([locale]) #

DateFormat.MMMMEEEEd([locale]) : this("MMMMEEEEd", locale);

new DateFormat.ms([locale]) #

DateFormat.ms([locale]) : this("ms", locale);

new DateFormat.QQQ([locale]) #

DateFormat.QQQ([locale]) : this("QQQ", locale);

new DateFormat.QQQQ([locale]) #

DateFormat.QQQQ([locale]) : this("QQQQ", locale);

new DateFormat.s([locale]) #

DateFormat.s([locale]) : this("s", locale);

new DateFormat.y([locale]) #

DateFormat.y([locale]) : this("y", locale);

new DateFormat.yM([locale]) #

DateFormat.yM([locale]) : this("yM", locale);

new DateFormat.yMd([locale]) #

DateFormat.yMd([locale]) : this("yMd", locale);

new DateFormat.yMEd([locale]) #

DateFormat.yMEd([locale]) : this("yMEd", locale);

new DateFormat.yMMM([locale]) #

DateFormat.yMMM([locale]) : this("yMMM", locale);

new DateFormat.yMMMd([locale]) #

DateFormat.yMMMd([locale]) : this("yMMMd", locale);

new DateFormat.yMMMEd([locale]) #

DateFormat.yMMMEd([locale]) : this("yMMMEd", locale);

new DateFormat.yMMMM([locale]) #

DateFormat.yMMMM([locale]) : this("yMMMM", locale);

new DateFormat.yMMMMd([locale]) #

DateFormat.yMMMMd([locale]) : this("yMMMMd", locale);

new DateFormat.yMMMMEEEEd([locale]) #

DateFormat.yMMMMEEEEd([locale]) : this("yMMMMEEEEd", locale);

new DateFormat.yQQQ([locale]) #

DateFormat.yQQQ([locale]) : this("yQQQ", locale);

new DateFormat.yQQQQ([locale]) #

DateFormat.yQQQQ([locale]) : this("yQQQQ", locale);

Properties

final String locale #

Return the locale code in which we operate, e.g. 'en_US' or 'pt'.

String get locale => _locale;

final pattern #

Return the pattern that we use to format dates.

get pattern => _pattern;

Methods

DateFormat add_d() #

The "add_*" methods append a particular skeleton to the format, or set it as the only format if none was previously set. These are primarily useful for creating compound formats. For example

  new DateFormat.yMd().add_Hms();

would create a date format that prints both the date and the time.

DateFormat add_d() => addPattern("d");

DateFormat add_E() #

DateFormat add_E() => addPattern("E");

DateFormat add_EEEE() #

DateFormat add_EEEE() => addPattern("EEEE");

DateFormat add_H() #

DateFormat add_H() => addPattern("H");

DateFormat add_Hm() #

DateFormat add_Hm() => addPattern("Hm");

DateFormat add_Hms() #

DateFormat add_Hms() => addPattern("Hms");

DateFormat add_j() #

DateFormat add_j() => addPattern("j");

DateFormat add_jm() #

DateFormat add_jm() => addPattern("jm");

DateFormat add_jms() #

DateFormat add_jms() => addPattern("jms");

DateFormat add_jmv() #

DateFormat add_jmv() => addPattern("jmv");

DateFormat add_jmz() #

DateFormat add_jmz() => addPattern("jmz");

DateFormat add_jv() #

DateFormat add_jv() => addPattern("jv");

DateFormat add_jz() #

DateFormat add_jz() => addPattern("jz");

DateFormat add_LLL() #

DateFormat add_LLL() => addPattern("LLL");

DateFormat add_LLLL() #

DateFormat add_LLLL() => addPattern("LLLL");

DateFormat add_m() #

DateFormat add_m() => addPattern("m");

DateFormat add_M() #

DateFormat add_M() => addPattern("M");

DateFormat add_Md() #

DateFormat add_Md() => addPattern("Md");

DateFormat add_MEd() #

DateFormat add_MEd() => addPattern("MEd");

DateFormat add_MMM() #

DateFormat add_MMM() => addPattern("MMM");

DateFormat add_MMMd() #

DateFormat add_MMMd() => addPattern("MMMd");

DateFormat add_MMMEd() #

DateFormat add_MMMEd() => addPattern("MMMEd");

DateFormat add_MMMM() #

DateFormat add_MMMM() => addPattern("MMMM");

DateFormat add_MMMMd() #

DateFormat add_MMMMd() => addPattern("MMMMd");

DateFormat add_MMMMEEEEd() #

DateFormat add_MMMMEEEEd() => addPattern("MMMMEEEEd");

DateFormat add_ms() #

DateFormat add_ms() => addPattern("ms");

DateFormat add_QQQ() #

DateFormat add_QQQ() => addPattern("QQQ");

DateFormat add_QQQQ() #

DateFormat add_QQQQ() => addPattern("QQQQ");

DateFormat add_s() #

DateFormat add_s() => addPattern("s");

DateFormat add_y() #

DateFormat add_y() => addPattern("y");

DateFormat add_yM() #

DateFormat add_yM() => addPattern("yM");

DateFormat add_yMd() #

DateFormat add_yMd() => addPattern("yMd");

DateFormat add_yMEd() #

DateFormat add_yMEd() => addPattern("yMEd");

DateFormat add_yMMM() #

DateFormat add_yMMM() => addPattern("yMMM");

DateFormat add_yMMMd() #

DateFormat add_yMMMd() => addPattern("yMMMd");

DateFormat add_yMMMEd() #

DateFormat add_yMMMEd() => addPattern("yMMMEd");

DateFormat add_yMMMM() #

DateFormat add_yMMMM() => addPattern("yMMMM");

DateFormat add_yMMMMd() #

DateFormat add_yMMMMd() => addPattern("yMMMMd");

DateFormat add_yMMMMEEEEd() #

DateFormat add_yMMMMEEEEd() => addPattern("yMMMMEEEEd");

DateFormat add_yQQQ() #

DateFormat add_yQQQ() => addPattern("yQQQ");

DateFormat add_yQQQQ() #

DateFormat add_yQQQQ() => addPattern("yQQQQ");

DateFormat addPattern(String inputPattern, [String separator = ' ']) #

Add inputPattern to this instance as a pattern. If there was a previous pattern, then this appends to it, separating the two by separator. inputPattern is first looked up in our list of known skeletons. If it's found there, then use the corresponding pattern for this locale. If it's not, then treat inputPattern as an explicit pattern.

DateFormat addPattern(String inputPattern, [String separator = ' ']) {
  // TODO(alanknight): This is an expensive operation. Caching recently used
  // formats, or possibly introducing an entire "locale" object that would
  // cache patterns for that locale could be a good optimization.
  // If we have already parsed the format fields, reset them.
  _formatFieldsPrivate = null;
  if (inputPattern == null) return this;
  if (!_availableSkeletons.containsKey(inputPattern)) {
    _appendPattern(inputPattern, separator);
  } else {
    _appendPattern(_availableSkeletons[inputPattern], separator);
  }
  return this;
}

String format(Date date) #

Return a string representing date formatted according to our locale and internal format.

String format(Date date) {
  // TODO(efortuna): read optional TimeZone argument (or similar)?
  var result = new StringBuffer();
  _formatFields.forEach((field) => result.add(field.format(date)));
  return result.toString();
}

String formatDuration(Date reference) #

Returns a date string indicating how long ago (3 hours, 2 minutes) something has happened or how long in the future something will happen given a reference Date relative to the current time.

String formatDuration(Date reference) {
  return '';
}

String formatDurationFrom(Duration duration, Date date) #

Formats a string indicating how long ago (negative duration) or how far in the future (positive duration) some time is with respect to a reference date.

String formatDurationFrom(Duration duration, Date date) {
  return '';
}

Date parse(String inputString, [utc = false]) #

Given user input, attempt to parse the inputString into the anticipated format, treating it as being in the local timezone.

Date parse(String inputString, [utc = false]) {
  // TODO(alanknight): The Closure code refers to special parsing of numeric
  // values with no delimiters, which we currently don't do. Should we?
  var dateFields = new _DateBuilder();
  if (utc) dateFields.utc=true;
  var stream = new _Stream(inputString);
  _formatFields.forEach(
      (each) => each.parse(stream, dateFields));
  return dateFields.asDate();
}

List parsePattern(String pattern) #

Parse the template pattern and return a list of field objects.

List parsePattern(String pattern) {
  if (pattern == null) return null;
  return _reverse(_parsePatternHelper(pattern));
}

Date parseUTC(String inputString) #

Given user input, attempt to parse the inputString into the anticipated format, treating it as being in UTC.

Date parseUTC(String inputString) {
  return parse(inputString, true);
}