334 * This API is very basic and is intended to be a building block for more 335 * fancy APIs. The caller tells it exactly what to display in a locale 336 * independent way. While this class automatically provides the correct plural 337 * forms, the grammatical form is otherwise as neutral as possible. It is the 338 * caller's responsibility to handle cut-off logic such as deciding between 339 * displaying "in 7 days" or "in 1 week." This API supports relative dates 340 * involving one single unit. This API does not support relative dates 341 * involving compound units, 342 * e.g "in 5 days and 4 hours" nor does it support parsing. 343 *
344 * This class is mostly thread safe and immutable with the following caveats: 345 * 1. The assignment operator violates Immutability. It must not be used 346 * concurrently with other operations. 347 * 2. Caller must not hold onto adopted pointers. 348 *
349 * This class is not intended for public subclassing. 350 *
351 * Here are some examples of use: 352 *
353 * 354 * UErrorCode status = U_ZERO_ERROR; 355 * UnicodeString appendTo; 356 * RelativeDateTimeFormatter fmt(status); 357 * // Appends "in 1 day" 358 * fmt.format( 359 * 1, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status); 360 * // Appends "in 3 days" 361 * fmt.format( 362 * 3, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status); 363 * // Appends "3.2 years ago" 364 * fmt.format( 365 * 3.2, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, appendTo, status); 366 * // Appends "last Sunday" 367 * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SUNDAY, appendTo, status); 368 * // Appends "this Sunday" 369 * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, appendTo, status); 370 * // Appends "next Sunday" 371 * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SUNDAY, appendTo, status); 372 * // Appends "Sunday" 373 * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, appendTo, status); 374 * 375 * // Appends "yesterday" 376 * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_DAY, appendTo, status); 377 * // Appends "today" 378 * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_DAY, appendTo, status); 379 * // Appends "tomorrow" 380 * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_DAY, appendTo, status); 381 * // Appends "now" 382 * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, appendTo, status); 383 * 384 * 385 *
354 * UErrorCode status = U_ZERO_ERROR; 355 * UnicodeString appendTo; 356 * RelativeDateTimeFormatter fmt(status); 357 * // Appends "in 1 day" 358 * fmt.format( 359 * 1, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status); 360 * // Appends "in 3 days" 361 * fmt.format( 362 * 3, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status); 363 * // Appends "3.2 years ago" 364 * fmt.format( 365 * 3.2, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, appendTo, status); 366 * // Appends "last Sunday" 367 * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SUNDAY, appendTo, status); 368 * // Appends "this Sunday" 369 * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, appendTo, status); 370 * // Appends "next Sunday" 371 * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SUNDAY, appendTo, status); 372 * // Appends "Sunday" 373 * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, appendTo, status); 374 * 375 * // Appends "yesterday" 376 * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_DAY, appendTo, status); 377 * // Appends "today" 378 * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_DAY, appendTo, status); 379 * // Appends "tomorrow" 380 * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_DAY, appendTo, status); 381 * // Appends "now" 382 * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, appendTo, status); 383 * 384 *
387 * In the future, we may add more forms, such as abbreviated/short forms 388 * (3 secs ago), and relative day periods ("yesterday afternoon"), etc. 389 * 390 * The RelativeDateTimeFormatter class is not intended for public subclassing. 391 * 392 * @stable ICU 53 393 */ 394 class U_I18N_API RelativeDateTimeFormatter : public UObject { 395 public: 396 397 /** 398 * Create RelativeDateTimeFormatter with default locale. 399 * @stable ICU 53 400 */ 401 RelativeDateTimeFormatter(UErrorCode& status); 402 403 /** 404 * Create RelativeDateTimeFormatter with given locale. 405 * @stable ICU 53 406 */ 407 RelativeDateTimeFormatter(const Locale& locale, UErrorCode& status); 408 409 /** 410 * Create RelativeDateTimeFormatter with given locale and NumberFormat. 411 * 412 * @param locale the locale 413 * @param nfToAdopt Constructed object takes ownership of this pointer. 414 * It is an error for caller to delete this pointer or change its 415 * contents after calling this constructor. 416 * @param status Any error is returned here. 417 * @stable ICU 53 418 */ 419 RelativeDateTimeFormatter( 420 const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status); 421 422 /** 423 * Create RelativeDateTimeFormatter with given locale, NumberFormat, 424 * and capitalization context. 425 * 426 * @param locale the locale 427 * @param nfToAdopt Constructed object takes ownership of this pointer. 428 * It is an error for caller to delete this pointer or change its 429 * contents after calling this constructor. Caller may pass nullptr for 430 * this argument if they want default number format behavior. 431 * @param style the format style. The UDAT_RELATIVE bit field has no effect. 432 * @param capitalizationContext A value from UDisplayContext that pertains to 433 * capitalization. 434 * @param status Any error is returned here. 435 * @stable ICU 54 436 */ 437 RelativeDateTimeFormatter( 438 const Locale& locale, 439 NumberFormat *nfToAdopt, 440 UDateRelativeDateTimeFormatterStyle style, 441 UDisplayContext capitalizationContext, 442 UErrorCode& status); 443 444 /** 445 * Copy constructor. 446 * @stable ICU 53 447 */ 448 RelativeDateTimeFormatter(const RelativeDateTimeFormatter& other); 449 450 /** 451 * Assignment operator. 452 * @stable ICU 53 453 */ 454 RelativeDateTimeFormatter& operator=( 455 const RelativeDateTimeFormatter& other); 456 457 /** 458 * Destructor. 459 * @stable ICU 53 460 */ 461 virtual ~RelativeDateTimeFormatter(); 462 463 /** 464 * Formats a relative date with a quantity such as "in 5 days" or 465 * "3 months ago" 466 * 467 * This method returns a String. To get more information about the 468 * formatting result, use formatToValue(). 469 * 470 * @param quantity The numerical amount e.g 5. This value is formatted 471 * according to this object's NumberFormat object. 472 * @param direction NEXT means a future relative date; LAST means a past 473 * relative date. If direction is anything else, this method sets 474 * status to U_ILLEGAL_ARGUMENT_ERROR. 475 * @param unit the unit e.g day? month? year? 476 * @param appendTo The string to which the formatted result will be 477 * appended 478 * @param status ICU error code returned here. 479 * @return appendTo 480 * @stable ICU 53 481 */ 482 UnicodeString& format( 483 double quantity, 484 UDateDirection direction, 485 UDateRelativeUnit unit, 486 UnicodeString& appendTo, 487 UErrorCode& status) const; 488 489 /** 490 * Formats a relative date with a quantity such as "in 5 days" or 491 * "3 months ago" 492 * 493 * This method returns a FormattedRelativeDateTime, which exposes more 494 * information than the String returned by format(). 495 * 496 * @param quantity The numerical amount e.g 5. This value is formatted 497 * according to this object's NumberFormat object. 498 * @param direction NEXT means a future relative date; LAST means a past 499 * relative date. If direction is anything else, this method sets 500 * status to U_ILLEGAL_ARGUMENT_ERROR. 501 * @param unit the unit e.g day? month? year? 502 * @param status ICU error code returned here. 503 * @return The formatted relative datetime 504 * @stable ICU 64 505 */ 506 FormattedRelativeDateTime formatToValue( 507 double quantity, 508 UDateDirection direction, 509 UDateRelativeUnit unit, 510 UErrorCode& status) const; 511 512 /** 513 * Formats a relative date without a quantity. 514 * 515 * This method returns a String. To get more information about the 516 * formatting result, use formatToValue(). 517 * 518 * @param direction NEXT, LAST, THIS, etc. 519 * @param unit e.g SATURDAY, DAY, MONTH 520 * @param appendTo The string to which the formatted result will be 521 * appended. If the value of direction is documented as not being fully 522 * supported in all locales then this method leaves appendTo unchanged if 523 * no format string is available. 524 * @param status ICU error code returned here. 525 * @return appendTo 526 * @stable ICU 53 527 */ 528 UnicodeString& format( 529 UDateDirection direction, 530 UDateAbsoluteUnit unit, 531 UnicodeString& appendTo, 532 UErrorCode& status) const; 533 534 /** 535 * Formats a relative date without a quantity. 536 * 537 * This method returns a FormattedRelativeDateTime, which exposes more 538 * information than the String returned by format(). 539 * 540 * If the string is not available in the requested locale, the return 541 * value will be empty (calling toString will give an empty string). 542 * 543 * @param direction NEXT, LAST, THIS, etc. 544 * @param unit e.g SATURDAY, DAY, MONTH 545 * @param status ICU error code returned here. 546 * @return The formatted relative datetime 547 * @stable ICU 64 548 */ 549 FormattedRelativeDateTime formatToValue( 550 UDateDirection direction, 551 UDateAbsoluteUnit unit, 552 UErrorCode& status) const; 553 554 /** 555 * Format a combination of URelativeDateTimeUnit and numeric offset 556 * using a numeric style, e.g. "1 week ago", "in 1 week", 557 * "5 weeks ago", "in 5 weeks". 558 * 559 * This method returns a String. To get more information about the 560 * formatting result, use formatNumericToValue(). 561 * 562 * @param offset The signed offset for the specified unit. This 563 * will be formatted according to this object's 564 * NumberFormat object. 565 * @param unit The unit to use when formatting the relative 566 * date, e.g. UDAT_REL_UNIT_WEEK, 567 * UDAT_REL_UNIT_FRIDAY. 568 * @param appendTo The string to which the formatted result will be 569 * appended. 570 * @param status ICU error code returned here. 571 * @return appendTo 572 * @stable ICU 57 573 */ 574 UnicodeString& formatNumeric( 575 double offset, 576 URelativeDateTimeUnit unit, 577 UnicodeString& appendTo, 578 UErrorCode& status) const; 579 580 /** 581 * Format a combination of URelativeDateTimeUnit and numeric offset 582 * using a numeric style, e.g. "1 week ago", "in 1 week", 583 * "5 weeks ago", "in 5 weeks". 584 * 585 * This method returns a FormattedRelativeDateTime, which exposes more 586 * information than the String returned by formatNumeric(). 587 * 588 * @param offset The signed offset for the specified unit. This 589 * will be formatted according to this object's 590 * NumberFormat object. 591 * @param unit The unit to use when formatting the relative 592 * date, e.g. UDAT_REL_UNIT_WEEK, 593 * UDAT_REL_UNIT_FRIDAY. 594 * @param status ICU error code returned here. 595 * @return The formatted relative datetime 596 * @stable ICU 64 597 */ 598 FormattedRelativeDateTime formatNumericToValue( 599 double offset, 600 URelativeDateTimeUnit unit, 601 UErrorCode& status) const; 602 603 /** 604 * Format a combination of URelativeDateTimeUnit and numeric offset 605 * using a text style if possible, e.g. "last week", "this week", 606 * "next week", "yesterday", "tomorrow". Falls back to numeric 607 * style if no appropriate text term is available for the specified 608 * offset in the object's locale. 609 * 610 * This method returns a String. To get more information about the 611 * formatting result, use formatToValue(). 612 * 613 * @param offset The signed offset for the specified unit. 614 * @param unit The unit to use when formatting the relative 615 * date, e.g. UDAT_REL_UNIT_WEEK, 616 * UDAT_REL_UNIT_FRIDAY. 617 * @param appendTo The string to which the formatted result will be 618 * appended. 619 * @param status ICU error code returned here. 620 * @return appendTo 621 * @stable ICU 57 622 */ 623 UnicodeString& format( 624 double offset, 625 URelativeDateTimeUnit unit, 626 UnicodeString& appendTo, 627 UErrorCode& status) const; 628 629 /** 630 * Format a combination of URelativeDateTimeUnit and numeric offset 631 * using a text style if possible, e.g. "last week", "this week", 632 * "next week", "yesterday", "tomorrow". Falls back to numeric 633 * style if no appropriate text term is available for the specified 634 * offset in the object's locale. 635 * 636 * This method returns a FormattedRelativeDateTime, which exposes more 637 * information than the String returned by format(). 638 * 639 * @param offset The signed offset for the specified unit. 640 * @param unit The unit to use when formatting the relative 641 * date, e.g. UDAT_REL_UNIT_WEEK, 642 * UDAT_REL_UNIT_FRIDAY. 643 * @param status ICU error code returned here. 644 * @return The formatted relative datetime 645 * @stable ICU 64 646 */ 647 FormattedRelativeDateTime formatToValue( 648 double offset, 649 URelativeDateTimeUnit unit, 650 UErrorCode& status) const; 651 652 /** 653 * Combines a relative date string and a time string in this object's 654 * locale. This is done with the same date-time separator used for the 655 * default calendar in this locale. 656 * 657 * @param relativeDateString the relative date, e.g 'yesterday' 658 * @param timeString the time e.g '3:45' 659 * @param appendTo concatenated date and time appended here 660 * @param status ICU error code returned here. 661 * @return appendTo 662 * @stable ICU 53 663 */ 664 UnicodeString& combineDateAndTime( 665 const UnicodeString& relativeDateString, 666 const UnicodeString& timeString, 667 UnicodeString& appendTo, 668 UErrorCode& status) const; 669 670 /** 671 * Returns the NumberFormat this object is using. 672 * 673 * @stable ICU 53 674 */ 675 const NumberFormat& getNumberFormat() const; 676 677 /** 678 * Returns the capitalization context. 679 * 680 * @stable ICU 54 681 */ 682 UDisplayContext getCapitalizationContext() const; 683 684 /** 685 * Returns the format style. 686 * 687 * @stable ICU 54 688 */ 689 UDateRelativeDateTimeFormatterStyle getFormatStyle() const; 690 691 private: 692 const RelativeDateTimeCacheData* fCache; 693 const SharedNumberFormat *fNumberFormat; 694 const SharedPluralRules *fPluralRules; 695 UDateRelativeDateTimeFormatterStyle fStyle; 696 UDisplayContext fContext; 697 #if !UCONFIG_NO_BREAK_ITERATION 698 const SharedBreakIterator *fOptBreakIterator; 699 #else 700 std::nullptr_t fOptBreakIterator = nullptr; 701 #endif // !UCONFIG_NO_BREAK_ITERATION 702 Locale fLocale; 703 void init( 704 NumberFormat *nfToAdopt, 705 #if !UCONFIG_NO_BREAK_ITERATION 706 BreakIterator *brkIter, 707 #else 708 std::nullptr_t, 709 #endif // !UCONFIG_NO_BREAK_ITERATION 710 UErrorCode &status); 711 UnicodeString& adjustForContext(UnicodeString &) const; 712 UBool checkNoAdjustForContext(UErrorCode& status) const; 713 714 template 715 UnicodeString& doFormat( 716 F callback, 717 UnicodeString& appendTo, 718 UErrorCode& status, 719 Args... args) const; 720 721 template 722 FormattedRelativeDateTime doFormatToValue( 723 F callback, 724 UErrorCode& status, 725 Args... args) const; 726 727 void formatImpl( 728 double quantity, 729 UDateDirection direction, 730 UDateRelativeUnit unit, 731 FormattedRelativeDateTimeData& output, 732 UErrorCode& status) const; 733 void formatAbsoluteImpl( 734 UDateDirection direction, 735 UDateAbsoluteUnit unit, 736 FormattedRelativeDateTimeData& output, 737 UErrorCode& status) const; 738 void formatNumericImpl( 739 double offset, 740 URelativeDateTimeUnit unit, 741 FormattedRelativeDateTimeData& output, 742 UErrorCode& status) const; 743 void formatRelativeImpl( 744 double offset, 745 URelativeDateTimeUnit unit, 746 FormattedRelativeDateTimeData& output, 747 UErrorCode& status) const; 748 }; 749 750 U_NAMESPACE_END 751 752 #endif /* !UCONFIG_NO_FORMATTING */ 753 754 #endif /* U_SHOW_CPLUSPLUS_API */ 755 756 #endif /* __RELDATEFMT_H */