1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /******************************************************************************** 4 * Copyright (C) 2008-2016, International Business Machines Corporation and 5 * others. All Rights Reserved. 6 ******************************************************************************* 7 * 8 * File DTITVFMT.H 9 * 10 ******************************************************************************* 11 */ 12 13 #ifndef __DTITVFMT_H__ 14 #define __DTITVFMT_H__ 15 16 17 #include "unicode/utypes.h" 18 19 /** 20 * \file 21 * \brief C++ API: Format and parse date interval in a language-independent manner. 22 */ 23 24 #if !UCONFIG_NO_FORMATTING 25 26 #include "unicode/ucal.h" 27 #include "unicode/smpdtfmt.h" 28 #include "unicode/dtintrv.h" 29 #include "unicode/dtitvinf.h" 30 #include "unicode/dtptngen.h" 31 32 U_NAMESPACE_BEGIN 33 34 35 36 /** 37 * DateIntervalFormat is a class for formatting and parsing date 38 * intervals in a language-independent manner. 39 * Only formatting is supported, parsing is not supported. 40 * 41 * <P> 42 * Date interval means from one date to another date, 43 * for example, from "Jan 11, 2008" to "Jan 18, 2008". 44 * We introduced class DateInterval to represent it. 45 * DateInterval is a pair of UDate, which is 46 * the standard milliseconds since 24:00 GMT, Jan 1, 1970. 47 * 48 * <P> 49 * DateIntervalFormat formats a DateInterval into 50 * text as compactly as possible. 51 * For example, the date interval format from "Jan 11, 2008" to "Jan 18,. 2008" 52 * is "Jan 11-18, 2008" for English. 53 * And it parses text into DateInterval, 54 * although initially, parsing is not supported. 55 * 56 * <P> 57 * There is no structural information in date time patterns. 58 * For any punctuations and string literals inside a date time pattern, 59 * we do not know whether it is just a separator, or a prefix, or a suffix. 60 * Without such information, so, it is difficult to generate a sub-pattern 61 * (or super-pattern) by algorithm. 62 * So, formatting a DateInterval is pattern-driven. It is very 63 * similar to formatting in SimpleDateFormat. 64 * We introduce class DateIntervalInfo to save date interval 65 * patterns, similar to date time pattern in SimpleDateFormat. 66 * 67 * <P> 68 * Logically, the interval patterns are mappings 69 * from (skeleton, the_largest_different_calendar_field) 70 * to (date_interval_pattern). 71 * 72 * <P> 73 * A skeleton 74 * <ol> 75 * <li> 76 * only keeps the field pattern letter and ignores all other parts 77 * in a pattern, such as space, punctuations, and string literals. 78 * </li> 79 * <li> 80 * hides the order of fields. 81 * </li> 82 * <li> 83 * might hide a field's pattern letter length. 84 * </li> 85 * </ol> 86 * 87 * For those non-digit calendar fields, the pattern letter length is 88 * important, such as MMM, MMMM, and MMMMM; EEE and EEEE, 89 * and the field's pattern letter length is honored. 90 * 91 * For the digit calendar fields, such as M or MM, d or dd, yy or yyyy, 92 * the field pattern length is ignored and the best match, which is defined 93 * in date time patterns, will be returned without honor the field pattern 94 * letter length in skeleton. 95 * 96 * <P> 97 * The calendar fields we support for interval formatting are: 98 * year, month, date, day-of-week, am-pm, hour, hour-of-day, minute, and second 99 * (though we do not currently have specific intervalFormat date for skeletons 100 * with seconds). 101 * Those calendar fields can be defined in the following order: 102 * year > month > date > hour (in day) > minute > second 103 * 104 * The largest different calendar fields between 2 calendars is the 105 * first different calendar field in above order. 106 * 107 * For example: the largest different calendar fields between "Jan 10, 2007" 108 * and "Feb 20, 2008" is year. 109 * 110 * <P> 111 * For other calendar fields, the compact interval formatting is not 112 * supported. And the interval format will be fall back to fall-back 113 * patterns, which is mostly "{date0} - {date1}". 114 * 115 * <P> 116 * There is a set of pre-defined static skeleton strings. 117 * There are pre-defined interval patterns for those pre-defined skeletons 118 * in locales' resource files. 119 * For example, for a skeleton UDAT_YEAR_ABBR_MONTH_DAY, which is "yMMMd", 120 * in en_US, if the largest different calendar field between date1 and date2 121 * is "year", the date interval pattern is "MMM d, yyyy - MMM d, yyyy", 122 * such as "Jan 10, 2007 - Jan 10, 2008". 123 * If the largest different calendar field between date1 and date2 is "month", 124 * the date interval pattern is "MMM d - MMM d, yyyy", 125 * such as "Jan 10 - Feb 10, 2007". 126 * If the largest different calendar field between date1 and date2 is "day", 127 * the date interval pattern is "MMM d-d, yyyy", such as "Jan 10-20, 2007". 128 * 129 * For date skeleton, the interval patterns when year, or month, or date is 130 * different are defined in resource files. 131 * For time skeleton, the interval patterns when am/pm, or hour, or minute is 132 * different are defined in resource files. 133 * 134 * <P> 135 * If a skeleton is not found in a locale's DateIntervalInfo, which means 136 * the interval patterns for the skeleton is not defined in resource file, 137 * the interval pattern will falls back to the interval "fallback" pattern 138 * defined in resource file. 139 * If the interval "fallback" pattern is not defined, the default fall-back 140 * is "{date0} - {data1}". 141 * 142 * <P> 143 * For the combination of date and time, 144 * The rule to generate interval patterns are: 145 * <ol> 146 * <li> 147 * when the year, month, or day differs, falls back to fall-back 148 * interval pattern, which mostly is the concatenate the two original 149 * expressions with a separator between, 150 * For example, interval pattern from "Jan 10, 2007 10:10 am" 151 * to "Jan 11, 2007 10:10am" is 152 * "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 153 * </li> 154 * <li> 155 * otherwise, present the date followed by the range expression 156 * for the time. 157 * For example, interval pattern from "Jan 10, 2007 10:10 am" 158 * to "Jan 10, 2007 11:10am" is "Jan 10, 2007 10:10 am - 11:10am" 159 * </li> 160 * </ol> 161 * 162 * 163 * <P> 164 * If two dates are the same, the interval pattern is the single date pattern. 165 * For example, interval pattern from "Jan 10, 2007" to "Jan 10, 2007" is 166 * "Jan 10, 2007". 167 * 168 * Or if the presenting fields between 2 dates have the exact same values, 169 * the interval pattern is the single date pattern. 170 * For example, if user only requests year and month, 171 * the interval pattern from "Jan 10, 2007" to "Jan 20, 2007" is "Jan 2007". 172 * 173 * <P> 174 * DateIntervalFormat needs the following information for correct 175 * formatting: time zone, calendar type, pattern, date format symbols, 176 * and date interval patterns. 177 * It can be instantiated in 2 ways: 178 * <ol> 179 * <li> 180 * create an instance using default or given locale plus given skeleton. 181 * Users are encouraged to created date interval formatter this way and 182 * to use the pre-defined skeleton macros, such as 183 * UDAT_YEAR_NUM_MONTH, which consists the calendar fields and 184 * the format style. 185 * </li> 186 * <li> 187 * create an instance using default or given locale plus given skeleton 188 * plus a given DateIntervalInfo. 189 * This factory method is for powerful users who want to provide their own 190 * interval patterns. 191 * Locale provides the timezone, calendar, and format symbols information. 192 * Local plus skeleton provides full pattern information. 193 * DateIntervalInfo provides the date interval patterns. 194 * </li> 195 * </ol> 196 * 197 * <P> 198 * For the calendar field pattern letter, such as G, y, M, d, a, h, H, m, s etc. 199 * DateIntervalFormat uses the same syntax as that of 200 * DateTime format. 201 * 202 * <P> 203 * Code Sample: general usage 204 * <pre> 205 * \code 206 * // the date interval object which the DateIntervalFormat formats on 207 * // and parses into 208 * DateInterval* dtInterval = new DateInterval(1000*3600*24, 1000*3600*24*2); 209 * UErrorCode status = U_ZERO_ERROR; 210 * DateIntervalFormat* dtIntervalFmt = DateIntervalFormat::createInstance( 211 * UDAT_YEAR_MONTH_DAY, 212 * Locale("en", "GB", ""), status); 213 * UnicodeUnicodeString dateIntervalString; 214 * FieldPosition pos = 0; 215 * // formatting 216 * dtIntervalFmt->format(dtInterval, dateIntervalUnicodeString, pos, status); 217 * delete dtIntervalFmt; 218 * \endcode 219 * </pre> 220 */ 221 222 class U_I18N_API DateIntervalFormat : public Format { 223 public: 224 225 /** 226 * Construct a DateIntervalFormat from skeleton and the default locale. 227 * 228 * This is a convenient override of 229 * createInstance(const UnicodeString& skeleton, const Locale& locale, 230 * UErrorCode&) 231 * with the value of locale as default locale. 232 * 233 * @param skeleton the skeleton on which interval format based. 234 * @param status output param set to success/failure code on exit 235 * @return a date time interval formatter which the caller owns. 236 * @stable ICU 4.0 237 */ 238 static DateIntervalFormat* U_EXPORT2 createInstance( 239 const UnicodeString& skeleton, 240 UErrorCode& status); 241 242 /** 243 * Construct a DateIntervalFormat from skeleton and a given locale. 244 * <P> 245 * In this factory method, 246 * the date interval pattern information is load from resource files. 247 * Users are encouraged to created date interval formatter this way and 248 * to use the pre-defined skeleton macros. 249 * 250 * <P> 251 * There are pre-defined skeletons (defined in udate.h) having predefined 252 * interval patterns in resource files. 253 * Users are encouraged to use those macros. 254 * For example: 255 * DateIntervalFormat::createInstance(UDAT_MONTH_DAY, status) 256 * 257 * The given Locale provides the interval patterns. 258 * For example, for en_GB, if skeleton is UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY, 259 * which is "yMMMEEEd", 260 * the interval patterns defined in resource file to above skeleton are: 261 * "EEE, d MMM, yyyy - EEE, d MMM, yyyy" for year differs, 262 * "EEE, d MMM - EEE, d MMM, yyyy" for month differs, 263 * "EEE, d - EEE, d MMM, yyyy" for day differs, 264 * @param skeleton the skeleton on which the interval format is based. 265 * @param locale the given locale 266 * @param status output param set to success/failure code on exit 267 * @return a date time interval formatter which the caller owns. 268 * @stable ICU 4.0 269 * <p> 270 * <h4>Sample code</h4> 271 * \snippet samples/dtitvfmtsample/dtitvfmtsample.cpp dtitvfmtPreDefined1 272 * \snippet samples/dtitvfmtsample/dtitvfmtsample.cpp dtitvfmtPreDefined 273 * <p> 274 */ 275 276 static DateIntervalFormat* U_EXPORT2 createInstance( 277 const UnicodeString& skeleton, 278 const Locale& locale, 279 UErrorCode& status); 280 281 /** 282 * Construct a DateIntervalFormat from skeleton 283 * DateIntervalInfo, and default locale. 284 * 285 * This is a convenient override of 286 * createInstance(const UnicodeString& skeleton, const Locale& locale, 287 * const DateIntervalInfo& dtitvinf, UErrorCode&) 288 * with the locale value as default locale. 289 * 290 * @param skeleton the skeleton on which interval format based. 291 * @param dtitvinf the DateIntervalInfo object. 292 * @param status output param set to success/failure code on exit 293 * @return a date time interval formatter which the caller owns. 294 * @stable ICU 4.0 295 */ 296 static DateIntervalFormat* U_EXPORT2 createInstance( 297 const UnicodeString& skeleton, 298 const DateIntervalInfo& dtitvinf, 299 UErrorCode& status); 300 301 /** 302 * Construct a DateIntervalFormat from skeleton 303 * a DateIntervalInfo, and the given locale. 304 * 305 * <P> 306 * In this factory method, user provides its own date interval pattern 307 * information, instead of using those pre-defined data in resource file. 308 * This factory method is for powerful users who want to provide their own 309 * interval patterns. 310 * <P> 311 * There are pre-defined skeletons (defined in udate.h) having predefined 312 * interval patterns in resource files. 313 * Users are encouraged to use those macros. 314 * For example: 315 * DateIntervalFormat::createInstance(UDAT_MONTH_DAY, status) 316 * 317 * The DateIntervalInfo provides the interval patterns. 318 * and the DateIntervalInfo ownership remains to the caller. 319 * 320 * User are encouraged to set default interval pattern in DateIntervalInfo 321 * as well, if they want to set other interval patterns ( instead of 322 * reading the interval patterns from resource files). 323 * When the corresponding interval pattern for a largest calendar different 324 * field is not found ( if user not set it ), interval format fallback to 325 * the default interval pattern. 326 * If user does not provide default interval pattern, it fallback to 327 * "{date0} - {date1}" 328 * 329 * @param skeleton the skeleton on which interval format based. 330 * @param locale the given locale 331 * @param dtitvinf the DateIntervalInfo object. 332 * @param status output param set to success/failure code on exit 333 * @return a date time interval formatter which the caller owns. 334 * @stable ICU 4.0 335 * <p> 336 * <h4>Sample code</h4> 337 * \snippet samples/dtitvfmtsample/dtitvfmtsample.cpp dtitvfmtPreDefined1 338 * \snippet samples/dtitvfmtsample/dtitvfmtsample.cpp dtitvfmtCustomized 339 * <p> 340 */ 341 static DateIntervalFormat* U_EXPORT2 createInstance( 342 const UnicodeString& skeleton, 343 const Locale& locale, 344 const DateIntervalInfo& dtitvinf, 345 UErrorCode& status); 346 347 /** 348 * Destructor. 349 * @stable ICU 4.0 350 */ 351 virtual ~DateIntervalFormat(); 352 353 /** 354 * Clone this Format object polymorphically. The caller owns the result and 355 * should delete it when done. 356 * @return A copy of the object. 357 * @stable ICU 4.0 358 */ 359 virtual Format* clone(void) const; 360 361 /** 362 * Return true if the given Format objects are semantically equal. Objects 363 * of different subclasses are considered unequal. 364 * @param other the object to be compared with. 365 * @return true if the given Format objects are semantically equal. 366 * @stable ICU 4.0 367 */ 368 virtual UBool operator==(const Format& other) const; 369 370 /** 371 * Return true if the given Format objects are not semantically equal. 372 * Objects of different subclasses are considered unequal. 373 * @param other the object to be compared with. 374 * @return true if the given Format objects are not semantically equal. 375 * @stable ICU 4.0 376 */ 377 UBool operator!=(const Format& other) const; 378 379 380 using Format::format; 381 382 /** 383 * Format an object to produce a string. This method handles Formattable 384 * objects with a DateInterval type. 385 * If a the Formattable object type is not a DateInterval, 386 * then it returns a failing UErrorCode. 387 * 388 * @param obj The object to format. 389 * Must be a DateInterval. 390 * @param appendTo Output parameter to receive result. 391 * Result is appended to existing contents. 392 * @param fieldPosition On input: an alignment field, if desired. 393 * On output: the offsets of the alignment field. 394 * There may be multiple instances of a given field type 395 * in an interval format; in this case the fieldPosition 396 * offsets refer to the first instance. 397 * @param status Output param filled with success/failure status. 398 * @return Reference to 'appendTo' parameter. 399 * @stable ICU 4.0 400 */ 401 virtual UnicodeString& format(const Formattable& obj, 402 UnicodeString& appendTo, 403 FieldPosition& fieldPosition, 404 UErrorCode& status) const ; 405 406 407 408 /** 409 * Format a DateInterval to produce a string. 410 * 411 * @param dtInterval DateInterval to be formatted. 412 * @param appendTo Output parameter to receive result. 413 * Result is appended to existing contents. 414 * @param fieldPosition On input: an alignment field, if desired. 415 * On output: the offsets of the alignment field. 416 * There may be multiple instances of a given field type 417 * in an interval format; in this case the fieldPosition 418 * offsets refer to the first instance. 419 * @param status Output param filled with success/failure status. 420 * @return Reference to 'appendTo' parameter. 421 * @stable ICU 4.0 422 */ 423 UnicodeString& format(const DateInterval* dtInterval, 424 UnicodeString& appendTo, 425 FieldPosition& fieldPosition, 426 UErrorCode& status) const ; 427 428 429 /** 430 * Format 2 Calendars to produce a string. 431 * 432 * Note: "fromCalendar" and "toCalendar" are not const, 433 * since calendar is not const in SimpleDateFormat::format(Calendar&), 434 * 435 * @param fromCalendar calendar set to the from date in date interval 436 * to be formatted into date interval string 437 * @param toCalendar calendar set to the to date in date interval 438 * to be formatted into date interval string 439 * @param appendTo Output parameter to receive result. 440 * Result is appended to existing contents. 441 * @param fieldPosition On input: an alignment field, if desired. 442 * On output: the offsets of the alignment field. 443 * There may be multiple instances of a given field type 444 * in an interval format; in this case the fieldPosition 445 * offsets refer to the first instance. 446 * @param status Output param filled with success/failure status. 447 * Caller needs to make sure it is SUCCESS 448 * at the function entrance 449 * @return Reference to 'appendTo' parameter. 450 * @stable ICU 4.0 451 */ 452 UnicodeString& format(Calendar& fromCalendar, 453 Calendar& toCalendar, 454 UnicodeString& appendTo, 455 FieldPosition& fieldPosition, 456 UErrorCode& status) const ; 457 458 /** 459 * Date interval parsing is not supported. Please do not use. 460 * <P> 461 * This method should handle parsing of 462 * date time interval strings into Formattable objects with 463 * DateInterval type, which is a pair of UDate. 464 * <P> 465 * Before calling, set parse_pos.index to the offset you want to start 466 * parsing at in the source. After calling, parse_pos.index is the end of 467 * the text you parsed. If error occurs, index is unchanged. 468 * <P> 469 * When parsing, leading whitespace is discarded (with a successful parse), 470 * while trailing whitespace is left as is. 471 * <P> 472 * See Format::parseObject() for more. 473 * 474 * @param source The string to be parsed into an object. 475 * @param result Formattable to be set to the parse result. 476 * If parse fails, return contents are undefined. 477 * @param parse_pos The position to start parsing at. Since no parsing 478 * is supported, upon return this param is unchanged. 479 * @return A newly created Formattable* object, or NULL 480 * on failure. The caller owns this and should 481 * delete it when done. 482 * @internal ICU 4.0 483 */ 484 virtual void parseObject(const UnicodeString& source, 485 Formattable& result, 486 ParsePosition& parse_pos) const; 487 488 489 /** 490 * Gets the date time interval patterns. 491 * @return the date time interval patterns associated with 492 * this date interval formatter. 493 * @stable ICU 4.0 494 */ 495 const DateIntervalInfo* getDateIntervalInfo(void) const; 496 497 498 /** 499 * Set the date time interval patterns. 500 * @param newIntervalPatterns the given interval patterns to copy. 501 * @param status output param set to success/failure code on exit 502 * @stable ICU 4.0 503 */ 504 void setDateIntervalInfo(const DateIntervalInfo& newIntervalPatterns, 505 UErrorCode& status); 506 507 508 /** 509 * Gets the date formatter. The DateIntervalFormat instance continues to own 510 * the returned DateFormatter object, and will use and possibly modify it 511 * during format operations. In a multi-threaded environment, the returned 512 * DateFormat can only be used if it is certain that no other threads are 513 * concurrently using this DateIntervalFormatter, even for nominally const 514 * functions. 515 * 516 * @return the date formatter associated with this date interval formatter. 517 * @stable ICU 4.0 518 */ 519 const DateFormat* getDateFormat(void) const; 520 521 /** 522 * Returns a reference to the TimeZone used by this DateIntervalFormat's calendar. 523 * @return the time zone associated with the calendar of DateIntervalFormat. 524 * @stable ICU 4.8 525 */ 526 virtual const TimeZone& getTimeZone(void) const; 527 528 /** 529 * Sets the time zone for the calendar used by this DateIntervalFormat object. The 530 * caller no longer owns the TimeZone object and should not delete it after this call. 531 * @param zoneToAdopt the TimeZone to be adopted. 532 * @stable ICU 4.8 533 */ 534 virtual void adoptTimeZone(TimeZone* zoneToAdopt); 535 536 /** 537 * Sets the time zone for the calendar used by this DateIntervalFormat object. 538 * @param zone the new time zone. 539 * @stable ICU 4.8 540 */ 541 virtual void setTimeZone(const TimeZone& zone); 542 543 /** 544 * Return the class ID for this class. This is useful only for comparing to 545 * a return value from getDynamicClassID(). For example: 546 * <pre> 547 * . Base* polymorphic_pointer = createPolymorphicObject(); 548 * . if (polymorphic_pointer->getDynamicClassID() == 549 * . erived::getStaticClassID()) ... 550 * </pre> 551 * @return The class ID for all objects of this class. 552 * @stable ICU 4.0 553 */ 554 static UClassID U_EXPORT2 getStaticClassID(void); 555 556 /** 557 * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This 558 * method is to implement a simple version of RTTI, since not all C++ 559 * compilers support genuine RTTI. Polymorphic operator==() and clone() 560 * methods call this method. 561 * 562 * @return The class ID for this object. All objects of a 563 * given class have the same class ID. Objects of 564 * other classes have different class IDs. 565 * @stable ICU 4.0 566 */ 567 virtual UClassID getDynamicClassID(void) const; 568 569 protected: 570 571 /** 572 * Copy constructor. 573 * @stable ICU 4.0 574 */ 575 DateIntervalFormat(const DateIntervalFormat&); 576 577 /** 578 * Assignment operator. 579 * @stable ICU 4.0 580 */ 581 DateIntervalFormat& operator=(const DateIntervalFormat&); 582 583 private: 584 585 /* 586 * This is for ICU internal use only. Please do not use. 587 * Save the interval pattern information. 588 * Interval pattern consists of 2 single date patterns and the separator. 589 * For example, interval pattern "MMM d - MMM d, yyyy" consists 590 * a single date pattern "MMM d", another single date pattern "MMM d, yyyy", 591 * and a separator "-". 592 * The pattern is divided into 2 parts. For above example, 593 * the first part is "MMM d - ", and the second part is "MMM d, yyyy". 594 * Also, the first date appears in an interval pattern could be 595 * the earlier date or the later date. 596 * And such information is saved in the interval pattern as well. 597 */ 598 struct PatternInfo { 599 UnicodeString firstPart; 600 UnicodeString secondPart; 601 /** 602 * Whether the first date in interval pattern is later date or not. 603 * Fallback format set the default ordering. 604 * And for a particular interval pattern, the order can be 605 * overriden by prefixing the interval pattern with "latestFirst:" or 606 * "earliestFirst:" 607 * For example, given 2 date, Jan 10, 2007 to Feb 10, 2007. 608 * if the fallback format is "{0} - {1}", 609 * and the pattern is "d MMM - d MMM yyyy", the interval format is 610 * "10 Jan - 10 Feb, 2007". 611 * If the pattern is "latestFirst:d MMM - d MMM yyyy", 612 * the interval format is "10 Feb - 10 Jan, 2007" 613 */ 614 UBool laterDateFirst; 615 }; 616 617 618 /** 619 * default constructor 620 * @internal (private) 621 */ 622 DateIntervalFormat(); 623 624 /** 625 * Construct a DateIntervalFormat from DateFormat, 626 * a DateIntervalInfo, and skeleton. 627 * DateFormat provides the timezone, calendar, 628 * full pattern, and date format symbols information. 629 * It should be a SimpleDateFormat object which 630 * has a pattern in it. 631 * the DateIntervalInfo provides the interval patterns. 632 * 633 * Note: the DateIntervalFormat takes ownership of both 634 * DateFormat and DateIntervalInfo objects. 635 * Caller should not delete them. 636 * 637 * @param locale the locale of this date interval formatter. 638 * @param dtItvInfo the DateIntervalInfo object to be adopted. 639 * @param skeleton the skeleton of the date formatter 640 * @param status output param set to success/failure code on exit 641 */ 642 DateIntervalFormat(const Locale& locale, DateIntervalInfo* dtItvInfo, 643 const UnicodeString* skeleton, UErrorCode& status); 644 645 646 /** 647 * Construct a DateIntervalFormat from DateFormat 648 * and a DateIntervalInfo. 649 * 650 * It is a wrapper of the constructor. 651 * 652 * @param locale the locale of this date interval formatter. 653 * @param dtitvinf the DateIntervalInfo object to be adopted. 654 * @param skeleton the skeleton of this formatter. 655 * @param status Output param set to success/failure code. 656 * @return a date time interval formatter which the caller owns. 657 */ 658 static DateIntervalFormat* U_EXPORT2 create(const Locale& locale, 659 DateIntervalInfo* dtitvinf, 660 const UnicodeString* skeleton, 661 UErrorCode& status); 662 663 /** 664 * Below are for generating interval patterns local to the formatter 665 */ 666 667 /** 668 * Provide an updated FieldPosition posResult based on two formats, 669 * the FieldPosition values for each of them, and the pattern used 670 * to combine them. The idea is for posResult to indicate the first 671 * instance (if any) of the specified field in the combined result, 672 * with correct offsets. 673 * 674 * @param combiningPattern Pattern used to combine pat0 and pat1 675 * @param pat0 Formatted date/time value to replace {0} 676 * @param pos0 FieldPosition within pat0 677 * @param pat1 Formatted date/time value to replace {1} 678 * @param pos1 FieldPosition within pat1 679 * @param posResult FieldPosition to be set to the correct 680 * position of the first field instance when 681 * pat0 and pat1 are combined using combiningPattern 682 */ 683 static void 684 adjustPosition(UnicodeString& combiningPattern, // has {0} and {1} in it 685 UnicodeString& pat0, FieldPosition& pos0, // pattern and pos corresponding to {0} 686 UnicodeString& pat1, FieldPosition& pos1, // pattern and pos corresponding to {1} 687 FieldPosition& posResult); 688 689 690 /** 691 * Format 2 Calendars using fall-back interval pattern 692 * 693 * The full pattern used in this fall-back format is the 694 * full pattern of the date formatter. 695 * 696 * gFormatterMutex must already be locked when calling this function. 697 * 698 * @param fromCalendar calendar set to the from date in date interval 699 * to be formatted into date interval string 700 * @param toCalendar calendar set to the to date in date interval 701 * to be formatted into date interval string 702 * @param fromToOnSameDay TRUE iff from and to dates are on the same day 703 * (any difference is in ampm/hours or below) 704 * @param appendTo Output parameter to receive result. 705 * Result is appended to existing contents. 706 * @param pos On input: an alignment field, if desired. 707 * On output: the offsets of the alignment field. 708 * @param status output param set to success/failure code on exit 709 * @return Reference to 'appendTo' parameter. 710 * @internal (private) 711 */ 712 UnicodeString& fallbackFormat(Calendar& fromCalendar, 713 Calendar& toCalendar, 714 UBool fromToOnSameDay, 715 UnicodeString& appendTo, 716 FieldPosition& pos, 717 UErrorCode& status) const; 718 719 720 721 /** 722 * Initialize interval patterns locale to this formatter 723 * 724 * This code is a bit complicated since 725 * 1. the interval patterns saved in resource bundle files are interval 726 * patterns based on date or time only. 727 * It does not have interval patterns based on both date and time. 728 * Interval patterns on both date and time are algorithm generated. 729 * 730 * For example, it has interval patterns on skeleton "dMy" and "hm", 731 * but it does not have interval patterns on skeleton "dMyhm". 732 * 733 * The rule to generate interval patterns for both date and time skeleton are 734 * 1) when the year, month, or day differs, concatenate the two original 735 * expressions with a separator between, 736 * For example, interval pattern from "Jan 10, 2007 10:10 am" 737 * to "Jan 11, 2007 10:10am" is 738 * "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 739 * 740 * 2) otherwise, present the date followed by the range expression 741 * for the time. 742 * For example, interval pattern from "Jan 10, 2007 10:10 am" 743 * to "Jan 10, 2007 11:10am" is 744 * "Jan 10, 2007 10:10 am - 11:10am" 745 * 746 * 2. even a pattern does not request a certain calendar field, 747 * the interval pattern needs to include such field if such fields are 748 * different between 2 dates. 749 * For example, a pattern/skeleton is "hm", but the interval pattern 750 * includes year, month, and date when year, month, and date differs. 751 * 752 * 753 * @param status output param set to success/failure code on exit 754 */ 755 void initializePattern(UErrorCode& status); 756 757 758 759 /** 760 * Set fall back interval pattern given a calendar field, 761 * a skeleton, and a date time pattern generator. 762 * @param field the largest different calendar field 763 * @param skeleton a skeleton 764 * @param status output param set to success/failure code on exit 765 */ 766 void setFallbackPattern(UCalendarDateFields field, 767 const UnicodeString& skeleton, 768 UErrorCode& status); 769 770 771 772 /** 773 * get separated date and time skeleton from a combined skeleton. 774 * 775 * The difference between date skeleton and normalizedDateSkeleton are: 776 * 1. both 'y' and 'd' are appeared only once in normalizeDateSkeleton 777 * 2. 'E' and 'EE' are normalized into 'EEE' 778 * 3. 'MM' is normalized into 'M' 779 * 780 ** the difference between time skeleton and normalizedTimeSkeleton are: 781 * 1. both 'H' and 'h' are normalized as 'h' in normalized time skeleton, 782 * 2. 'a' is omitted in normalized time skeleton. 783 * 3. there is only one appearance for 'h', 'm','v', 'z' in normalized time 784 * skeleton 785 * 786 * 787 * @param skeleton given combined skeleton. 788 * @param date Output parameter for date only skeleton. 789 * @param normalizedDate Output parameter for normalized date only 790 * 791 * @param time Output parameter for time only skeleton. 792 * @param normalizedTime Output parameter for normalized time only 793 * skeleton. 794 * 795 */ 796 static void U_EXPORT2 getDateTimeSkeleton(const UnicodeString& skeleton, 797 UnicodeString& date, 798 UnicodeString& normalizedDate, 799 UnicodeString& time, 800 UnicodeString& normalizedTime); 801 802 803 804 /** 805 * Generate date or time interval pattern from resource, 806 * and set them into the interval pattern locale to this formatter. 807 * 808 * It needs to handle the following: 809 * 1. need to adjust field width. 810 * For example, the interval patterns saved in DateIntervalInfo 811 * includes "dMMMy", but not "dMMMMy". 812 * Need to get interval patterns for dMMMMy from dMMMy. 813 * Another example, the interval patterns saved in DateIntervalInfo 814 * includes "hmv", but not "hmz". 815 * Need to get interval patterns for "hmz' from 'hmv' 816 * 817 * 2. there might be no pattern for 'y' differ for skeleton "Md", 818 * in order to get interval patterns for 'y' differ, 819 * need to look for it from skeleton 'yMd' 820 * 821 * @param dateSkeleton normalized date skeleton 822 * @param timeSkeleton normalized time skeleton 823 * @return whether the resource is found for the skeleton. 824 * TRUE if interval pattern found for the skeleton, 825 * FALSE otherwise. 826 */ 827 UBool setSeparateDateTimePtn(const UnicodeString& dateSkeleton, 828 const UnicodeString& timeSkeleton); 829 830 831 832 833 /** 834 * Generate interval pattern from existing resource 835 * 836 * It not only save the interval patterns, 837 * but also return the extended skeleton and its best match skeleton. 838 * 839 * @param field largest different calendar field 840 * @param skeleton skeleton 841 * @param bestSkeleton the best match skeleton which has interval pattern 842 * defined in resource 843 * @param differenceInfo the difference between skeleton and best skeleton 844 * 0 means the best matched skeleton is the same as input skeleton 845 * 1 means the fields are the same, but field width are different 846 * 2 means the only difference between fields are v/z, 847 * -1 means there are other fields difference 848 * 849 * @param extendedSkeleton extended skeleton 850 * @param extendedBestSkeleton extended best match skeleton 851 * @return whether the interval pattern is found 852 * through extending skeleton or not. 853 * TRUE if interval pattern is found by 854 * extending skeleton, FALSE otherwise. 855 */ 856 UBool setIntervalPattern(UCalendarDateFields field, 857 const UnicodeString* skeleton, 858 const UnicodeString* bestSkeleton, 859 int8_t differenceInfo, 860 UnicodeString* extendedSkeleton = NULL, 861 UnicodeString* extendedBestSkeleton = NULL); 862 863 /** 864 * Adjust field width in best match interval pattern to match 865 * the field width in input skeleton. 866 * 867 * TODO (xji) make a general solution 868 * The adjusting rule can be: 869 * 1. always adjust 870 * 2. never adjust 871 * 3. default adjust, which means adjust according to the following rules 872 * 3.1 always adjust string, such as MMM and MMMM 873 * 3.2 never adjust between string and numeric, such as MM and MMM 874 * 3.3 always adjust year 875 * 3.4 do not adjust 'd', 'h', or 'm' if h presents 876 * 3.5 do not adjust 'M' if it is numeric(?) 877 * 878 * Since date interval format is well-formed format, 879 * date and time skeletons are normalized previously, 880 * till this stage, the adjust here is only "adjust strings, such as MMM 881 * and MMMM, EEE and EEEE. 882 * 883 * @param inputSkeleton the input skeleton 884 * @param bestMatchSkeleton the best match skeleton 885 * @param bestMatchIntervalPattern the best match interval pattern 886 * @param differenceInfo the difference between 2 skeletons 887 * 1 means only field width differs 888 * 2 means v/z exchange 889 * @param adjustedIntervalPattern adjusted interval pattern 890 */ 891 static void U_EXPORT2 adjustFieldWidth( 892 const UnicodeString& inputSkeleton, 893 const UnicodeString& bestMatchSkeleton, 894 const UnicodeString& bestMatchIntervalPattern, 895 int8_t differenceInfo, 896 UnicodeString& adjustedIntervalPattern); 897 898 /** 899 * Concat a single date pattern with a time interval pattern, 900 * set it into the intervalPatterns, while field is time field. 901 * This is used to handle time interval patterns on skeleton with 902 * both time and date. Present the date followed by 903 * the range expression for the time. 904 * @param format date and time format 905 * @param datePattern date pattern 906 * @param field time calendar field: AM_PM, HOUR, MINUTE 907 * @param status output param set to success/failure code on exit 908 */ 909 void concatSingleDate2TimeInterval(UnicodeString& format, 910 const UnicodeString& datePattern, 911 UCalendarDateFields field, 912 UErrorCode& status); 913 914 /** 915 * check whether a calendar field present in a skeleton. 916 * @param field calendar field need to check 917 * @param skeleton given skeleton on which to check the calendar field 918 * @return true if field present in a skeleton. 919 */ 920 static UBool U_EXPORT2 fieldExistsInSkeleton(UCalendarDateFields field, 921 const UnicodeString& skeleton); 922 923 924 /** 925 * Split interval patterns into 2 part. 926 * @param intervalPattern interval pattern 927 * @return the index in interval pattern which split the pattern into 2 part 928 */ 929 static int32_t U_EXPORT2 splitPatternInto2Part(const UnicodeString& intervalPattern); 930 931 932 /** 933 * Break interval patterns as 2 part and save them into pattern info. 934 * @param field calendar field 935 * @param intervalPattern interval pattern 936 */ 937 void setIntervalPattern(UCalendarDateFields field, 938 const UnicodeString& intervalPattern); 939 940 941 /** 942 * Break interval patterns as 2 part and save them into pattern info. 943 * @param field calendar field 944 * @param intervalPattern interval pattern 945 * @param laterDateFirst whether later date appear first in interval pattern 946 */ 947 void setIntervalPattern(UCalendarDateFields field, 948 const UnicodeString& intervalPattern, 949 UBool laterDateFirst); 950 951 952 /** 953 * Set pattern information. 954 * 955 * @param field calendar field 956 * @param firstPart the first part in interval pattern 957 * @param secondPart the second part in interval pattern 958 * @param laterDateFirst whether the first date in intervalPattern 959 * is earlier date or later date 960 */ 961 void setPatternInfo(UCalendarDateFields field, 962 const UnicodeString* firstPart, 963 const UnicodeString* secondPart, 964 UBool laterDateFirst); 965 966 /** 967 * Format 2 Calendars to produce a string. 968 * Implementation of the similar public format function. 969 * Must be called with gFormatterMutex already locked. 970 * 971 * Note: "fromCalendar" and "toCalendar" are not const, 972 * since calendar is not const in SimpleDateFormat::format(Calendar&), 973 * 974 * @param fromCalendar calendar set to the from date in date interval 975 * to be formatted into date interval string 976 * @param toCalendar calendar set to the to date in date interval 977 * to be formatted into date interval string 978 * @param appendTo Output parameter to receive result. 979 * Result is appended to existing contents. 980 * @param fieldPosition On input: an alignment field, if desired. 981 * On output: the offsets of the alignment field. 982 * There may be multiple instances of a given field type 983 * in an interval format; in this case the fieldPosition 984 * offsets refer to the first instance. 985 * @param status Output param filled with success/failure status. 986 * Caller needs to make sure it is SUCCESS 987 * at the function entrance 988 * @return Reference to 'appendTo' parameter. 989 * @internal (private) 990 */ 991 UnicodeString& formatImpl(Calendar& fromCalendar, 992 Calendar& toCalendar, 993 UnicodeString& appendTo, 994 FieldPosition& fieldPosition, 995 UErrorCode& status) const ; 996 997 998 // from calendar field to pattern letter 999 static const char16_t fgCalendarFieldToPatternLetter[]; 1000 1001 1002 /** 1003 * The interval patterns for this locale. 1004 */ 1005 DateIntervalInfo* fInfo; 1006 1007 /** 1008 * The DateFormat object used to format single pattern 1009 */ 1010 SimpleDateFormat* fDateFormat; 1011 1012 /** 1013 * The 2 calendars with the from and to date. 1014 * could re-use the calendar in fDateFormat, 1015 * but keeping 2 calendars make it clear and clean. 1016 */ 1017 Calendar* fFromCalendar; 1018 Calendar* fToCalendar; 1019 1020 Locale fLocale; 1021 1022 /** 1023 * Following are interval information relevant (locale) to this formatter. 1024 */ 1025 UnicodeString fSkeleton; 1026 PatternInfo fIntervalPatterns[DateIntervalInfo::kIPI_MAX_INDEX]; 1027 1028 /** 1029 * Patterns for fallback formatting. 1030 */ 1031 UnicodeString* fDatePattern; 1032 UnicodeString* fTimePattern; 1033 UnicodeString* fDateTimeFormat; 1034 }; 1035 1036 inline UBool 1037 DateIntervalFormat::operator!=(const Format& other) const { 1038 return !operator==(other); 1039 } 1040 1041 U_NAMESPACE_END 1042 1043 #endif /* #if !UCONFIG_NO_FORMATTING */ 1044 1045 #endif // _DTITVFMT_H__ 1046 //eof 1047