OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 /** | |
6 * DateFormat is for formatting and parsing dates in a locale-sensitive | |
7 * manner. | |
8 * It allows the user to choose from a set of standard date time formats as well | |
9 * as specify a customized pattern under certain locales. Date elements that | |
10 * vary across locales include month name, week name, field order, etc. | |
11 * <!-- TODO(efortuna): Customized pattern system -- suggested by i18n needs | |
12 *feedback on appropriateness. --> | |
13 * We also allow the user to use any customized pattern to parse or format | |
14 * date-time strings under certain locales. Date elements that vary across | |
15 * locales include month name, weekname, field, order, etc. | |
16 * | |
17 * This library uses the ICU/JDK date/time pattern specification as described | |
18 * below. | |
19 * | |
20 * Time Format Syntax: To specify the time format use a time pattern string. | |
21 * In this pattern, following letters are reserved as pattern letters, which | |
22 * are defined in the following manner: | |
23 * | |
24 * Symbol Meaning Presentation Example | |
25 * ------ ------- ------------ ------- | |
26 * G era designator (Text) AD | |
27 * y# year (Number) 1996 | |
28 * M month in year (Text & Number) July & 07 | |
29 * d day in month (Number) 10 | |
30 * h hour in am/pm (1~12) (Number) 12 | |
31 * H hour in day (0~23) (Number) 0 | |
32 * m minute in hour (Number) 30 | |
33 * s second in minute (Number) 55 | |
34 * S fractional second (Number) 978 | |
35 * E day of week (Text) Tuesday | |
36 * D day in year (Number) 189 | |
37 * a am/pm marker (Text) PM | |
38 * k hour in day (1~24) (Number) 24 | |
39 * K hour in am/pm (0~11) (Number) 0 | |
40 * z time zone (Text) Pacific Standard Time | |
41 * Z time zone (RFC 822) (Number) -0800 | |
42 * v time zone (generic) (Text) Pacific Time | |
43 * ' escape for text (Delimiter) 'Date=' | |
44 * '' single quote (Literal) 'o''clock' | |
45 * | |
46 * Items marked with '#' work differently than in Java. | |
47 * | |
48 * The count of pattern letters determine the format. | |
49 * **Text**: | |
50 * * 4 or more pattern letters--use full form, | |
51 * * less than 4--use short or abbreviated form if one exists. | |
52 * In parsing, we will always try long format, then short. | |
53 * (e.g., "EEEE" produces "Monday", "EEE" produces "Mon") | |
54 * | |
55 * **Number**: the minimum number of digits. Shorter numbers are zero-padded to | |
56 * this amount (e.g. if "m" produces "6", "mm" produces "06"). Year is handled | |
57 * specially; that is, if the count of 'y' is 2, the Year will be truncated to | |
58 * 2 digits. (e.g., if "yyyy" produces "1997", "yy" produces "97".) Unlike other | |
59 * fields, fractional seconds are padded on the right with zero. | |
60 * | |
61 * (Text & Number): 3 or over, use text, otherwise use number. | |
62 * | |
63 * Any characters that not in the pattern will be treated as quoted text. For | |
64 * instance, characters like ':', '.', ' ', '#' and '@' will appear in the | |
65 * resulting time text even they are not embraced within single quotes. In our | |
66 * current pattern usage, we didn't use up all letters. But those unused | |
67 * letters are strongly discouraged to be used as quoted text without quote. | |
68 * That's because we may use other letter for pattern in future. | |
69 * | |
70 * Examples Using the US Locale: | |
71 * | |
72 * Format Pattern Result | |
73 * -------------- ------- | |
74 * "yyyy.MM.dd G 'at' HH:mm:ss vvvv"->1996.07.10 AD at 15:08:56 Pacific Time | |
75 * "EEE, MMM d, ''yy" ->Wed, July 10, '96 | |
76 * "h:mm a" ->12:08 PM | |
77 * "hh 'o''clock' a, zzzz" ->12 o'clock PM, Pacific Daylight Time | |
78 * "K:mm a, vvv" ->0:00 PM, PT | |
79 * "yyyyy.MMMMM.dd GGG hh:mm aaa" ->01996.July.10 AD 12:08 PM | |
80 * | |
81 * When parsing a date string using the abbreviated year pattern ("yy"), | |
82 * DateTimeParse must interpret the abbreviated year relative to some | |
83 * century. It does this by adjusting dates to be within 80 years before and 20 | |
84 * years after the time the parse function is called. For example, using a | |
85 * pattern of "MM/dd/yy" and a DateTimeParse instance created on Jan 1, 1997, | |
86 * the string "01/11/12" would be interpreted as Jan 11, 2012 while the string | |
87 * "05/04/64" would be interpreted as May 4, 1964. During parsing, only | |
88 * strings consisting of exactly two digits, as defined by {@link | |
89 * java.lang.Character#isDigit(char)}, will be parsed into the default | |
90 * century. Any other numeric string, such as a one digit string, a three or | |
91 * more digit string will be interpreted as its face value. | |
92 * | |
93 * If the year pattern does not have exactly two 'y' characters, the year is | |
94 * interpreted literally, regardless of the number of digits. So using the | |
95 * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D. | |
96 * | |
97 * When numeric fields abut one another directly, with no intervening | |
98 * delimiter characters, they constitute a run of abutting numeric fields. Such | |
99 * runs are parsed specially. For example, the format "HHmmss" parses the input | |
100 * text "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and | |
101 * fails to parse "1234". In other words, the leftmost field of the run is | |
102 * flexible, while the others keep a fixed width. If the parse fails anywhere in | |
103 * the run, then the leftmost field is shortened by one character, and the | |
104 * entire run is parsed again. This is repeated until either the parse succeeds | |
105 * or the leftmost field is one character in length. If the parse still fails at | |
106 * that point, the parse of the run fails. | |
107 */ | |
108 | |
109 class DateFormat { | |
110 | |
111 /** Definition of how this object formats dates. */ | |
112 String _formatDefinition; | |
113 | |
114 /** | |
115 * The locale code with which the message is to be formatted (such as en-CA). | |
116 */ | |
117 String _locale; | |
118 | |
119 /** | |
120 * Date/Time format "skeleton" patterns. Also specifiable by String, but | |
121 * written this way so that they can be discoverable via autocomplete. These | |
122 * follow the ICU syntax described at the top of the file. These skeletons can | |
123 * be combined and we will attempt to find the best format for each locale | |
124 * given the pattern. | |
125 */ | |
126 // TODO(efortuna): Hear back from i18n about Time Zones and the "core set" | |
127 // of skeleton patterns. | |
128 // Example of how this looks in the US | |
129 // locale. | |
130 static final String Hm = 'Hm'; // HH:mm | |
131 static final String Hms = 'Hms'; // HH:mm:ss | |
132 static final String M = 'M'; // L | |
133 static final String MEd = 'MEd'; // E, M/d | |
134 static final String MMM = 'MMM'; // LLL | |
135 static final String MMMEd = 'MMMEd'; // E, MMM d | |
136 static final String MMMMEd = 'MMMMEd'; // E, MMMM d | |
137 static final String MMMMd = 'MMMMd'; // MMMM d | |
138 static final String MMMd = 'MMMd'; // MMM d | |
139 static final String Md = 'Md'; // M/d | |
140 static final String d = 'd'; // d | |
141 static final String hm = 'hm'; // h:mm a | |
142 static final String ms = 'ms'; // mm:ss | |
143 static final String y = 'y'; // yyyy | |
144 static final String yM = 'yM'; // M/yyyy | |
145 static final String yMEd = 'yMEd'; // EEE, M/d/yyyy | |
146 static final String yMMM = 'yMMM'; // MMM yyyy | |
147 static final String yMMMEd = 'yMMMEd'; // EEE, MM d, yyyy | |
148 static final String yMMMM = 'yMMMM'; // MMMM yyyy | |
149 static final String yQ = 'yQ'; // Q yyyy | |
150 static final String yQQQ = 'yQQQ'; // QQQ yyyy | |
151 | |
152 /** Date/Time format patterns. */ | |
153 // TODO(efortuna): This are just guesses of what a full date, long date is. | |
154 // Do the proper homework on ICU to find the proper set "Hms"/"yMMd" | |
155 // applicable to each case. | |
156 static final String fullDate = '$y$MMMMd'; | |
157 static final String longDate = yMMMEd; | |
158 static final String mediumDate = '$y$Md'; | |
159 static final String shortDate = Md; | |
160 static final String fullTime = '$Hms a'; | |
161 static final String longTime = '$Hms a zzzz'; | |
162 static final String mediumTime = Hms; | |
163 static final String shortTime = Hm; | |
164 static final String fullDateTime = '$fullDate$fullTime'; | |
165 static final String longDateTime = '$longDate$longTime'; | |
166 static final String mediumDateTime = '$mediumDate$mediumTime'; | |
167 static final String shortDateTime = '$shortDate$shortTime'; | |
168 | |
169 /** | |
170 * Constructors for dates/times that use a default format. | |
171 */ | |
172 DateFormat.Hm([locale='']) : _locale = locale, _formatDefinition = Hm; | |
173 DateFormat.Hms([locale='']) : _locale = locale, _formatDefinition = Hms; | |
174 DateFormat.M([locale='']) : _locale = locale, _formatDefinition = M; | |
175 DateFormat.MEd([locale='']) : _locale = locale, _formatDefinition = MEd; | |
176 DateFormat.MMM([locale='']) : _locale = locale, _formatDefinition = MMM; | |
177 DateFormat.MMMEd([locale='']) : _locale = locale, _formatDefinition = MMMEd; | |
178 DateFormat.MMMMEd([locale='']) : _locale = locale, _formatDefinition = MMMMEd; | |
179 DateFormat.MMMMd([locale='']) : _locale = locale, _formatDefinition = MMMMd; | |
180 DateFormat.MMMd([locale='']) : _locale = locale, _formatDefinition = MMMd; | |
181 DateFormat.Md([locale='']) : _locale = locale, _formatDefinition = Md; | |
182 DateFormat.d([locale='']) : _locale = locale, _formatDefinition = d; | |
183 DateFormat.hm([locale='']) : _locale = locale, _formatDefinition = hm; | |
184 DateFormat.ms([locale='']) : _locale = locale, _formatDefinition = ms; | |
185 DateFormat.y([locale='']) : _locale = locale, _formatDefinition = y; | |
186 DateFormat.yM([locale='']) : _locale = locale, _formatDefinition = yM; | |
187 DateFormat.yMEd([locale='']) : _locale = locale, _formatDefinition = yMEd; | |
188 DateFormat.yMMM([locale='']) : _locale = locale, _formatDefinition = yMMM; | |
189 DateFormat.yMMMEd([locale='']) : _locale = locale, _formatDefinition = yMMMEd; | |
190 DateFormat.yMMMM([locale='']) : _locale = locale, _formatDefinition = yMMMM; | |
191 DateFormat.yQ([locale='']) : _locale = locale, _formatDefinition = yQ; | |
192 DateFormat.yQQQ([locale='']) : _locale = locale, _formatDefinition = yQQQ; | |
193 | |
194 DateFormat.fullDate([locale='']) : _locale = locale, | |
195 _formatDefinition = fullDate; | |
196 DateFormat.longDate([locale='']) : _locale = locale, | |
197 _formatDefinition = longDate; | |
198 DateFormat.mediumDate([locale='']) : _locale = locale, | |
199 _formatDefinition = mediumDate; | |
200 DateFormat.shortDate([locale='']) : _locale = locale, | |
201 _formatDefinition = shortDate; | |
202 DateFormat.fullTime([locale='']) : _locale = locale, | |
203 _formatDefinition = fullTime; | |
204 DateFormat.longTime([locale='']) : _locale = locale, | |
205 _formatDefinition = longTime; | |
206 DateFormat.mediumTime([locale='']) : _locale = locale, | |
207 _formatDefinition = mediumTime; | |
208 DateFormat.shortTime([locale='']) : _locale = locale, | |
209 _formatDefinition = shortTime; | |
210 DateFormat.fullDateTime([locale='']) : _locale = locale, | |
211 _formatDefinition = fullDateTime; | |
212 DateFormat.longDateTime([locale='']) : _locale = locale, | |
213 _formatDefinition = longDateTime; | |
214 DateFormat.mediumDateTime([locale='']) : _locale = locale, | |
215 _formatDefinition = mediumDateTime; | |
216 DateFormat.shortDateTime([locale='']) : _locale = locale, | |
217 _formatDefinition = shortDateTime; | |
218 | |
219 /** | |
220 * Constructor accepts a [formatDefinition], which can be a String, one of the | |
221 * predefined static forms, or a custom date format using the syntax described | |
222 * above. An optional [locale] can be provided for specifics of the language | |
223 * locale to be used, otherwise, we will attempt to infer it (acceptable if | |
224 * Dart is running on the client, we can infer from the browser). | |
225 */ | |
226 DateFormat([formatDefinition = fullDate, locale = '']) { | |
227 this._formatDefinition = formatDefinition; | |
228 this._locale = locale; | |
229 } | |
230 | |
231 /** | |
232 * Given user input, attempt to parse the [inputString] into the anticipated | |
233 * format. | |
234 */ | |
235 String parse(String inputString) { | |
236 return inputString; | |
237 } | |
238 | |
239 /** | |
240 * Format the given [date] object according to preset pattern and current | |
241 * locale and return a formated string for the given date. | |
242 */ | |
243 String format(Date date) { | |
244 // TODO(efortuna): readd optional TimeZone argument (or similar)? | |
245 return date.toString(); | |
246 } | |
247 | |
248 /** | |
249 * Returns a date string indicating how long ago (3 hours, 2 minutes) | |
250 * something has happened or how long in the future something will happen | |
251 * given a [reference] Date relative to the current time. | |
252 */ | |
253 String formatDuration(Date reference) { | |
254 return ''; | |
255 } | |
256 | |
257 /** | |
258 * Formats a string indicating how long ago (negative [duration]) or how far | |
259 * in the future (positive [duration]) some time is with respect to a | |
260 * reference [date]. | |
261 */ | |
262 String formatDurationFrom(Duration duration, Date date) { | |
263 return ''; | |
264 } | |
265 } | |
OLD | NEW |