//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package mx.formatters { import mx.core.mx_internal; import mx.managers.ISystemManager; import mx.managers.SystemManager; use namespace mx_internal; [ResourceBundle("SharedResources")] [Alternative(replacement="spark.formatters.DateTimeFormatter", since="4.5")] /** * The DateFormatter class uses a format String to return a formatted date and time String * from an input String or a Date object. * You can create many variations easily, including international formats. * *
If an error occurs, an empty String is returned and a String describing
* the error is saved to the error
property. The error
* property can have one of the following values:
"Invalid value"
means a value that is not a Date object or a
* is not a recognized String representation of a date is
* passed to the format()
method. (An empty argument is allowed.)"Invalid format"
means either the formatString
* property is set to empty (""), or there is less than one pattern letter
* in the formatString
property.The parseDateString()
method uses the mx.formatters.DateBase class
* to define the localized string information required to convert
* a date that is formatted as a String into a Date object.
You use the <mx:DateFormatter>
tag
* to render date and time Strings from a Date object.
The <mx:DateFormatter>
tag
* inherits all of the tag attributes of its superclass,
* and adds the following tag attributes:
* <mx:DateFormatter * formatString="Y|M|D|A|E|H|J|K|L|N|S|Q" * /> ** * @includeExample examples/DateFormatterExample.mxml * * @see mx.formatters.DateBase * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public class DateFormatter extends Formatter { include "../core/Version.as"; //-------------------------------------------------------------------------- // // Class constants // //-------------------------------------------------------------------------- /** * @private */ private static const VALID_PATTERN_CHARS:String = "Y,M,D,A,E,H,J,K,L,N,S,Q"; //-------------------------------------------------------------------------- // // Class methods // //-------------------------------------------------------------------------- /** * Converts a date that is formatted as a String into a Date object. * Month and day names must match the names in mx.formatters.DateBase. * * The hour value in the String must be between 0 and 23, inclusive. * The minutes and seconds value must be between 0 and 59, inclusive. * The following example uses this method to create a Date object: * *
* var myDate:Date = DateFormatter.parseDateString("2009-12-02 23:45:30");* * @see mx.formatters.DateBase * * @param str Date that is formatted as a String. * * @return Date object. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public static function parseDateString (str:String):Date { if (!str || str == "") return null; var year:int = -1; var mon:int = -1; var day:int = -1; var hour:int = -1; var min:int = -1; var sec:int = -1; var letter:String = ""; var marker:Object = 0; var count:int = 0; var len:int = str.length; // Strip out the Timezone. It is not used by the DateFormatter var timezoneRegEx:RegExp = /(GMT|UTC)((\+|-)\d\d\d\d )?/ig; str = str.replace(timezoneRegEx, ""); while (count < len) { letter = str.charAt(count); count++; // If the letter is a blank space or a comma, // continue to the next character if (letter <= " " || letter == ",") continue; // If the letter is a key punctuation character, // cache it for the next time around. if (letter == "/" || letter == ":" || letter == "+" || letter == "-") { marker = letter; continue; } // Scan for groups of numbers and letters // and match them to Date parameters if ("a" <= letter && letter <= "z" || "A" <= letter && letter <= "Z") { // Scan for groups of letters var word:String = letter; while (count < len) { letter = str.charAt(count); if (!("a" <= letter && letter <= "z" || "A" <= letter && letter <= "Z")) { break; } word += letter; count++; } // Allow for an exact match // or a match to the first 3 letters as a prefix. var n:int = DateBase.defaultStringKey.length; for (var i:int = 0; i < n; i++) { var s:String = String(DateBase.defaultStringKey[i]); if (s.toLowerCase() == word.toLowerCase() || s.toLowerCase().substr(0,3) == word.toLowerCase()) { if (i == 13) { // pm if (hour > 12 || hour < 1) break; // error else if (hour < 12) hour += 12; } else if (i == 12) { // am if (hour > 12 || hour < 1) break; // error else if (hour == 12) hour = 0; } else if (i < 12) { // month if (mon < 0) mon = i; else break; // error } break; } } marker = 0; } else if ("0" <= letter && letter <= "9") { // Scan for groups of numbers var numbers:String = letter; while ("0" <= (letter = str.charAt(count)) && letter <= "9" && count < len) { numbers += letter; count++; } var num:int = int(numbers); // If num is a number greater than 70, assign num to year. if (num >= 70) { if (year != -1) { break; // error } else if (letter <= " " || letter == "," || letter == "." || letter == "/" || letter == "-" || count >= len) { year = num; } else { break; //error } } // If the current letter is a slash or a dash, // assign num to month or day. else if (letter == "/" || letter == "-" || letter == ".") { if (mon < 0) mon = (num - 1); else if (day < 0) day = num; else break; //error } // If the current letter is a colon, // assign num to hour or minute. else if (letter == ":") { if (hour < 0) hour = num; else if (min < 0) min = num; else break; //error } // If hours are defined and minutes are not, // assign num to minutes. else if (hour >= 0 && min < 0) { min = num; } // If minutes are defined and seconds are not, // assign num to seconds. else if (min >= 0 && sec < 0) { sec = num; } // If day is not defined, assign num to day. else if (day < 0) { day = num; } // If month and day are defined and year is not, // assign num to year. else if (year < 0 && mon >= 0 && day >= 0) { year = 2000 + num; } // Otherwise, break the loop else { break; //error } marker = 0 } } if (year < 0 || mon < 0 || mon > 11 || day < 1 || day > 31) return null; // error - needs to be a date // Time is set to 0 if null. if (sec < 0) sec = 0; if (min < 0) min = 0; if (hour < 0) hour = 0; // create a date object and check the validity of the input date // by comparing the result with input values. var newDate:Date = new Date(year, mon, day, hour, min, sec); if (day != newDate.getDate() || mon != newDate.getMonth()) return null; return newDate; } //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function DateFormatter() { super(); } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // formatString //---------------------------------- /** * @private * Storage for the formatString property. */ private var _formatString:String; /** * @private */ private var formatStringOverride:String; [Inspectable(category="General", defaultValue="null")] /** * The mask pattern. * *
You compose a pattern String using specific uppercase letters, * for example: YYYY/MM.
* *The DateFormatter pattern String can contain other text * in addition to pattern letters. * To form a valid pattern String, you only need one pattern letter.
* *The following table describes the valid pattern letters:
* *Pattern letter | Description |
---|---|
Y | * Year. If the number of pattern letters is two, the year is
* truncated to two digits; otherwise, it appears as four digits.
* The year can be zero-padded, as the third example shows in the
* following set of examples:
*
|
*
M | * Month in year. The format depends on the following criteria:
*
|
*
D | *Day in month. While a single-letter pattern string for day is valid,
* you typically use a two-letter pattern string.
*
* Examples: *
|
*
E | *Day in week. The format depends on the following criteria:
*
|
*
A | *am/pm indicator. | *
J | *Hour in day (0-23). | *
H | *Hour in day (1-24). | *
K | *Hour in am/pm (0-11). | *
L | *Hour in am/pm (1-12). | *
N | *Minute in hour.
*
* Examples: *
|
*
S | *Second in minute.
*
* Example: *
|
*
Q | *Millisecond in second
*
* Example: *
|
*
Other text | *You can add other text into the pattern string to further
* format the string. You can use punctuation, numbers,
* and all lowercase letters. You should avoid uppercase letters
* because they may be interpreted as pattern letters.
*
* Example: *
|
*
formatString
property
* determines the format of the output String.
* If value
cannot be formatted, return an empty String
* and write a description of the error to the error
property.
*
* @param value Date to format. This can be a Date object,
* or a date-formatted String such as "Thursday, April 22, 2004".
*
* @return Formatted String. Empty if an error occurs. A description
* of the error condition is written to the error
property.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function format(value:Object):String
{
// Reset any previous errors.
if (error)
error = null;
// If value is null, or empty String just return ""
// but treat it as an error for consistency.
// Users will ignore it anyway.
if (!value || (value is String && value == ""))
{
error = defaultInvalidValueError;
return "";
}
// -- value --
if (value is String)
{
value = DateFormatter.parseDateString(String(value));
if (!value)
{
error = defaultInvalidValueError;
return "";
}
}
else if (!(value is Date))
{
error = defaultInvalidValueError;
return "";
}
// -- format --
var letter:String;
var nTokens:int = 0;
var tokens:String = "";
var n:int = formatString.length;
for (var i:int = 0; i < n; i++)
{
letter = formatString.charAt(i);
if (VALID_PATTERN_CHARS.indexOf(letter) != -1 && letter != ",")
{
nTokens++;
if (tokens.indexOf(letter) == -1)
{
tokens += letter;
}
else
{
if (letter != formatString.charAt(Math.max(i - 1, 0)))
{
error = defaultInvalidFormatError;
return "";
}
}
}
}
if (nTokens < 1)
{
error = defaultInvalidFormatError;
return "";
}
var dataFormatter:StringFormatter = new StringFormatter(
formatString, VALID_PATTERN_CHARS,
DateBase.extractTokenDate);
return dataFormatter.formatValue(value);
}
}
}