• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *******************************************************************************
3  * Copyright (C) 2008-2015, 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 &quot;Jan 10, 2007&quot;
82  * and &quot;Feb 20, 2008&quot; 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  &quot;yMMMd&quot;,
89  * in  en_US, if the largest different calendar field between date1 and date2
90  * is &quot;year&quot;, the date interval pattern  is &quot;MMM d, yyyy - MMM d, yyyy&quot;,
91  * such as &quot;Jan 10, 2007 - Jan 10, 2008&quot;.
92  * If the largest different calendar field between date1 and date2 is &quot;month&quot;,
93  * the date interval pattern is &quot;MMM d - MMM d, yyyy&quot;,
94  * such as &quot;Jan 10 - Feb 10, 2007&quot;.
95  * If the largest different calendar field between date1 and date2 is &quot;day&quot;,
96  * the date interval pattern is &quot;MMM d-d, yyyy&quot;, such as &quot;Jan 10-20, 2007&quot;.
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 &quot;{0} - {1}&quot;, it means
110  * the first date in the interval pattern for this locale is earlier date.
111  * If the fallback format is &quot;{1} - {0}&quot;, 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 &quot;latestFirst:&quot; or &quot;earliestFirst:&quot; to the interval pattern.
115  * For example, if the fallback format is &quot;{0}-{1}&quot;,
116  * but for skeleton &quot;yMMMd&quot;, the interval pattern when day is different is
117  * &quot;latestFirst:d-d MMM yy&quot;, it means by default, the first date in interval
118  * pattern is the earlier date. But for skeleton &quot;yMMMd&quot;, when day is different,
119  * the first date in &quot;d-d MMM yy&quot; 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 U_FINAL : 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_SECOND,
357         kIPI_MAX_INDEX
358     };
359 public:
360 #ifndef U_HIDE_INTERNAL_API
361     /**
362      * Max index for stored interval patterns
363      * @internal ICU 4.4
364      */
365      enum {
366          kMaxIntervalPatternIndex = kIPI_MAX_INDEX
367      };
368 #endif  /* U_HIDE_INTERNAL_API */
369 private:
370 
371 
372     /**
373      * Initialize the DateIntervalInfo from locale
374      * @param locale   the given locale.
375      * @param status   output param set to success/failure code on exit
376      */
377     void initializeData(const Locale& locale, UErrorCode& status);
378 
379 
380     /* Set Interval pattern.
381      *
382      * It sets interval pattern into the hash map.
383      *
384      * @param skeleton         skeleton on which the interval pattern based
385      * @param lrgDiffCalUnit   the largest different calendar unit.
386      * @param intervalPattern  the interval pattern on the largest different
387      *                         calendar unit.
388      * @param status           output param set to success/failure code on exit
389      */
390     void setIntervalPatternInternally(const UnicodeString& skeleton,
391                                       UCalendarDateFields lrgDiffCalUnit,
392                                       const UnicodeString& intervalPattern,
393                                       UErrorCode& status);
394 
395 
396     /**given an input skeleton, get the best match skeleton
397      * which has pre-defined interval pattern in resource file.
398      * Also return the difference between the input skeleton
399      * and the best match skeleton.
400      *
401      * TODO (xji): set field weight or
402      *             isolate the funtionality in DateTimePatternGenerator
403      * @param  skeleton               input skeleton
404      * @param  bestMatchDistanceInfo  the difference between input skeleton
405      *                                and best match skeleton.
406      *         0, if there is exact match for input skeleton
407      *         1, if there is only field width difference between
408      *            the best match and the input skeleton
409      *         2, the only field difference is 'v' and 'z'
410      *        -1, if there is calendar field difference between
411      *            the best match and the input skeleton
412      * @return                        best match skeleton
413      */
414     const UnicodeString* getBestSkeleton(const UnicodeString& skeleton,
415                                          int8_t& bestMatchDistanceInfo) const;
416 
417 
418     /**
419      * Parse skeleton, save each field's width.
420      * It is used for looking for best match skeleton,
421      * and adjust pattern field width.
422      * @param skeleton            skeleton to be parsed
423      * @param skeletonFieldWidth  parsed skeleton field width
424      */
425     static void U_EXPORT2 parseSkeleton(const UnicodeString& skeleton,
426                                         int32_t* skeletonFieldWidth);
427 
428 
429     /**
430      * Check whether one field width is numeric while the other is string.
431      *
432      * TODO (xji): make it general
433      *
434      * @param fieldWidth          one field width
435      * @param anotherFieldWidth   another field width
436      * @param patternLetter       pattern letter char
437      * @return true if one field width is numeric and the other is string,
438      *         false otherwise.
439      */
440     static UBool U_EXPORT2 stringNumeric(int32_t fieldWidth,
441                                          int32_t anotherFieldWidth,
442                                          char patternLetter);
443 
444 
445     /**
446      * Convert calendar field to the interval pattern index in
447      * hash table.
448      *
449      * Since we only support the following calendar fields:
450      * ERA, YEAR, MONTH, DATE,  DAY_OF_MONTH, DAY_OF_WEEK,
451      * AM_PM,  HOUR, HOUR_OF_DAY, and MINUTE,
452      * We reserve only 4 interval patterns for a skeleton.
453      *
454      * @param field    calendar field
455      * @param status   output param set to success/failure code on exit
456      * @return  interval pattern index in hash table
457      */
458     static IntervalPatternIndex U_EXPORT2 calendarFieldToIntervalIndex(
459                                                       UCalendarDateFields field,
460                                                       UErrorCode& status);
461 
462 
463     /**
464      * delete hash table (of type fIntervalPatterns).
465      *
466      * @param hTable  hash table to be deleted
467      */
468     void deleteHash(Hashtable* hTable);
469 
470 
471     /**
472      * initialize hash table (of type fIntervalPatterns).
473      *
474      * @param status   output param set to success/failure code on exit
475      * @return         hash table initialized
476      */
477     Hashtable* initHash(UErrorCode& status);
478 
479 
480 
481     /**
482      * copy hash table (of type fIntervalPatterns).
483      *
484      * @param source   the source to copy from
485      * @param target   the target to copy to
486      * @param status   output param set to success/failure code on exit
487      */
488     void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
489 
490 
491     // data members
492     // fallback interval pattern
493     UnicodeString fFallbackIntervalPattern;
494     // default order
495     UBool fFirstDateInPtnIsLaterDate;
496 
497     // HashMap<UnicodeString, UnicodeString[kIPI_MAX_INDEX]>
498     // HashMap( skeleton, pattern[largest_different_field] )
499     Hashtable* fIntervalPatterns;
500 
501 };// end class DateIntervalInfo
502 
503 
504 inline UBool
505 DateIntervalInfo::operator!=(const DateIntervalInfo& other) const {
506     return !operator==(other);
507 }
508 
509 
510 U_NAMESPACE_END
511 
512 #endif
513 
514 #endif
515 
516