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