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"
19 #if U_SHOW_CPLUSPLUS_API
21 #include "unicode/uobject.h"
22 #include "unicode/udisplaycontext.h"
23 #include "unicode/ureldatefmt.h"
24 #include "unicode/locid.h"
25 #include "unicode/formattedvalue.h"
29 * \brief C++ API: Formats relative dates such as "1 day ago" or "tomorrow"
32 #if !UCONFIG_NO_FORMATTING
35 * Represents the unit for formatting a relative date. e.g "in 5 days"
39 typedef enum UDateRelativeUnit
{
45 UDAT_RELATIVE_SECONDS
,
51 UDAT_RELATIVE_MINUTES
,
83 #ifndef U_HIDE_DEPRECATED_API
85 * One more than the highest normal UDateRelativeUnit value.
86 * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
88 UDAT_RELATIVE_UNIT_COUNT
89 #endif // U_HIDE_DEPRECATED_API
93 * Represents an absolute unit.
96 typedef enum UDateAbsoluteUnit
{
98 // Days of week have to remain together and in order from Sunday to
104 UDAT_ABSOLUTE_SUNDAY
,
110 UDAT_ABSOLUTE_MONDAY
,
116 UDAT_ABSOLUTE_TUESDAY
,
122 UDAT_ABSOLUTE_WEDNESDAY
,
128 UDAT_ABSOLUTE_THURSDAY
,
134 UDAT_ABSOLUTE_FRIDAY
,
140 UDAT_ABSOLUTE_SATURDAY
,
176 UDAT_ABSOLUTE_QUARTER
,
178 #ifndef U_HIDE_DRAFT_API
189 UDAT_ABSOLUTE_MINUTE
,
190 #endif // U_HIDE_DRAFT_API
192 #ifndef U_HIDE_DEPRECATED_API
194 * One more than the highest normal UDateAbsoluteUnit value.
195 * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
197 UDAT_ABSOLUTE_UNIT_COUNT
= UDAT_ABSOLUTE_NOW
+ 4
198 #endif // U_HIDE_DEPRECATED_API
202 * Represents a direction for an absolute unit e.g "Next Tuesday"
206 typedef enum UDateDirection
{
209 * Two before. Not fully supported in every locale.
212 UDAT_DIRECTION_LAST_2
,
233 * Two after. Not fully supported in every locale.
236 UDAT_DIRECTION_NEXT_2
,
239 * Plain, which means the absence of a qualifier.
242 UDAT_DIRECTION_PLAIN
,
244 #ifndef U_HIDE_DEPRECATED_API
246 * One more than the highest normal UDateDirection value.
247 * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
250 #endif // U_HIDE_DEPRECATED_API
253 #if !UCONFIG_NO_BREAK_ITERATION
258 class RelativeDateTimeCacheData
;
259 class SharedNumberFormat
;
260 class SharedPluralRules
;
261 class SharedBreakIterator
;
264 class FormattedRelativeDateTime
;
265 class FormattedRelativeDateTimeData
;
267 #ifndef U_HIDE_DRAFT_API
269 * An immutable class containing the result of a relative datetime formatting operation.
271 * Instances of this class are immutable and thread-safe.
273 * Not intended for public subclassing.
277 class U_I18N_API FormattedRelativeDateTime
: public UMemory
, public FormattedValue
{
280 * Default constructor; makes an empty FormattedRelativeDateTime.
283 FormattedRelativeDateTime() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR
) {}
286 * Move constructor: Leaves the source FormattedRelativeDateTime in an undefined state.
289 FormattedRelativeDateTime(FormattedRelativeDateTime
&& src
) U_NOEXCEPT
;
292 * Destruct an instance of FormattedRelativeDateTime.
295 virtual ~FormattedRelativeDateTime() U_OVERRIDE
;
297 /** Copying not supported; use move constructor instead. */
298 FormattedRelativeDateTime(const FormattedRelativeDateTime
&) = delete;
300 /** Copying not supported; use move assignment instead. */
301 FormattedRelativeDateTime
& operator=(const FormattedRelativeDateTime
&) = delete;
304 * Move assignment: Leaves the source FormattedRelativeDateTime in an undefined state.
307 FormattedRelativeDateTime
& operator=(FormattedRelativeDateTime
&& src
) U_NOEXCEPT
;
309 /** @copydoc FormattedValue::toString() */
310 UnicodeString
toString(UErrorCode
& status
) const U_OVERRIDE
;
312 /** @copydoc FormattedValue::toTempString() */
313 UnicodeString
toTempString(UErrorCode
& status
) const U_OVERRIDE
;
315 /** @copydoc FormattedValue::appendTo() */
316 Appendable
&appendTo(Appendable
& appendable
, UErrorCode
& status
) const U_OVERRIDE
;
318 /** @copydoc FormattedValue::nextPosition() */
319 UBool
nextPosition(ConstrainedFieldPosition
& cfpos
, UErrorCode
& status
) const U_OVERRIDE
;
322 FormattedRelativeDateTimeData
*fData
;
323 UErrorCode fErrorCode
;
324 explicit FormattedRelativeDateTime(FormattedRelativeDateTimeData
*results
)
325 : fData(results
), fErrorCode(U_ZERO_ERROR
) {}
326 explicit FormattedRelativeDateTime(UErrorCode errorCode
)
327 : fData(nullptr), fErrorCode(errorCode
) {}
328 friend class RelativeDateTimeFormatter
;
330 #endif /* U_HIDE_DRAFT_API */
333 * Formats simple relative dates. There are two types of relative dates that
336 * <li>relative dates with a quantity e.g "in 5 days"</li>
337 * <li>relative dates without a quantity e.g "next Tuesday"</li>
340 * This API is very basic and is intended to be a building block for more
341 * fancy APIs. The caller tells it exactly what to display in a locale
342 * independent way. While this class automatically provides the correct plural
343 * forms, the grammatical form is otherwise as neutral as possible. It is the
344 * caller's responsibility to handle cut-off logic such as deciding between
345 * displaying "in 7 days" or "in 1 week." This API supports relative dates
346 * involving one single unit. This API does not support relative dates
347 * involving compound units,
348 * e.g "in 5 days and 4 hours" nor does it support parsing.
350 * This class is mostly thread safe and immutable with the following caveats:
351 * 1. The assignment operator violates Immutability. It must not be used
352 * concurrently with other operations.
353 * 2. Caller must not hold onto adopted pointers.
355 * This class is not intended for public subclassing.
357 * Here are some examples of use:
360 * UErrorCode status = U_ZERO_ERROR;
361 * UnicodeString appendTo;
362 * RelativeDateTimeFormatter fmt(status);
363 * // Appends "in 1 day"
365 * 1, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status);
366 * // Appends "in 3 days"
368 * 3, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status);
369 * // Appends "3.2 years ago"
371 * 3.2, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, appendTo, status);
372 * // Appends "last Sunday"
373 * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
374 * // Appends "this Sunday"
375 * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
376 * // Appends "next Sunday"
377 * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
378 * // Appends "Sunday"
379 * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
381 * // Appends "yesterday"
382 * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_DAY, appendTo, status);
384 * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_DAY, appendTo, status);
385 * // Appends "tomorrow"
386 * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_DAY, appendTo, status);
388 * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, appendTo, status);
393 * In the future, we may add more forms, such as abbreviated/short forms
394 * (3 secs ago), and relative day periods ("yesterday afternoon"), etc.
396 * The RelativeDateTimeFormatter class is not intended for public subclassing.
400 class U_I18N_API RelativeDateTimeFormatter
: public UObject
{
404 * Create RelativeDateTimeFormatter with default locale.
407 RelativeDateTimeFormatter(UErrorCode
& status
);
410 * Create RelativeDateTimeFormatter with given locale.
413 RelativeDateTimeFormatter(const Locale
& locale
, UErrorCode
& status
);
416 * Create RelativeDateTimeFormatter with given locale and NumberFormat.
418 * @param locale the locale
419 * @param nfToAdopt Constructed object takes ownership of this pointer.
420 * It is an error for caller to delete this pointer or change its
421 * contents after calling this constructor.
422 * @param status Any error is returned here.
425 RelativeDateTimeFormatter(
426 const Locale
& locale
, NumberFormat
*nfToAdopt
, UErrorCode
& status
);
429 * Create RelativeDateTimeFormatter with given locale, NumberFormat,
430 * and capitalization context.
432 * @param locale the locale
433 * @param nfToAdopt Constructed object takes ownership of this pointer.
434 * It is an error for caller to delete this pointer or change its
435 * contents after calling this constructor. Caller may pass NULL for
436 * this argument if they want default number format behavior.
437 * @param style the format style. The UDAT_RELATIVE bit field has no effect.
438 * @param capitalizationContext A value from UDisplayContext that pertains to
440 * @param status Any error is returned here.
443 RelativeDateTimeFormatter(
444 const Locale
& locale
,
445 NumberFormat
*nfToAdopt
,
446 UDateRelativeDateTimeFormatterStyle style
,
447 UDisplayContext capitalizationContext
,
454 RelativeDateTimeFormatter(const RelativeDateTimeFormatter
& other
);
457 * Assignment operator.
460 RelativeDateTimeFormatter
& operator=(
461 const RelativeDateTimeFormatter
& other
);
467 virtual ~RelativeDateTimeFormatter();
470 * Formats a relative date with a quantity such as "in 5 days" or
473 * This method returns a String. To get more information about the
474 * formatting result, use formatToValue().
476 * @param quantity The numerical amount e.g 5. This value is formatted
477 * according to this object's NumberFormat object.
478 * @param direction NEXT means a future relative date; LAST means a past
479 * relative date. If direction is anything else, this method sets
480 * status to U_ILLEGAL_ARGUMENT_ERROR.
481 * @param unit the unit e.g day? month? year?
482 * @param appendTo The string to which the formatted result will be
484 * @param status ICU error code returned here.
488 UnicodeString
& format(
490 UDateDirection direction
,
491 UDateRelativeUnit unit
,
492 UnicodeString
& appendTo
,
493 UErrorCode
& status
) const;
495 #ifndef U_HIDE_DRAFT_API
497 * Formats a relative date with a quantity such as "in 5 days" or
500 * This method returns a FormattedRelativeDateTime, which exposes more
501 * information than the String returned by format().
503 * @param quantity The numerical amount e.g 5. This value is formatted
504 * according to this object's NumberFormat object.
505 * @param direction NEXT means a future relative date; LAST means a past
506 * relative date. If direction is anything else, this method sets
507 * status to U_ILLEGAL_ARGUMENT_ERROR.
508 * @param unit the unit e.g day? month? year?
509 * @param status ICU error code returned here.
510 * @return The formatted relative datetime
513 FormattedRelativeDateTime
formatToValue(
515 UDateDirection direction
,
516 UDateRelativeUnit unit
,
517 UErrorCode
& status
) const;
518 #endif /* U_HIDE_DRAFT_API */
521 * Formats a relative date without a quantity.
523 * This method returns a String. To get more information about the
524 * formatting result, use formatToValue().
526 * @param direction NEXT, LAST, THIS, etc.
527 * @param unit e.g SATURDAY, DAY, MONTH
528 * @param appendTo The string to which the formatted result will be
529 * appended. If the value of direction is documented as not being fully
530 * supported in all locales then this method leaves appendTo unchanged if
531 * no format string is available.
532 * @param status ICU error code returned here.
536 UnicodeString
& format(
537 UDateDirection direction
,
538 UDateAbsoluteUnit unit
,
539 UnicodeString
& appendTo
,
540 UErrorCode
& status
) const;
542 #ifndef U_HIDE_DRAFT_API
544 * Formats a relative date without a quantity.
546 * This method returns a FormattedRelativeDateTime, which exposes more
547 * information than the String returned by format().
549 * If the string is not available in the requested locale, the return
550 * value will be empty (calling toString will give an empty string).
552 * @param direction NEXT, LAST, THIS, etc.
553 * @param unit e.g SATURDAY, DAY, MONTH
554 * @param status ICU error code returned here.
555 * @return The formatted relative datetime
558 FormattedRelativeDateTime
formatToValue(
559 UDateDirection direction
,
560 UDateAbsoluteUnit unit
,
561 UErrorCode
& status
) const;
562 #endif /* U_HIDE_DRAFT_API */
565 * Format a combination of URelativeDateTimeUnit and numeric offset
566 * using a numeric style, e.g. "1 week ago", "in 1 week",
567 * "5 weeks ago", "in 5 weeks".
569 * This method returns a String. To get more information about the
570 * formatting result, use formatNumericToValue().
572 * @param offset The signed offset for the specified unit. This
573 * will be formatted according to this object's
574 * NumberFormat object.
575 * @param unit The unit to use when formatting the relative
576 * date, e.g. UDAT_REL_UNIT_WEEK,
577 * UDAT_REL_UNIT_FRIDAY.
578 * @param appendTo The string to which the formatted result will be
580 * @param status ICU error code returned here.
584 UnicodeString
& formatNumeric(
586 URelativeDateTimeUnit unit
,
587 UnicodeString
& appendTo
,
588 UErrorCode
& status
) const;
590 #ifndef U_HIDE_DRAFT_API
592 * Format a combination of URelativeDateTimeUnit and numeric offset
593 * using a numeric style, e.g. "1 week ago", "in 1 week",
594 * "5 weeks ago", "in 5 weeks".
596 * This method returns a FormattedRelativeDateTime, which exposes more
597 * information than the String returned by formatNumeric().
599 * @param offset The signed offset for the specified unit. This
600 * will be formatted according to this object's
601 * NumberFormat object.
602 * @param unit The unit to use when formatting the relative
603 * date, e.g. UDAT_REL_UNIT_WEEK,
604 * UDAT_REL_UNIT_FRIDAY.
605 * @param status ICU error code returned here.
606 * @return The formatted relative datetime
609 FormattedRelativeDateTime
formatNumericToValue(
611 URelativeDateTimeUnit unit
,
612 UErrorCode
& status
) const;
613 #endif /* U_HIDE_DRAFT_API */
616 * Format a combination of URelativeDateTimeUnit and numeric offset
617 * using a text style if possible, e.g. "last week", "this week",
618 * "next week", "yesterday", "tomorrow". Falls back to numeric
619 * style if no appropriate text term is available for the specified
620 * offset in the object's locale.
622 * This method returns a String. To get more information about the
623 * formatting result, use formatToValue().
625 * @param offset The signed offset for the specified unit.
626 * @param unit The unit to use when formatting the relative
627 * date, e.g. UDAT_REL_UNIT_WEEK,
628 * UDAT_REL_UNIT_FRIDAY.
629 * @param appendTo The string to which the formatted result will be
631 * @param status ICU error code returned here.
635 UnicodeString
& format(
637 URelativeDateTimeUnit unit
,
638 UnicodeString
& appendTo
,
639 UErrorCode
& status
) const;
641 #ifndef U_HIDE_DRAFT_API
643 * Format a combination of URelativeDateTimeUnit and numeric offset
644 * using a text style if possible, e.g. "last week", "this week",
645 * "next week", "yesterday", "tomorrow". Falls back to numeric
646 * style if no appropriate text term is available for the specified
647 * offset in the object's locale.
649 * This method returns a FormattedRelativeDateTime, which exposes more
650 * information than the String returned by format().
652 * @param offset The signed offset for the specified unit.
653 * @param unit The unit to use when formatting the relative
654 * date, e.g. UDAT_REL_UNIT_WEEK,
655 * UDAT_REL_UNIT_FRIDAY.
656 * @param status ICU error code returned here.
657 * @return The formatted relative datetime
660 FormattedRelativeDateTime
formatToValue(
662 URelativeDateTimeUnit unit
,
663 UErrorCode
& status
) const;
664 #endif /* U_HIDE_DRAFT_API */
667 * Combines a relative date string and a time string in this object's
668 * locale. This is done with the same date-time separator used for the
669 * default calendar in this locale.
671 * @param relativeDateString the relative date, e.g 'yesterday'
672 * @param timeString the time e.g '3:45'
673 * @param appendTo concatenated date and time appended here
674 * @param status ICU error code returned here.
678 UnicodeString
& combineDateAndTime(
679 const UnicodeString
& relativeDateString
,
680 const UnicodeString
& timeString
,
681 UnicodeString
& appendTo
,
682 UErrorCode
& status
) const;
685 * Returns the NumberFormat this object is using.
689 const NumberFormat
& getNumberFormat() const;
692 * Returns the capitalization context.
696 UDisplayContext
getCapitalizationContext() const;
699 * Returns the format style.
703 UDateRelativeDateTimeFormatterStyle
getFormatStyle() const;
706 const RelativeDateTimeCacheData
* fCache
;
707 const SharedNumberFormat
*fNumberFormat
;
708 const SharedPluralRules
*fPluralRules
;
709 UDateRelativeDateTimeFormatterStyle fStyle
;
710 UDisplayContext fContext
;
711 const SharedBreakIterator
*fOptBreakIterator
;
714 NumberFormat
*nfToAdopt
,
715 BreakIterator
*brkIter
,
717 UnicodeString
& adjustForContext(UnicodeString
&) const;
718 UBool
checkNoAdjustForContext(UErrorCode
& status
) const;
720 template<typename F
, typename
... Args
>
721 UnicodeString
& doFormat(
723 UnicodeString
& appendTo
,
727 #ifndef U_HIDE_DRAFT_API // for FormattedRelativeDateTime
728 template<typename F
, typename
... Args
>
729 FormattedRelativeDateTime
doFormatToValue(
733 #endif // U_HIDE_DRAFT_API
737 UDateDirection direction
,
738 UDateRelativeUnit unit
,
739 FormattedRelativeDateTimeData
& output
,
740 UErrorCode
& status
) const;
741 void formatAbsoluteImpl(
742 UDateDirection direction
,
743 UDateAbsoluteUnit unit
,
744 FormattedRelativeDateTimeData
& output
,
745 UErrorCode
& status
) const;
746 void formatNumericImpl(
748 URelativeDateTimeUnit unit
,
749 FormattedRelativeDateTimeData
& output
,
750 UErrorCode
& status
) const;
751 void formatRelativeImpl(
753 URelativeDateTimeUnit unit
,
754 FormattedRelativeDateTimeData
& output
,
755 UErrorCode
& status
) const;
760 #endif /* !UCONFIG_NO_BREAK_ITERATION */
761 #endif /* !UCONFIG_NO_FORMATTING */
763 #endif /* U_SHOW_CPLUSPLUS_API */
765 #endif /* __RELDATEFMT_H */