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