|
1 /* |
|
2 ******************************************************************************* |
|
3 * Copyright (C) 2008-2011,2013, International Business Machines Corporation and |
|
4 * others. All Rights Reserved. |
|
5 ******************************************************************************* |
|
6 * |
|
7 * File DTITVINF.H |
|
8 * |
|
9 ******************************************************************************* |
|
10 */ |
|
11 |
|
12 #ifndef __DTITVINF_H__ |
|
13 #define __DTITVINF_H__ |
|
14 |
|
15 #include "unicode/utypes.h" |
|
16 |
|
17 /** |
|
18 * \file |
|
19 * \brief C++ API: Date/Time interval patterns for formatting date/time interval |
|
20 */ |
|
21 |
|
22 #if !UCONFIG_NO_FORMATTING |
|
23 |
|
24 #include "unicode/udat.h" |
|
25 #include "unicode/locid.h" |
|
26 #include "unicode/ucal.h" |
|
27 #include "unicode/dtptngen.h" |
|
28 |
|
29 U_NAMESPACE_BEGIN |
|
30 |
|
31 /** |
|
32 * DateIntervalInfo is a public class for encapsulating localizable |
|
33 * date time interval patterns. It is used by DateIntervalFormat. |
|
34 * |
|
35 * <P> |
|
36 * For most users, ordinary use of DateIntervalFormat does not need to create |
|
37 * DateIntervalInfo object directly. |
|
38 * DateIntervalFormat will take care of it when creating a date interval |
|
39 * formatter when user pass in skeleton and locale. |
|
40 * |
|
41 * <P> |
|
42 * For power users, who want to create their own date interval patterns, |
|
43 * or want to re-set date interval patterns, they could do so by |
|
44 * directly creating DateIntervalInfo and manupulating it. |
|
45 * |
|
46 * <P> |
|
47 * Logically, the interval patterns are mappings |
|
48 * from (skeleton, the_largest_different_calendar_field) |
|
49 * to (date_interval_pattern). |
|
50 * |
|
51 * <P> |
|
52 * A skeleton |
|
53 * <ol> |
|
54 * <li> |
|
55 * only keeps the field pattern letter and ignores all other parts |
|
56 * in a pattern, such as space, punctuations, and string literals. |
|
57 * <li> |
|
58 * hides the order of fields. |
|
59 * <li> |
|
60 * might hide a field's pattern letter length. |
|
61 * |
|
62 * For those non-digit calendar fields, the pattern letter length is |
|
63 * important, such as MMM, MMMM, and MMMMM; EEE and EEEE, |
|
64 * and the field's pattern letter length is honored. |
|
65 * |
|
66 * For the digit calendar fields, such as M or MM, d or dd, yy or yyyy, |
|
67 * the field pattern length is ignored and the best match, which is defined |
|
68 * in date time patterns, will be returned without honor the field pattern |
|
69 * letter length in skeleton. |
|
70 * </ol> |
|
71 * |
|
72 * <P> |
|
73 * The calendar fields we support for interval formatting are: |
|
74 * year, month, date, day-of-week, am-pm, hour, hour-of-day, and minute. |
|
75 * Those calendar fields can be defined in the following order: |
|
76 * year > month > date > am-pm > hour > minute |
|
77 * |
|
78 * The largest different calendar fields between 2 calendars is the |
|
79 * first different calendar field in above order. |
|
80 * |
|
81 * For example: the largest different calendar fields between "Jan 10, 2007" |
|
82 * and "Feb 20, 2008" is year. |
|
83 * |
|
84 * <P> |
|
85 * There is a set of pre-defined static skeleton strings. |
|
86 * There are pre-defined interval patterns for those pre-defined skeletons |
|
87 * in locales' resource files. |
|
88 * For example, for a skeleton UDAT_YEAR_ABBR_MONTH_DAY, which is "yMMMd", |
|
89 * in en_US, if the largest different calendar field between date1 and date2 |
|
90 * is "year", the date interval pattern is "MMM d, yyyy - MMM d, yyyy", |
|
91 * such as "Jan 10, 2007 - Jan 10, 2008". |
|
92 * If the largest different calendar field between date1 and date2 is "month", |
|
93 * the date interval pattern is "MMM d - MMM d, yyyy", |
|
94 * such as "Jan 10 - Feb 10, 2007". |
|
95 * If the largest different calendar field between date1 and date2 is "day", |
|
96 * the date interval pattern is "MMM d-d, yyyy", such as "Jan 10-20, 2007". |
|
97 * |
|
98 * For date skeleton, the interval patterns when year, or month, or date is |
|
99 * different are defined in resource files. |
|
100 * For time skeleton, the interval patterns when am/pm, or hour, or minute is |
|
101 * different are defined in resource files. |
|
102 * |
|
103 * |
|
104 * <P> |
|
105 * There are 2 dates in interval pattern. For most locales, the first date |
|
106 * in an interval pattern is the earlier date. There might be a locale in which |
|
107 * the first date in an interval pattern is the later date. |
|
108 * We use fallback format for the default order for the locale. |
|
109 * For example, if the fallback format is "{0} - {1}", it means |
|
110 * the first date in the interval pattern for this locale is earlier date. |
|
111 * If the fallback format is "{1} - {0}", it means the first date is the |
|
112 * later date. |
|
113 * For a particular interval pattern, the default order can be overriden |
|
114 * by prefixing "latestFirst:" or "earliestFirst:" to the interval pattern. |
|
115 * For example, if the fallback format is "{0}-{1}", |
|
116 * but for skeleton "yMMMd", the interval pattern when day is different is |
|
117 * "latestFirst:d-d MMM yy", it means by default, the first date in interval |
|
118 * pattern is the earlier date. But for skeleton "yMMMd", when day is different, |
|
119 * the first date in "d-d MMM yy" is the later date. |
|
120 * |
|
121 * <P> |
|
122 * The recommended way to create a DateIntervalFormat object is to pass in |
|
123 * the locale. |
|
124 * By using a Locale parameter, the DateIntervalFormat object is |
|
125 * initialized with the pre-defined interval patterns for a given or |
|
126 * default locale. |
|
127 * <P> |
|
128 * Users can also create DateIntervalFormat object |
|
129 * by supplying their own interval patterns. |
|
130 * It provides flexibility for power users. |
|
131 * |
|
132 * <P> |
|
133 * After a DateIntervalInfo object is created, clients may modify |
|
134 * the interval patterns using setIntervalPattern function as so desired. |
|
135 * Currently, users can only set interval patterns when the following |
|
136 * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, |
|
137 * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE. |
|
138 * Interval patterns when other calendar fields are different is not supported. |
|
139 * <P> |
|
140 * DateIntervalInfo objects are cloneable. |
|
141 * When clients obtain a DateIntervalInfo object, |
|
142 * they can feel free to modify it as necessary. |
|
143 * <P> |
|
144 * DateIntervalInfo are not expected to be subclassed. |
|
145 * Data for a calendar is loaded out of resource bundles. |
|
146 * Through ICU 4.4, date interval patterns are only supported in the Gregorian |
|
147 * calendar; non-Gregorian calendars are supported from ICU 4.4.1. |
|
148 * @stable ICU 4.0 |
|
149 **/ |
|
150 |
|
151 class U_I18N_API DateIntervalInfo : public UObject { |
|
152 public: |
|
153 #ifndef U_HIDE_INTERNAL_API |
|
154 /** |
|
155 * Default constructor. |
|
156 * It does not initialize any interval patterns except |
|
157 * that it initialize default fall-back pattern as "{0} - {1}", |
|
158 * which can be reset by setFallbackIntervalPattern(). |
|
159 * It should be followed by setFallbackIntervalPattern() and |
|
160 * setIntervalPattern(), |
|
161 * and is recommended to be used only for power users who |
|
162 * wants to create their own interval patterns and use them to create |
|
163 * date interval formatter. |
|
164 * @param status output param set to success/failure code on exit |
|
165 * @internal ICU 4.0 |
|
166 */ |
|
167 DateIntervalInfo(UErrorCode& status); |
|
168 #endif /* U_HIDE_INTERNAL_API */ |
|
169 |
|
170 |
|
171 /** |
|
172 * Construct DateIntervalInfo for the given locale, |
|
173 * @param locale the interval patterns are loaded from the appropriate calendar |
|
174 * data (specified calendar or default calendar) in this locale. |
|
175 * @param status output param set to success/failure code on exit |
|
176 * @stable ICU 4.0 |
|
177 */ |
|
178 DateIntervalInfo(const Locale& locale, UErrorCode& status); |
|
179 |
|
180 |
|
181 /** |
|
182 * Copy constructor. |
|
183 * @stable ICU 4.0 |
|
184 */ |
|
185 DateIntervalInfo(const DateIntervalInfo&); |
|
186 |
|
187 /** |
|
188 * Assignment operator |
|
189 * @stable ICU 4.0 |
|
190 */ |
|
191 DateIntervalInfo& operator=(const DateIntervalInfo&); |
|
192 |
|
193 /** |
|
194 * Clone this object polymorphically. |
|
195 * The caller owns the result and should delete it when done. |
|
196 * @return a copy of the object |
|
197 * @stable ICU 4.0 |
|
198 */ |
|
199 virtual DateIntervalInfo* clone(void) const; |
|
200 |
|
201 /** |
|
202 * Destructor. |
|
203 * It is virtual to be safe, but it is not designed to be subclassed. |
|
204 * @stable ICU 4.0 |
|
205 */ |
|
206 virtual ~DateIntervalInfo(); |
|
207 |
|
208 |
|
209 /** |
|
210 * Return true if another object is semantically equal to this one. |
|
211 * |
|
212 * @param other the DateIntervalInfo object to be compared with. |
|
213 * @return true if other is semantically equal to this. |
|
214 * @stable ICU 4.0 |
|
215 */ |
|
216 virtual UBool operator==(const DateIntervalInfo& other) const; |
|
217 |
|
218 /** |
|
219 * Return true if another object is semantically unequal to this one. |
|
220 * |
|
221 * @param other the DateIntervalInfo object to be compared with. |
|
222 * @return true if other is semantically unequal to this. |
|
223 * @stable ICU 4.0 |
|
224 */ |
|
225 UBool operator!=(const DateIntervalInfo& other) const; |
|
226 |
|
227 |
|
228 |
|
229 /** |
|
230 * Provides a way for client to build interval patterns. |
|
231 * User could construct DateIntervalInfo by providing a list of skeletons |
|
232 * and their patterns. |
|
233 * <P> |
|
234 * For example: |
|
235 * <pre> |
|
236 * UErrorCode status = U_ZERO_ERROR; |
|
237 * DateIntervalInfo dIntervalInfo = new DateIntervalInfo(); |
|
238 * dIntervalInfo->setFallbackIntervalPattern("{0} ~ {1}"); |
|
239 * dIntervalInfo->setIntervalPattern("yMd", UCAL_YEAR, "'from' yyyy-M-d 'to' yyyy-M-d", status); |
|
240 * dIntervalInfo->setIntervalPattern("yMMMd", UCAL_MONTH, "'from' yyyy MMM d 'to' MMM d", status); |
|
241 * dIntervalInfo->setIntervalPattern("yMMMd", UCAL_DAY, "yyyy MMM d-d", status, status); |
|
242 * </pre> |
|
243 * |
|
244 * Restriction: |
|
245 * Currently, users can only set interval patterns when the following |
|
246 * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, |
|
247 * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE. |
|
248 * Interval patterns when other calendar fields are different are |
|
249 * not supported. |
|
250 * |
|
251 * @param skeleton the skeleton on which interval pattern based |
|
252 * @param lrgDiffCalUnit the largest different calendar unit. |
|
253 * @param intervalPattern the interval pattern on the largest different |
|
254 * calendar unit. |
|
255 * For example, if lrgDiffCalUnit is |
|
256 * "year", the interval pattern for en_US when year |
|
257 * is different could be "'from' yyyy 'to' yyyy". |
|
258 * @param status output param set to success/failure code on exit |
|
259 * @stable ICU 4.0 |
|
260 */ |
|
261 void setIntervalPattern(const UnicodeString& skeleton, |
|
262 UCalendarDateFields lrgDiffCalUnit, |
|
263 const UnicodeString& intervalPattern, |
|
264 UErrorCode& status); |
|
265 |
|
266 /** |
|
267 * Get the interval pattern given skeleton and |
|
268 * the largest different calendar field. |
|
269 * @param skeleton the skeleton |
|
270 * @param field the largest different calendar field |
|
271 * @param result output param to receive the pattern |
|
272 * @param status output param set to success/failure code on exit |
|
273 * @return a reference to 'result' |
|
274 * @stable ICU 4.0 |
|
275 */ |
|
276 UnicodeString& getIntervalPattern(const UnicodeString& skeleton, |
|
277 UCalendarDateFields field, |
|
278 UnicodeString& result, |
|
279 UErrorCode& status) const; |
|
280 |
|
281 /** |
|
282 * Get the fallback interval pattern. |
|
283 * @param result output param to receive the pattern |
|
284 * @return a reference to 'result' |
|
285 * @stable ICU 4.0 |
|
286 */ |
|
287 UnicodeString& getFallbackIntervalPattern(UnicodeString& result) const; |
|
288 |
|
289 |
|
290 /** |
|
291 * Re-set the fallback interval pattern. |
|
292 * |
|
293 * In construction, default fallback pattern is set as "{0} - {1}". |
|
294 * And constructor taking locale as parameter will set the |
|
295 * fallback pattern as what defined in the locale resource file. |
|
296 * |
|
297 * This method provides a way for user to replace the fallback pattern. |
|
298 * |
|
299 * @param fallbackPattern fall-back interval pattern. |
|
300 * @param status output param set to success/failure code on exit |
|
301 * @stable ICU 4.0 |
|
302 */ |
|
303 void setFallbackIntervalPattern(const UnicodeString& fallbackPattern, |
|
304 UErrorCode& status); |
|
305 |
|
306 |
|
307 /** Get default order -- whether the first date in pattern is later date |
|
308 or not. |
|
309 * return default date ordering in interval pattern. TRUE if the first date |
|
310 * in pattern is later date, FALSE otherwise. |
|
311 * @stable ICU 4.0 |
|
312 */ |
|
313 UBool getDefaultOrder() const; |
|
314 |
|
315 |
|
316 /** |
|
317 * ICU "poor man's RTTI", returns a UClassID for the actual class. |
|
318 * |
|
319 * @stable ICU 4.0 |
|
320 */ |
|
321 virtual UClassID getDynamicClassID() const; |
|
322 |
|
323 /** |
|
324 * ICU "poor man's RTTI", returns a UClassID for this class. |
|
325 * |
|
326 * @stable ICU 4.0 |
|
327 */ |
|
328 static UClassID U_EXPORT2 getStaticClassID(); |
|
329 |
|
330 |
|
331 private: |
|
332 /** |
|
333 * DateIntervalFormat will need access to |
|
334 * getBestSkeleton(), parseSkeleton(), enum IntervalPatternIndex, |
|
335 * and calendarFieldToPatternIndex(). |
|
336 * |
|
337 * Instead of making above public, |
|
338 * make DateIntervalFormat a friend of DateIntervalInfo. |
|
339 */ |
|
340 friend class DateIntervalFormat; |
|
341 |
|
342 /** |
|
343 * Following is for saving the interval patterns. |
|
344 * We only support interval patterns on |
|
345 * ERA, YEAR, MONTH, DAY, AM_PM, HOUR, and MINUTE |
|
346 */ |
|
347 enum IntervalPatternIndex |
|
348 { |
|
349 kIPI_ERA, |
|
350 kIPI_YEAR, |
|
351 kIPI_MONTH, |
|
352 kIPI_DATE, |
|
353 kIPI_AM_PM, |
|
354 kIPI_HOUR, |
|
355 kIPI_MINUTE, |
|
356 kIPI_MAX_INDEX |
|
357 }; |
|
358 public: |
|
359 #ifndef U_HIDE_INTERNAL_API |
|
360 /** |
|
361 * Max index for stored interval patterns |
|
362 * @internal ICU 4.4 |
|
363 */ |
|
364 enum { |
|
365 kMaxIntervalPatternIndex = kIPI_MAX_INDEX |
|
366 }; |
|
367 #endif /* U_HIDE_INTERNAL_API */ |
|
368 private: |
|
369 |
|
370 |
|
371 /** |
|
372 * Initialize the DateIntervalInfo from locale |
|
373 * @param locale the given locale. |
|
374 * @param status output param set to success/failure code on exit |
|
375 */ |
|
376 void initializeData(const Locale& locale, UErrorCode& status); |
|
377 |
|
378 |
|
379 /* Set Interval pattern. |
|
380 * |
|
381 * It sets interval pattern into the hash map. |
|
382 * |
|
383 * @param skeleton skeleton on which the interval pattern based |
|
384 * @param lrgDiffCalUnit the largest different calendar unit. |
|
385 * @param intervalPattern the interval pattern on the largest different |
|
386 * calendar unit. |
|
387 * @param status output param set to success/failure code on exit |
|
388 */ |
|
389 void setIntervalPatternInternally(const UnicodeString& skeleton, |
|
390 UCalendarDateFields lrgDiffCalUnit, |
|
391 const UnicodeString& intervalPattern, |
|
392 UErrorCode& status); |
|
393 |
|
394 |
|
395 /**given an input skeleton, get the best match skeleton |
|
396 * which has pre-defined interval pattern in resource file. |
|
397 * Also return the difference between the input skeleton |
|
398 * and the best match skeleton. |
|
399 * |
|
400 * TODO (xji): set field weight or |
|
401 * isolate the funtionality in DateTimePatternGenerator |
|
402 * @param skeleton input skeleton |
|
403 * @param bestMatchDistanceInfo the difference between input skeleton |
|
404 * and best match skeleton. |
|
405 * 0, if there is exact match for input skeleton |
|
406 * 1, if there is only field width difference between |
|
407 * the best match and the input skeleton |
|
408 * 2, the only field difference is 'v' and 'z' |
|
409 * -1, if there is calendar field difference between |
|
410 * the best match and the input skeleton |
|
411 * @return best match skeleton |
|
412 */ |
|
413 const UnicodeString* getBestSkeleton(const UnicodeString& skeleton, |
|
414 int8_t& bestMatchDistanceInfo) const; |
|
415 |
|
416 |
|
417 /** |
|
418 * Parse skeleton, save each field's width. |
|
419 * It is used for looking for best match skeleton, |
|
420 * and adjust pattern field width. |
|
421 * @param skeleton skeleton to be parsed |
|
422 * @param skeletonFieldWidth parsed skeleton field width |
|
423 */ |
|
424 static void U_EXPORT2 parseSkeleton(const UnicodeString& skeleton, |
|
425 int32_t* skeletonFieldWidth); |
|
426 |
|
427 |
|
428 /** |
|
429 * Check whether one field width is numeric while the other is string. |
|
430 * |
|
431 * TODO (xji): make it general |
|
432 * |
|
433 * @param fieldWidth one field width |
|
434 * @param anotherFieldWidth another field width |
|
435 * @param patternLetter pattern letter char |
|
436 * @return true if one field width is numeric and the other is string, |
|
437 * false otherwise. |
|
438 */ |
|
439 static UBool U_EXPORT2 stringNumeric(int32_t fieldWidth, |
|
440 int32_t anotherFieldWidth, |
|
441 char patternLetter); |
|
442 |
|
443 |
|
444 /** |
|
445 * Convert calendar field to the interval pattern index in |
|
446 * hash table. |
|
447 * |
|
448 * Since we only support the following calendar fields: |
|
449 * ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, DAY_OF_WEEK, |
|
450 * AM_PM, HOUR, HOUR_OF_DAY, and MINUTE, |
|
451 * We reserve only 4 interval patterns for a skeleton. |
|
452 * |
|
453 * @param field calendar field |
|
454 * @param status output param set to success/failure code on exit |
|
455 * @return interval pattern index in hash table |
|
456 */ |
|
457 static IntervalPatternIndex U_EXPORT2 calendarFieldToIntervalIndex( |
|
458 UCalendarDateFields field, |
|
459 UErrorCode& status); |
|
460 |
|
461 |
|
462 /** |
|
463 * delete hash table (of type fIntervalPatterns). |
|
464 * |
|
465 * @param hTable hash table to be deleted |
|
466 */ |
|
467 void deleteHash(Hashtable* hTable); |
|
468 |
|
469 |
|
470 /** |
|
471 * initialize hash table (of type fIntervalPatterns). |
|
472 * |
|
473 * @param status output param set to success/failure code on exit |
|
474 * @return hash table initialized |
|
475 */ |
|
476 Hashtable* initHash(UErrorCode& status); |
|
477 |
|
478 |
|
479 |
|
480 /** |
|
481 * copy hash table (of type fIntervalPatterns). |
|
482 * |
|
483 * @param source the source to copy from |
|
484 * @param target the target to copy to |
|
485 * @param status output param set to success/failure code on exit |
|
486 */ |
|
487 void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status); |
|
488 |
|
489 |
|
490 // data members |
|
491 // fallback interval pattern |
|
492 UnicodeString fFallbackIntervalPattern; |
|
493 // default order |
|
494 UBool fFirstDateInPtnIsLaterDate; |
|
495 |
|
496 // HashMap<UnicodeString, UnicodeString[kIPI_MAX_INDEX]> |
|
497 // HashMap( skeleton, pattern[largest_different_field] ) |
|
498 Hashtable* fIntervalPatterns; |
|
499 |
|
500 };// end class DateIntervalInfo |
|
501 |
|
502 |
|
503 inline UBool |
|
504 DateIntervalInfo::operator!=(const DateIntervalInfo& other) const { |
|
505 return !operator==(other); |
|
506 } |
|
507 |
|
508 |
|
509 U_NAMESPACE_END |
|
510 |
|
511 #endif |
|
512 |
|
513 #endif |
|
514 |