OLD | NEW |
---|---|
1 /** | 1 /** |
2 * Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 * Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
3 * for details. All rights reserved. Use of this source code is governed by a | 3 * for details. All rights reserved. Use of this source code is governed by a |
4 * BSD-style license that can be found in the LICENSE file. | 4 * BSD-style license that can be found in the LICENSE file. |
5 * | 5 * |
6 * DateFormat is for formatting and parsing dates in a locale-sensitive | 6 * DateFormat is for formatting and parsing dates in a locale-sensitive |
7 * manner. | 7 * manner. |
8 * It allows the user to use any customized pattern to parse or format | 8 * It allows the user to choose from a set of standard date time formats as well |
9 * date-time strings under certain locales. Date elements that vary across | 9 * as specify a customized pattern under certain locales. Date elements that |
10 * locales include month name, weekname, field, order, etc. | 10 * vary across locales include month name, weekname, field, order, etc. |
11 * //TODO(efortuna): Customized pattern system -- needs feedback on | |
12 * // appropriateness. | |
11 * | 13 * |
12 * This library uses the ICU/JDK date/time pattern specification as described | 14 * This library uses the ICU date/time pattern specification as described |
13 * below. | 15 * below. |
14 * | 16 * |
15 * Time Format Syntax: To specify the time format use a time pattern string. | 17 * Time Format Syntax: To specify the time format use a time pattern string. |
16 * In this pattern, following letters are reserved as pattern letters, which | 18 * In this pattern, following letters are reserved as pattern letters, which |
17 * are defined in the following manner: | 19 * are defined in the following manner: |
18 * | 20 * |
19 * Symbol Meaning Presentation Example | 21 * Symbol Meaning Presentation Example |
20 * ------ ------- ------------ ------- | 22 * ------ ------- ------------ ------- |
21 * G era designator (Text) AD | 23 * G era designator (Text) AD |
22 * y# year (Number) 1996 | 24 * y year (Number) 1996 |
23 * M month in year (Text & Number) July & 07 | 25 * M month in year (Text & Number) July & 07 |
24 * d day in month (Number) 10 | 26 * d day in month (Number) 10 |
25 * h hour in am/pm (1~12) (Number) 12 | 27 * h hour in am/pm (1~12) (Number) 12 |
26 * H hour in day (0~23) (Number) 0 | 28 * H hour in day (0~23) (Number) 0 |
27 * m minute in hour (Number) 30 | 29 * m minute in hour (Number) 30 |
28 * s second in minute (Number) 55 | 30 * s second in minute (Number) 55 |
29 * S fractional second (Number) 978 | 31 * S fractional second (Number) 978 |
30 * E day of week (Text) Tuesday | 32 * E day of week (Text) Tuesday |
31 * D day in year (Number) 189 | 33 * D day in year (Number) 189 |
32 * a am/pm marker (Text) PM | 34 * a am/pm marker (Text) PM |
33 * k hour in day (1~24) (Number) 24 | 35 * k hour in day (1~24) (Number) 24 |
34 * K hour in am/pm (0~11) (Number) 0 | 36 * K hour in am/pm (0~11) (Number) 0 |
35 * z time zone (Text) Pacific Standard Time | 37 * z time zone (Text) Pacific Standard Time |
36 * Z time zone (RFC 822) (Number) -0800 | 38 * Z time zone (RFC 822) (Number) -0800 |
37 * v time zone (generic) (Text) Pacific Time | 39 * v time zone (generic) (Text) Pacific Time |
38 * ' escape for text (Delimiter) 'Date=' | |
39 * '' single quote (Literal) 'o''clock' | |
40 * | |
41 * Items marked with '#' work differently than in Java. | |
42 * | 40 * |
43 * The count of pattern letters determine the format. | 41 * The count of pattern letters determine the format. |
44 * (Text): 4 or more pattern letters--use full form, | 42 * (Text): 4 or more pattern letters--use full form, |
45 * less than 4--use short or abbreviated form if one exists. | 43 * less than 4--use short or abbreviated form if one exists. |
46 * In parsing, we will always try long format, then short. | 44 * In parsing, we will always try long format, then short. |
47 * (e.g., "EEEE" produces "Monday", "EEE" produces "Mon") | 45 * (e.g., "EEEE" produces "Monday", "EEE" produces "Mon") |
48 * | 46 * |
49 * (Number): the minimum number of digits. Shorter numbers are zero-padded to | 47 * (Number): the minimum number of digits. Shorter numbers are zero-padded to |
50 * this amount (e.g. if "m" produces "6", "mm" produces "06"). Year is handled | 48 * this amount (e.g. if "m" produces "6", "mm" produces "06"). Year is handled |
51 * specially; that is, if the count of 'y' is 2, the Year will be truncated to | 49 * specially; that is, if the count of 'y' is 2, the Year will be truncated to |
52 * 2 digits. (e.g., if "yyyy" produces "1997", "yy" produces "97".) Unlike other | 50 * 2 digits. (e.g., if "yyyy" produces "1997", "yy" produces "97".) Unlike other |
53 * fields, fractional seconds are padded on the right with zero. | 51 * fields, fractional seconds are padded on the right with zero. |
54 * | 52 * |
55 * (Text & Number): 3 or over, use text, otherwise use number. | 53 * (Text & Number): 3 or over, use text, otherwise use number. |
56 * | 54 * |
57 * Any characters that not in the pattern will be treated as quoted text. For | 55 * Any characters that not in the pattern will be treated as quoted text. For |
58 * instance, characters like ':', '.', ' ', '#' and '@' will appear in the | 56 * instance, characters like ':', '.', ' ', '#' and '@' will appear in the |
59 * resulting time text even they are not embraced within single quotes. In our | 57 * resulting time text even they are not embraced within single quotes. In our |
60 * current pattern usage, we didn't use up all letters. But those unused | 58 * current pattern usage, we didn't use up all letters. But those unused |
61 * letters are strongly discouraged to be used as quoted text without quote. | 59 * letters are strongly discouraged to be used as quoted text without quote. |
62 * That's because we may use other letter for pattern in future. | 60 * That's because we may use other letter for pattern in future. |
63 * | 61 * |
64 * Examples Using the US Locale: | 62 * Examples Using the US Locale: |
65 * | 63 * |
66 * Format Pattern Result | 64 * Format Pattern Result |
67 * -------------- ------- | 65 * -------------- ------- |
68 * "yyyy.MM.dd G 'at' HH:mm:ss vvvv"->> 1996.07.10 AD at 15:08:56 Pacific Ti me | 66 * "yyyy.MM.dd G 'at' HH:mm:ss vvvv"->1996.07.10 AD at 15:08:56 Pacific Time |
69 * "EEE, MMM d, ''yy" ->> Wed, July 10, '96 | 67 * "EEE, MMM d, ''yy" ->Wed, July 10, '96 |
70 * "h:mm a" ->> 12:08 PM | 68 * "h:mm a" ->12:08 PM |
71 * "hh 'o''clock' a, zzzz" ->> 12 o'clock PM, Pacific Daylight Time | 69 * "hh 'o''clock' a, zzzz" ->12 o'clock PM, Pacific Daylight Time |
72 * "K:mm a, vvv" ->> 0:00 PM, PT | 70 * "K:mm a, vvv" ->0:00 PM, PT |
73 * "yyyyy.MMMMM.dd GGG hh:mm aaa" ->> 01996.July.10 AD 12:08 PM | 71 * "yyyyy.MMMMM.dd GGG hh:mm aaa" ->01996.July.10 AD 12:08 PM |
74 * | 72 * |
75 * When parsing a date string using the abbreviated year pattern ("yy"), | 73 * When parsing a date string using the abbreviated year pattern ("yy"), |
76 * DateTimeParse must interpret the abbreviated year relative to some | 74 * DateTimeParse must interpret the abbreviated year relative to some |
77 * century. It does this by adjusting dates to be within 80 years before and 20 | 75 * century. It does this by adjusting dates to be within 80 years before and 20 |
78 * years after the time the parse function is called. For example, using a | 76 * years after the time the parse function is called. For example, using a |
79 * pattern of "MM/dd/yy" and a DateTimeParse instance created on Jan 1, 1997, | 77 * pattern of "MM/dd/yy" and a DateTimeParse instance created on Jan 1, 1997, |
80 * the string "01/11/12" would be interpreted as Jan 11, 2012 while the string | 78 * the string "01/11/12" would be interpreted as Jan 11, 2012 while the string |
81 * "05/04/64" would be interpreted as May 4, 1964. During parsing, only | 79 * "05/04/64" would be interpreted as May 4, 1964. During parsing, only |
82 * strings consisting of exactly two digits, as defined by {@link | 80 * strings consisting of exactly two digits, as defined by {@link |
83 * java.lang.Character#isDigit(char)}, will be parsed into the default | 81 * java.lang.Character#isDigit(char)}, will be parsed into the default |
84 * century. Any other numeric string, such as a one digit string, a three or | 82 * century. Any other numeric string, such as a one digit string, a three or |
85 * more digit string will be interpreted as its face value. | 83 * more digit string will be interpreted as its face value. |
86 * | 84 * |
87 * If the year pattern does not have exactly two 'y' characters, the year is | 85 * If the year pattern does not have exactly two 'y' characters, the year is |
88 * interpreted literally, regardless of the number of digits. So using the | 86 * interpreted literally, regardless of the number of digits. So using the |
89 * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D. | 87 * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D. |
90 * | 88 * |
91 * When numeric fields abut one another directly, with no intervening | 89 * When numeric fields abut one another directly, with no intervening |
92 * delimiter characters, they constitute a run of abutting numeric fields. Such | 90 * delimiter characters, they constitute a run of abutting numeric fields. Such |
93 * runs are parsed specially. For example, the format "HHmmss" parses the input | 91 * runs are parsed specially. For example, the format "HHmmss" parses the input |
94 * text "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and | 92 * text "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and |
95 * fails to parse "1234". In other words, the leftmost field of the run is | 93 * fails to parse "1234". In other words, the leftmost field of the run is |
96 * flexible, while the others keep a fixed width. If the parse fails anywhere in | 94 * flexible, while the others keep a fixed width. If the parse fails anywhere in |
97 * the run, then the leftmost field is shortened by one character, and the | 95 * the run, then the leftmost field is shortened by one character, and the |
98 * entire run is parsed again. This is repeated until either the parse succeeds | 96 * entire run is parsed again. This is repeated until either the parse succeeds |
99 * or the leftmost field is one character in length. If the parse still fails at | 97 * or the leftmost field is one character in length. If the parse still fails at |
100 * that point, the parse of the run fails. | 98 * that point, the parse of the run fails. |
101 */ | 99 */ |
102 | 100 |
103 #library('DateFormat'); | 101 #library('DateTimeFormat'); |
Alan Knight
2012/06/03 17:19:52
I had deliberately called it DateFormat, rather th
| |
104 | 102 |
105 class DateFormat { | 103 class DateTimeFormat { |
106 | 104 |
107 /** Definition of this object formats dates. */ | 105 /** Definition of this object formats dates. */ |
108 var formatDefinition; | 106 String formatDefinition; |
109 | 107 |
110 /** Date/Time format patterns. */ | 108 /** |
111 // TODO(alanknight): There's a style question of whether to use fullDate or | 109 * Date/Time format patterns. Also specifiable by String, but written this way |
112 // FULL_DATE naming conventions. | 110 * so that they can be discoverable via autocomplete. |
113 static final int _fullDate = 0; | 111 */ |
114 static final int _longDate = 1; | 112 static final String Hm = 'Hm'; // HH:mm |
115 static final int _mediumDate = 2; | 113 static final String Hms = 'Hms'; // HH:mm:ss |
116 static final int _shortDate = 3; | 114 static final String M = 'M'; // L |
117 static final int _fullTime = 4; | 115 static final String MEd = 'MEd'; // E, M/d |
118 static final int _longTime = 5; | 116 static final String MMM = 'MMM'; // LLL |
119 static final int _mediumTime = 6; | 117 static final String MMMEd = 'MMMEd'; // E, MMM d |
120 static final int _shortTime = 7; | 118 static final String MMMMEd = 'MMMMEd'; // E, MMMM d |
121 static final int _fullDateTime = 8; | 119 static final String MMMMd = 'MMMMd'; // MMMM d |
122 static final int _longDateTime = 9; | 120 static final String MMMd = 'MMMd'; // MMM d |
123 static final int _mediumDateTime = 10; | 121 static final String Md = 'Md'; // M/d |
124 static final int _shortDateTime = 11; | 122 static final String d = 'd'; // d |
123 static final String hm = 'hm'; // h:mm a | |
124 static final String ms = 'ms'; // mm:ss | |
125 static final String y = 'y'; // yyyy | |
126 static final String yM = 'yM'; // M/yyyy | |
127 static final String yMEd = 'yMEd'; // EEE, M/d/yyyy | |
128 static final String yMMM = 'yMMM'; // MMM yyyy | |
129 static final String yMMMEd = 'yMMMEd'; // EEE, MM d, yyyy | |
130 static final String yMMMM = 'yMMMM'; // MMMM yyyy | |
131 static final String yQ = 'yQ'; // Q yyyy | |
132 static final String yQQQ = 'yQQQ'; // QQQ yyyy | |
125 | 133 |
126 /** | 134 |
127 * Named constructors for each of the above values. | 135 DateTimeFormat(this.formatDefinition, [this._locale]) { |
Alan Knight
2012/06/03 17:19:52
Should we allow formatDefinition to also be option
| |
128 * These could probably be made shorter if we just set the format to the | 136 default_forms = ['Hm', 'Hms', 'M', 'MEd', 'MMM', 'MMMEd', 'MMMMEd', 'MMMMd', |
129 * constant and the parsing was lazy. | 137 'MMMd', 'Md', 'd', 'hm', 'ms', 'y', 'yM', 'yMEd', 'yMMM', |
130 */ | 138 'yMMMEd', 'yMMMM', 'yQ', 'yQQQ']; |
131 DateFormat.fullDate() : this.formatDefinition = _fullDate; | 139 // Default to full date and time if it does not match one of our expected |
132 DateFormat.longDate() : this.formatDefinition = _longDate; | 140 // forms (for now). |
133 DateFormat.mediumDate() : this.formatDefinition = _mediumDate; | 141 if(!default_forms.contains(formatDefinition)) formatDefinition = 'yMMMEd'; |
134 DateFormat.shortDate() : this.formatDefinition = _shortDate; | 142 } |
135 DateFormat.fullTime() : this.formatDefinition = _fullTime; | |
136 DateFormat.longTime() : this.formatDefinition = _longTime; | |
137 DateFormat.mediumTime() : this.formatDefinition = _mediumTime; | |
138 DateFormat.shortTime() : this.formatDefinition = _shortTime; | |
139 DateFormat.fullDateTime() : this.formatDefinition = _fullDateTime; | |
140 DateFormat.longDateTime() : this.formatDefinition = _longDateTime; | |
141 DateFormat.mediumDateTime() : this.formatDefinition = _mediumDateTime; | |
142 DateFormat.shortDateTime() : this.formatDefinition = _shortDateTime; | |
143 | |
144 DateFormat(this.formatDefinition); | |
145 | 143 |
146 /** | 144 /** |
147 * | 145 * |
148 */ | 146 */ |
149 String parse(String inputString) { | 147 String parse(String inputString) { |
150 return inputString; | 148 return inputString; |
151 } | 149 } |
152 | 150 |
153 /** | 151 /** |
154 * Format the given [date] object according to preset pattern and current | 152 * Format the given [date] object according to preset pattern and current |
155 * locale and return a formated string for the given date. | 153 * locale and return a formated string for the given date. |
156 */ | 154 */ |
157 String format(Date date, [TimeZone timeZone]) { | 155 String format(Date date) { |
158 // TODO(efortuna): optional TimeZone argument? TimeZone is deprecated... | 156 // TODO(efortuna): optional TimeZone argument? TimeZone is deprecated... |
159 return date.toString(); | 157 return date.toString(); |
160 } | 158 } |
161 } | 159 } |
OLD | NEW |