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 "Jan 10, 2007" 90 * and "Feb 20, 2008" 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 "yMMMd", 97 * in en_US, if the largest different calendar field between date1 and date2 98 * is "year", the date interval pattern is "MMM d, yyyy - MMM d, yyyy", 99 * such as "Jan 10, 2007 - Jan 10, 2008". 100 * If the largest different calendar field between date1 and date2 is "month", 101 * the date interval pattern is "MMM d - MMM d, yyyy", 102 * such as "Jan 10 - Feb 10, 2007". 103 * If the largest different calendar field between date1 and date2 is "day", 104 * the date interval pattern is "MMM d-d, yyyy", such as "Jan 10-20, 2007". 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 "{0} - {1}", it means 118 * the first date in the interval pattern for this locale is earlier date. 119 * If the fallback format is "{1} - {0}", 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 "latestFirst:" or "earliestFirst:" to the interval pattern. 123 * For example, if the fallback format is "{0}-{1}", 124 * but for skeleton "yMMMd", the interval pattern when day is different is 125 * "latestFirst:d-d MMM yy", it means by default, the first date in interval 126 * pattern is the earlier date. But for skeleton "yMMMd", when day is different, 127 * the first date in "d-d MMM yy" 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