1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *****************************************************************************
5 * Copyright (C) 2014-2016, International Business Machines Corporation and
8 *****************************************************************************
11 *****************************************************************************
14 #ifndef __RELDATEFMT_H
15 #define __RELDATEFMT_H
17 #include "unicode/utypes.h"
18 #include "unicode/uobject.h"
19 #include "unicode/udisplaycontext.h"
20 #include "unicode/ureldatefmt.h"
21 #include "unicode/locid.h"
22 #include "unicode/formattedvalue.h"
26 * \brief C++ API: Formats relative dates such as "1 day ago" or "tomorrow"
29 #if !UCONFIG_NO_FORMATTING
32 * Represents the unit for formatting a relative date. e.g "in 5 days"
36 typedef enum UDateRelativeUnit
{
42 UDAT_RELATIVE_SECONDS
,
48 UDAT_RELATIVE_MINUTES
,
80 #ifndef U_HIDE_DEPRECATED_API
82 * One more than the highest normal UDateRelativeUnit value.
83 * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
85 UDAT_RELATIVE_UNIT_COUNT
86 #endif // U_HIDE_DEPRECATED_API
90 * Represents an absolute unit.
93 typedef enum UDateAbsoluteUnit
{
95 // Days of week have to remain together and in order from Sunday to
101 UDAT_ABSOLUTE_SUNDAY
,
107 UDAT_ABSOLUTE_MONDAY
,
113 UDAT_ABSOLUTE_TUESDAY
,
119 UDAT_ABSOLUTE_WEDNESDAY
,
125 UDAT_ABSOLUTE_THURSDAY
,
131 UDAT_ABSOLUTE_FRIDAY
,
137 UDAT_ABSOLUTE_SATURDAY
,
169 #ifndef U_HIDE_DRAFT_API
174 UDAT_ABSOLUTE_QUARTER
,
175 #endif // U_HIDE_DRAFT_API
177 #ifndef U_HIDE_DEPRECATED_API
179 * One more than the highest normal UDateAbsoluteUnit value.
180 * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
182 UDAT_ABSOLUTE_UNIT_COUNT
= UDAT_ABSOLUTE_NOW
+ 2
183 #endif // U_HIDE_DEPRECATED_API
187 * Represents a direction for an absolute unit e.g "Next Tuesday"
191 typedef enum UDateDirection
{
194 * Two before. Not fully supported in every locale.
197 UDAT_DIRECTION_LAST_2
,
218 * Two after. Not fully supported in every locale.
221 UDAT_DIRECTION_NEXT_2
,
224 * Plain, which means the absence of a qualifier.
227 UDAT_DIRECTION_PLAIN
,
229 #ifndef U_HIDE_DEPRECATED_API
231 * One more than the highest normal UDateDirection value.
232 * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
235 #endif // U_HIDE_DEPRECATED_API
238 #if !UCONFIG_NO_BREAK_ITERATION
240 #if U_SHOW_CPLUSPLUS_API
244 class RelativeDateTimeCacheData
;
245 class SharedNumberFormat
;
246 class SharedPluralRules
;
247 class SharedBreakIterator
;
250 class FormattedRelativeDateTimeData
;
252 #ifndef U_HIDE_DRAFT_API
254 * An immutable class containing the result of a relative datetime formatting operation.
256 * Instances of this class are immutable and thread-safe.
258 * Not intended for public subclassing.
262 class U_I18N_API FormattedRelativeDateTime
: public UMemory
, public FormattedValue
{
265 * Default constructor; makes an empty FormattedRelativeDateTime.
268 FormattedRelativeDateTime() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR
) {}
271 * Move constructor: Leaves the source FormattedRelativeDateTime in an undefined state.
274 FormattedRelativeDateTime(FormattedRelativeDateTime
&& src
) U_NOEXCEPT
;
277 * Destruct an instance of FormattedRelativeDateTime.
280 virtual ~FormattedRelativeDateTime() U_OVERRIDE
;
282 /** Copying not supported; use move constructor instead. */
283 FormattedRelativeDateTime(const FormattedRelativeDateTime
&) = delete;
285 /** Copying not supported; use move assignment instead. */
286 FormattedRelativeDateTime
& operator=(const FormattedRelativeDateTime
&) = delete;
289 * Move assignment: Leaves the source FormattedRelativeDateTime in an undefined state.
292 FormattedRelativeDateTime
& operator=(FormattedRelativeDateTime
&& src
) U_NOEXCEPT
;
294 /** @copydoc FormattedValue::toString() */
295 UnicodeString
toString(UErrorCode
& status
) const U_OVERRIDE
;
297 /** @copydoc FormattedValue::toTempString() */
298 UnicodeString
toTempString(UErrorCode
& status
) const U_OVERRIDE
;
300 /** @copydoc FormattedValue::appendTo() */
301 Appendable
&appendTo(Appendable
& appendable
, UErrorCode
& status
) const U_OVERRIDE
;
303 /** @copydoc FormattedValue::nextPosition() */
304 UBool
nextPosition(ConstrainedFieldPosition
& cfpos
, UErrorCode
& status
) const U_OVERRIDE
;
307 FormattedRelativeDateTimeData
*fData
;
308 UErrorCode fErrorCode
;
309 explicit FormattedRelativeDateTime(FormattedRelativeDateTimeData
*results
)
310 : fData(results
), fErrorCode(U_ZERO_ERROR
) {}
311 explicit FormattedRelativeDateTime(UErrorCode errorCode
)
312 : fData(nullptr), fErrorCode(errorCode
) {}
313 friend class RelativeDateTimeFormatter
;
315 #endif /* U_HIDE_DRAFT_API */
318 * Formats simple relative dates. There are two types of relative dates that
321 * <li>relative dates with a quantity e.g "in 5 days"</li>
322 * <li>relative dates without a quantity e.g "next Tuesday"</li>
325 * This API is very basic and is intended to be a building block for more
326 * fancy APIs. The caller tells it exactly what to display in a locale
327 * independent way. While this class automatically provides the correct plural
328 * forms, the grammatical form is otherwise as neutral as possible. It is the
329 * caller's responsibility to handle cut-off logic such as deciding between
330 * displaying "in 7 days" or "in 1 week." This API supports relative dates
331 * involving one single unit. This API does not support relative dates
332 * involving compound units,
333 * e.g "in 5 days and 4 hours" nor does it support parsing.
335 * This class is mostly thread safe and immutable with the following caveats:
336 * 1. The assignment operator violates Immutability. It must not be used
337 * concurrently with other operations.
338 * 2. Caller must not hold onto adopted pointers.
340 * This class is not intended for public subclassing.
342 * Here are some examples of use:
345 * UErrorCode status = U_ZERO_ERROR;
346 * UnicodeString appendTo;
347 * RelativeDateTimeFormatter fmt(status);
348 * // Appends "in 1 day"
350 * 1, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status);
351 * // Appends "in 3 days"
353 * 3, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status);
354 * // Appends "3.2 years ago"
356 * 3.2, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, appendTo, status);
357 * // Appends "last Sunday"
358 * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
359 * // Appends "this Sunday"
360 * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
361 * // Appends "next Sunday"
362 * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
363 * // Appends "Sunday"
364 * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
366 * // Appends "yesterday"
367 * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_DAY, appendTo, status);
369 * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_DAY, appendTo, status);
370 * // Appends "tomorrow"
371 * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_DAY, appendTo, status);
373 * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, appendTo, status);
378 * In the future, we may add more forms, such as abbreviated/short forms
379 * (3 secs ago), and relative day periods ("yesterday afternoon"), etc.
381 * The RelativeDateTimeFormatter class is not intended for public subclassing.
385 class U_I18N_API RelativeDateTimeFormatter
: public UObject
{
389 * Create RelativeDateTimeFormatter with default locale.
392 RelativeDateTimeFormatter(UErrorCode
& status
);
395 * Create RelativeDateTimeFormatter with given locale.
398 RelativeDateTimeFormatter(const Locale
& locale
, UErrorCode
& status
);
401 * Create RelativeDateTimeFormatter with given locale and NumberFormat.
403 * @param locale the locale
404 * @param nfToAdopt Constructed object takes ownership of this pointer.
405 * It is an error for caller to delete this pointer or change its
406 * contents after calling this constructor.
407 * @param status Any error is returned here.
410 RelativeDateTimeFormatter(
411 const Locale
& locale
, NumberFormat
*nfToAdopt
, UErrorCode
& status
);
414 * Create RelativeDateTimeFormatter with given locale, NumberFormat,
415 * and capitalization context.
417 * @param locale the locale
418 * @param nfToAdopt Constructed object takes ownership of this pointer.
419 * It is an error for caller to delete this pointer or change its
420 * contents after calling this constructor. Caller may pass NULL for
421 * this argument if they want default number format behavior.
422 * @param style the format style. The UDAT_RELATIVE bit field has no effect.
423 * @param capitalizationContext A value from UDisplayContext that pertains to
425 * @param status Any error is returned here.
428 RelativeDateTimeFormatter(
429 const Locale
& locale
,
430 NumberFormat
*nfToAdopt
,
431 UDateRelativeDateTimeFormatterStyle style
,
432 UDisplayContext capitalizationContext
,
439 RelativeDateTimeFormatter(const RelativeDateTimeFormatter
& other
);
442 * Assignment operator.
445 RelativeDateTimeFormatter
& operator=(
446 const RelativeDateTimeFormatter
& other
);
452 virtual ~RelativeDateTimeFormatter();
455 * Formats a relative date with a quantity such as "in 5 days" or
458 * This method returns a String. To get more information about the
459 * formatting result, use formatToValue().
461 * @param quantity The numerical amount e.g 5. This value is formatted
462 * according to this object's NumberFormat object.
463 * @param direction NEXT means a future relative date; LAST means a past
464 * relative date. If direction is anything else, this method sets
465 * status to U_ILLEGAL_ARGUMENT_ERROR.
466 * @param unit the unit e.g day? month? year?
467 * @param appendTo The string to which the formatted result will be
469 * @param status ICU error code returned here.
473 UnicodeString
& format(
475 UDateDirection direction
,
476 UDateRelativeUnit unit
,
477 UnicodeString
& appendTo
,
478 UErrorCode
& status
) const;
480 #ifndef U_HIDE_DRAFT_API
482 * Formats a relative date with a quantity such as "in 5 days" or
485 * This method returns a FormattedRelativeDateTime, which exposes more
486 * information than the String returned by format().
488 * @param quantity The numerical amount e.g 5. This value is formatted
489 * according to this object's NumberFormat object.
490 * @param direction NEXT means a future relative date; LAST means a past
491 * relative date. If direction is anything else, this method sets
492 * status to U_ILLEGAL_ARGUMENT_ERROR.
493 * @param unit the unit e.g day? month? year?
494 * @param status ICU error code returned here.
495 * @return The formatted relative datetime
498 FormattedRelativeDateTime
formatToValue(
500 UDateDirection direction
,
501 UDateRelativeUnit unit
,
502 UErrorCode
& status
) const;
503 #endif /* U_HIDE_DRAFT_API */
506 * Formats a relative date without a quantity.
508 * This method returns a String. To get more information about the
509 * formatting result, use formatToValue().
511 * @param direction NEXT, LAST, THIS, etc.
512 * @param unit e.g SATURDAY, DAY, MONTH
513 * @param appendTo The string to which the formatted result will be
514 * appended. If the value of direction is documented as not being fully
515 * supported in all locales then this method leaves appendTo unchanged if
516 * no format string is available.
517 * @param status ICU error code returned here.
521 UnicodeString
& format(
522 UDateDirection direction
,
523 UDateAbsoluteUnit unit
,
524 UnicodeString
& appendTo
,
525 UErrorCode
& status
) const;
527 #ifndef U_HIDE_DRAFT_API
529 * Formats a relative date without a quantity.
531 * This method returns a FormattedRelativeDateTime, which exposes more
532 * information than the String returned by format().
534 * If the string is not available in the requested locale, the return
535 * value will be empty (calling toString will give an empty string).
537 * @param direction NEXT, LAST, THIS, etc.
538 * @param unit e.g SATURDAY, DAY, MONTH
539 * @param status ICU error code returned here.
540 * @return The formatted relative datetime
543 FormattedRelativeDateTime
formatToValue(
544 UDateDirection direction
,
545 UDateAbsoluteUnit unit
,
546 UErrorCode
& status
) const;
547 #endif /* U_HIDE_DRAFT_API */
550 * Format a combination of URelativeDateTimeUnit and numeric offset
551 * using a numeric style, e.g. "1 week ago", "in 1 week",
552 * "5 weeks ago", "in 5 weeks".
554 * This method returns a String. To get more information about the
555 * formatting result, use formatNumericToValue().
557 * @param offset The signed offset for the specified unit. This
558 * will be formatted according to this object's
559 * NumberFormat object.
560 * @param unit The unit to use when formatting the relative
561 * date, e.g. UDAT_REL_UNIT_WEEK,
562 * UDAT_REL_UNIT_FRIDAY.
563 * @param appendTo The string to which the formatted result will be
565 * @param status ICU error code returned here.
569 UnicodeString
& formatNumeric(
571 URelativeDateTimeUnit unit
,
572 UnicodeString
& appendTo
,
573 UErrorCode
& status
) const;
575 #ifndef U_HIDE_DRAFT_API
577 * Format a combination of URelativeDateTimeUnit and numeric offset
578 * using a numeric style, e.g. "1 week ago", "in 1 week",
579 * "5 weeks ago", "in 5 weeks".
581 * This method returns a FormattedRelativeDateTime, which exposes more
582 * information than the String returned by formatNumeric().
584 * @param offset The signed offset for the specified unit. This
585 * will be formatted according to this object's
586 * NumberFormat object.
587 * @param unit The unit to use when formatting the relative
588 * date, e.g. UDAT_REL_UNIT_WEEK,
589 * UDAT_REL_UNIT_FRIDAY.
590 * @param status ICU error code returned here.
591 * @return The formatted relative datetime
594 FormattedRelativeDateTime
formatNumericToValue(
596 URelativeDateTimeUnit unit
,
597 UErrorCode
& status
) const;
598 #endif /* U_HIDE_DRAFT_API */
601 * Format a combination of URelativeDateTimeUnit and numeric offset
602 * using a text style if possible, e.g. "last week", "this week",
603 * "next week", "yesterday", "tomorrow". Falls back to numeric
604 * style if no appropriate text term is available for the specified
605 * offset in the object's locale.
607 * This method returns a String. To get more information about the
608 * formatting result, use formatToValue().
610 * @param offset The signed offset for the specified unit.
611 * @param unit The unit to use when formatting the relative
612 * date, e.g. UDAT_REL_UNIT_WEEK,
613 * UDAT_REL_UNIT_FRIDAY.
614 * @param appendTo The string to which the formatted result will be
616 * @param status ICU error code returned here.
620 UnicodeString
& format(
622 URelativeDateTimeUnit unit
,
623 UnicodeString
& appendTo
,
624 UErrorCode
& status
) const;
626 #ifndef U_HIDE_DRAFT_API
628 * Format a combination of URelativeDateTimeUnit and numeric offset
629 * using a text style if possible, e.g. "last week", "this week",
630 * "next week", "yesterday", "tomorrow". Falls back to numeric
631 * style if no appropriate text term is available for the specified
632 * offset in the object's locale.
634 * This method returns a FormattedRelativeDateTime, which exposes more
635 * information than the String returned by format().
637 * @param offset The signed offset for the specified unit.
638 * @param unit The unit to use when formatting the relative
639 * date, e.g. UDAT_REL_UNIT_WEEK,
640 * UDAT_REL_UNIT_FRIDAY.
641 * @param status ICU error code returned here.
642 * @return The formatted relative datetime
645 FormattedRelativeDateTime
formatToValue(
647 URelativeDateTimeUnit unit
,
648 UErrorCode
& status
) const;
649 #endif /* U_HIDE_DRAFT_API */
652 * Combines a relative date string and a time string in this object's
653 * locale. This is done with the same date-time separator used for the
654 * default calendar in this locale.
656 * @param relativeDateString the relative date, e.g 'yesterday'
657 * @param timeString the time e.g '3:45'
658 * @param appendTo concatenated date and time appended here
659 * @param status ICU error code returned here.
663 UnicodeString
& combineDateAndTime(
664 const UnicodeString
& relativeDateString
,
665 const UnicodeString
& timeString
,
666 UnicodeString
& appendTo
,
667 UErrorCode
& status
) const;
670 * Returns the NumberFormat this object is using.
674 const NumberFormat
& getNumberFormat() const;
677 * Returns the capitalization context.
681 UDisplayContext
getCapitalizationContext() const;
684 * Returns the format style.
688 UDateRelativeDateTimeFormatterStyle
getFormatStyle() const;
691 const RelativeDateTimeCacheData
* fCache
;
692 const SharedNumberFormat
*fNumberFormat
;
693 const SharedPluralRules
*fPluralRules
;
694 UDateRelativeDateTimeFormatterStyle fStyle
;
695 UDisplayContext fContext
;
696 const SharedBreakIterator
*fOptBreakIterator
;
699 NumberFormat
*nfToAdopt
,
700 BreakIterator
*brkIter
,
702 UnicodeString
& adjustForContext(UnicodeString
&) const;
703 UBool
checkNoAdjustForContext(UErrorCode
& status
) const;
705 template<typename F
, typename
... Args
>
706 UnicodeString
& doFormat(
708 UnicodeString
& appendTo
,
712 #ifndef U_HIDE_DRAFT_API // for FormattedRelativeDateTime
713 template<typename F
, typename
... Args
>
714 FormattedRelativeDateTime
doFormatToValue(
718 #endif // U_HIDE_DRAFT_API
722 UDateDirection direction
,
723 UDateRelativeUnit unit
,
724 FormattedRelativeDateTimeData
& output
,
725 UErrorCode
& status
) const;
726 void formatAbsoluteImpl(
727 UDateDirection direction
,
728 UDateAbsoluteUnit unit
,
729 FormattedRelativeDateTimeData
& output
,
730 UErrorCode
& status
) const;
731 void formatNumericImpl(
733 URelativeDateTimeUnit unit
,
734 FormattedRelativeDateTimeData
& output
,
735 UErrorCode
& status
) const;
736 void formatRelativeImpl(
738 URelativeDateTimeUnit unit
,
739 FormattedRelativeDateTimeData
& output
,
740 UErrorCode
& status
) const;
744 #endif // U_SHOW_CPLUSPLUS_API
746 #endif /* !UCONFIG_NO_BREAK_ITERATION */
747 #endif /* !UCONFIG_NO_FORMATTING */
748 #endif /* __RELDATEFMT_H */