Home | History | Annotate | Download | only in unicode
      1 /*
      2  *******************************************************************************
      3  * Copyright (C) 2008-2011, 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 : 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      * @internal ICU 4.0
    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      * @internal ICU 4.0
    390      */
    391     void setIntervalPatternInternally(const UnicodeString& skeleton,
    392                                       UCalendarDateFields lrgDiffCalUnit,
    393                                       const UnicodeString& intervalPattern,
    394                                       UErrorCode& status);
    395 
    396 
    397     /**given an input skeleton, get the best match skeleton
    398      * which has pre-defined interval pattern in resource file.
    399      * Also return the difference between the input skeleton
    400      * and the best match skeleton.
    401      *
    402      * TODO (xji): set field weight or
    403      *             isolate the funtionality in DateTimePatternGenerator
    404      * @param  skeleton               input skeleton
    405      * @param  bestMatchDistanceInfo  the difference between input skeleton
    406      *                                and best match skeleton.
    407      *         0, if there is exact match for input skeleton
    408      *         1, if there is only field width difference between
    409      *            the best match and the input skeleton
    410      *         2, the only field difference is 'v' and 'z'
    411      *        -1, if there is calendar field difference between
    412      *            the best match and the input skeleton
    413      * @return                        best match skeleton
    414      * @internal ICU 4.0
    415      */
    416     const UnicodeString* getBestSkeleton(const UnicodeString& skeleton,
    417                                          int8_t& bestMatchDistanceInfo) const;
    418 
    419 
    420     /**
    421      * Parse skeleton, save each field's width.
    422      * It is used for looking for best match skeleton,
    423      * and adjust pattern field width.
    424      * @param skeleton            skeleton to be parsed
    425      * @param skeletonFieldWidth  parsed skeleton field width
    426      * @internal ICU 4.0
    427      */
    428     static void U_EXPORT2 parseSkeleton(const UnicodeString& skeleton,
    429                                         int32_t* skeletonFieldWidth);
    430 
    431 
    432     /**
    433      * Check whether one field width is numeric while the other is string.
    434      *
    435      * TODO (xji): make it general
    436      *
    437      * @param fieldWidth          one field width
    438      * @param anotherFieldWidth   another field width
    439      * @param patternLetter       pattern letter char
    440      * @return true if one field width is numeric and the other is string,
    441      *         false otherwise.
    442      * @internal ICU 4.0
    443      */
    444     static UBool U_EXPORT2 stringNumeric(int32_t fieldWidth,
    445                                          int32_t anotherFieldWidth,
    446                                          char patternLetter);
    447 
    448 
    449     /**
    450      * Convert calendar field to the interval pattern index in
    451      * hash table.
    452      *
    453      * Since we only support the following calendar fields:
    454      * ERA, YEAR, MONTH, DATE,  DAY_OF_MONTH, DAY_OF_WEEK,
    455      * AM_PM,  HOUR, HOUR_OF_DAY, and MINUTE,
    456      * We reserve only 4 interval patterns for a skeleton.
    457      *
    458      * @param field    calendar field
    459      * @param status   output param set to success/failure code on exit
    460      * @return  interval pattern index in hash table
    461      * @internal ICU 4.0
    462      */
    463     static IntervalPatternIndex U_EXPORT2 calendarFieldToIntervalIndex(
    464                                                       UCalendarDateFields field,
    465                                                       UErrorCode& status);
    466 
    467 
    468     /**
    469      * delete hash table (of type fIntervalPatterns).
    470      *
    471      * @param hTable  hash table to be deleted
    472      * @internal ICU 4.0
    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      * @internal ICU 4.0
    483      */
    484     Hashtable* initHash(UErrorCode& status);
    485 
    486 
    487 
    488     /**
    489      * copy hash table (of type fIntervalPatterns).
    490      *
    491      * @param source   the source to copy from
    492      * @param target   the target to copy to
    493      * @param status   output param set to success/failure code on exit
    494      * @internal ICU 4.0
    495      */
    496     void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
    497 
    498 
    499     // data members
    500     // fallback interval pattern
    501     UnicodeString fFallbackIntervalPattern;
    502     // default order
    503     UBool fFirstDateInPtnIsLaterDate;
    504 
    505     // HashMap<UnicodeString, UnicodeString[kIPI_MAX_INDEX]>
    506     // HashMap( skeleton, pattern[largest_different_field] )
    507     Hashtable* fIntervalPatterns;
    508 
    509 };// end class DateIntervalInfo
    510 
    511 
    512 inline UBool
    513 DateIntervalInfo::operator!=(const DateIntervalInfo& other) const {
    514     return !operator==(other);
    515 }
    516 
    517 
    518 U_NAMESPACE_END
    519 
    520 #endif
    521 
    522 #endif
    523 
    524