1 /*
2 *****************************************************************************
3 * Copyright (C) 2014-2015, International Business Machines Corporation and
4 * others.
5 * All Rights Reserved.
6 *****************************************************************************
7 *
8 * File RELDATEFMT.H
9 *****************************************************************************
10 */
11 
12 #ifndef __RELDATEFMT_H
13 #define __RELDATEFMT_H
14 
15 #include "unicode/utypes.h"
16 #include "unicode/uobject.h"
17 #include "unicode/udisplaycontext.h"
18 #include "unicode/locid.h"
19 
20 /**
21  * \file
22  * \brief C++ API: Formats relative dates such as "1 day ago" or "tomorrow"
23  */
24 
25 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION
26 
27 /**
28  * The formatting style
29  * @stable ICU 54
30  */
31 typedef enum UDateRelativeDateTimeFormatterStyle {
32   /**
33    * Everything spelled out.
34    * @stable ICU 54
35    */
36   UDAT_STYLE_LONG,
37 
38   /**
39    * Abbreviations used when possible.
40    * @stable ICU 54
41    */
42   UDAT_STYLE_SHORT,
43 
44   /**
45    * Use the shortest possible form.
46    * @stable ICU 54
47    */
48   UDAT_STYLE_NARROW,
49 
50   /**
51    * The number of styles.
52    * @stable ICU 54
53    */
54   UDAT_STYLE_COUNT
55 } UDateRelativeDateTimeFormatterStyle;
56 
57 /**
58  * Represents the unit for formatting a relative date. e.g "in 5 days"
59  * or "in 3 months"
60  * @stable ICU 53
61  */
62 typedef enum UDateRelativeUnit {
63 
64     /**
65      * Seconds
66      * @stable ICU 53
67      */
68     UDAT_RELATIVE_SECONDS,
69 
70     /**
71      * Minutes
72      * @stable ICU 53
73      */
74     UDAT_RELATIVE_MINUTES,
75 
76     /**
77      * Hours
78      * @stable ICU 53
79      */
80     UDAT_RELATIVE_HOURS,
81 
82     /**
83      * Days
84      * @stable ICU 53
85      */
86     UDAT_RELATIVE_DAYS,
87 
88     /**
89      * Weeks
90      * @stable ICU 53
91      */
92     UDAT_RELATIVE_WEEKS,
93 
94     /**
95      * Months
96      * @stable ICU 53
97      */
98     UDAT_RELATIVE_MONTHS,
99 
100     /**
101      * Years
102      * @stable ICU 53
103      */
104     UDAT_RELATIVE_YEARS,
105 
106     /**
107      * Count of items in this enum.
108      * @stable ICU 53
109      */
110     UDAT_RELATIVE_UNIT_COUNT
111 } UDateRelativeUnit;
112 
113 /**
114  * Represents an absolute unit.
115  * @stable ICU 53
116  */
117 typedef enum UDateAbsoluteUnit {
118 
119     // Days of week have to remain together and in order from Sunday to
120     // Saturday.
121     /**
122      * Sunday
123      * @stable ICU 53
124      */
125     UDAT_ABSOLUTE_SUNDAY,
126 
127     /**
128      * Monday
129      * @stable ICU 53
130      */
131     UDAT_ABSOLUTE_MONDAY,
132 
133     /**
134      * Tuesday
135      * @stable ICU 53
136      */
137     UDAT_ABSOLUTE_TUESDAY,
138 
139     /**
140      * Wednesday
141      * @stable ICU 53
142      */
143     UDAT_ABSOLUTE_WEDNESDAY,
144 
145     /**
146      * Thursday
147      * @stable ICU 53
148      */
149     UDAT_ABSOLUTE_THURSDAY,
150 
151     /**
152      * Friday
153      * @stable ICU 53
154      */
155     UDAT_ABSOLUTE_FRIDAY,
156 
157     /**
158      * Saturday
159      * @stable ICU 53
160      */
161     UDAT_ABSOLUTE_SATURDAY,
162 
163     /**
164      * Day
165      * @stable ICU 53
166      */
167     UDAT_ABSOLUTE_DAY,
168 
169     /**
170      * Week
171      * @stable ICU 53
172      */
173     UDAT_ABSOLUTE_WEEK,
174 
175     /**
176      * Month
177      * @stable ICU 53
178      */
179     UDAT_ABSOLUTE_MONTH,
180 
181     /**
182      * Year
183      * @stable ICU 53
184      */
185     UDAT_ABSOLUTE_YEAR,
186 
187     /**
188      * Now
189      * @stable ICU 53
190      */
191     UDAT_ABSOLUTE_NOW,
192 
193     /**
194      * Count of items in this enum.
195      * @stable ICU 53
196      */
197     UDAT_ABSOLUTE_UNIT_COUNT
198 } UDateAbsoluteUnit;
199 
200 /**
201  * Represents a direction for an absolute unit e.g "Next Tuesday"
202  * or "Last Tuesday"
203  * @stable ICU 53
204  */
205 typedef enum UDateDirection {
206 
207     /**
208      * Two before. Not fully supported in every locale.
209      * @stable ICU 53
210      */
211     UDAT_DIRECTION_LAST_2,
212 
213     /**
214      * Last
215      * @stable ICU 53
216      */
217     UDAT_DIRECTION_LAST,
218 
219     /**
220      * This
221      * @stable ICU 53
222      */
223     UDAT_DIRECTION_THIS,
224 
225     /**
226      * Next
227      * @stable ICU 53
228      */
229     UDAT_DIRECTION_NEXT,
230 
231     /**
232      * Two after. Not fully supported in every locale.
233      * @stable ICU 53
234      */
235     UDAT_DIRECTION_NEXT_2,
236 
237     /**
238      * Plain, which means the absence of a qualifier.
239      * @stable ICU 53
240      */
241     UDAT_DIRECTION_PLAIN,
242 
243     /**
244      * Count of items in this enum.
245      * @stable ICU 53
246      */
247     UDAT_DIRECTION_COUNT
248 } UDateDirection;
249 
250 
251 U_NAMESPACE_BEGIN
252 
253 class RelativeDateTimeCacheData;
254 class SharedNumberFormat;
255 class SharedPluralRules;
256 class SharedBreakIterator;
257 class NumberFormat;
258 class UnicodeString;
259 
260 /**
261  * Formats simple relative dates. There are two types of relative dates that
262  * it handles:
263  * <ul>
264  *   <li>relative dates with a quantity e.g "in 5 days"</li>
265  *   <li>relative dates without a quantity e.g "next Tuesday"</li>
266  * </ul>
267  * <p>
268  * This API is very basic and is intended to be a building block for more
269  * fancy APIs. The caller tells it exactly what to display in a locale
270  * independent way. While this class automatically provides the correct plural
271  * forms, the grammatical form is otherwise as neutral as possible. It is the
272  * caller's responsibility to handle cut-off logic such as deciding between
273  * displaying "in 7 days" or "in 1 week." This API supports relative dates
274  * involving one single unit. This API does not support relative dates
275  * involving compound units,
276  * e.g "in 5 days and 4 hours" nor does it support parsing.
277  * <p>
278  * This class is mostly thread safe and immutable with the following caveats:
279  * 1. The assignment operator violates Immutability. It must not be used
280  *    concurrently with other operations.
281  * 2. Caller must not hold onto adopted pointers.
282  * <p>
283  * This class is not intended for public subclassing.
284  * <p>
285  * Here are some examples of use:
286  * <blockquote>
287  * <pre>
288  * UErrorCode status = U_ZERO_ERROR;
289  * UnicodeString appendTo;
290  * RelativeDateTimeFormatter fmt(status);
291  * // Appends "in 1 day"
292  * fmt.format(
293  *     1, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status);
294  * // Appends "in 3 days"
295  * fmt.format(
296  *     3, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, appendTo, status);
297  * // Appends "3.2 years ago"
298  * fmt.format(
299  *     3.2, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, appendTo, status);
300  * // Appends "last Sunday"
301  * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
302  * // Appends "this Sunday"
303  * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
304  * // Appends "next Sunday"
305  * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
306  * // Appends "Sunday"
307  * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, appendTo, status);
308  *
309  * // Appends "yesterday"
310  * fmt.format(UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_DAY, appendTo, status);
311  * // Appends "today"
312  * fmt.format(UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_DAY, appendTo, status);
313  * // Appends "tomorrow"
314  * fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_DAY, appendTo, status);
315  * // Appends "now"
316  * fmt.format(UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, appendTo, status);
317  *
318  * </pre>
319  * </blockquote>
320  * <p>
321  * In the future, we may add more forms, such as abbreviated/short forms
322  * (3 secs ago), and relative day periods ("yesterday afternoon"), etc.
323  *
324  * The RelativeDateTimeFormatter class is not intended for public subclassing.
325  *
326  * @stable ICU 53
327  */
328 class U_I18N_API RelativeDateTimeFormatter : public UObject {
329 public:
330 
331     /**
332      * Create RelativeDateTimeFormatter with default locale.
333      * @stable ICU 53
334      */
335     RelativeDateTimeFormatter(UErrorCode& status);
336 
337     /**
338      * Create RelativeDateTimeFormatter with given locale.
339      * @stable ICU 53
340      */
341     RelativeDateTimeFormatter(const Locale& locale, UErrorCode& status);
342 
343     /**
344      * Create RelativeDateTimeFormatter with given locale and NumberFormat.
345      *
346      * @param locale the locale
347      * @param nfToAdopt Constructed object takes ownership of this pointer.
348      *   It is an error for caller to delete this pointer or change its
349      *   contents after calling this constructor.
350      * @status Any error is returned here.
351      * @stable ICU 53
352      */
353     RelativeDateTimeFormatter(
354         const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status);
355 
356     /**
357      * Create RelativeDateTimeFormatter with given locale, NumberFormat,
358      * and capitalization context.
359      *
360      * @param locale the locale
361      * @param nfToAdopt Constructed object takes ownership of this pointer.
362      *   It is an error for caller to delete this pointer or change its
363      *   contents after calling this constructor. Caller may pass NULL for
364      *   this argument if they want default number format behavior.
365      * @param style the format style. The UDAT_RELATIVE bit field has no effect.
366      * @param capitalizationContext A value from UDisplayContext that pertains to
367      * capitalization.
368      * @status Any error is returned here.
369      * @stable ICU 54
370      */
371     RelativeDateTimeFormatter(
372             const Locale& locale,
373             NumberFormat *nfToAdopt,
374             UDateRelativeDateTimeFormatterStyle style,
375             UDisplayContext capitalizationContext,
376             UErrorCode& status);
377 
378     /**
379      * Copy constructor.
380      * @stable ICU 53
381      */
382     RelativeDateTimeFormatter(const RelativeDateTimeFormatter& other);
383 
384     /**
385      * Assignment operator.
386      * @stable ICU 53
387      */
388     RelativeDateTimeFormatter& operator=(
389             const RelativeDateTimeFormatter& other);
390 
391     /**
392      * Destructor.
393      * @stable ICU 53
394      */
395     virtual ~RelativeDateTimeFormatter();
396 
397     /**
398      * Formats a relative date with a quantity such as "in 5 days" or
399      * "3 months ago"
400      * @param quantity The numerical amount e.g 5. This value is formatted
401      * according to this object's NumberFormat object.
402      * @param direction NEXT means a future relative date; LAST means a past
403      * relative date. If direction is anything else, this method sets
404      * status to U_ILLEGAL_ARGUMENT_ERROR.
405      * @param unit the unit e.g day? month? year?
406      * @param appendTo The string to which the formatted result will be
407      *  appended
408      * @param status ICU error code returned here.
409      * @return appendTo
410      * @stable ICU 53
411      */
412     UnicodeString& format(
413             double quantity,
414             UDateDirection direction,
415             UDateRelativeUnit unit,
416             UnicodeString& appendTo,
417             UErrorCode& status) const;
418 
419     /**
420      * Formats a relative date without a quantity.
421      * @param direction NEXT, LAST, THIS, etc.
422      * @param unit e.g SATURDAY, DAY, MONTH
423      * @param appendTo The string to which the formatted result will be
424      *  appended. If the value of direction is documented as not being fully
425      *  supported in all locales then this method leaves appendTo unchanged if
426      *  no format string is available.
427      * @param status ICU error code returned here.
428      * @return appendTo
429      * @stable ICU 53
430      */
431     UnicodeString& format(
432             UDateDirection direction,
433             UDateAbsoluteUnit unit,
434             UnicodeString& appendTo,
435             UErrorCode& status) const;
436 
437     /**
438      * Combines a relative date string and a time string in this object's
439      * locale. This is done with the same date-time separator used for the
440      * default calendar in this locale.
441      *
442      * @param relativeDateString the relative date, e.g 'yesterday'
443      * @param timeString the time e.g '3:45'
444      * @param appendTo concatenated date and time appended here
445      * @param status ICU error code returned here.
446      * @return appendTo
447      * @stable ICU 53
448      */
449     UnicodeString& combineDateAndTime(
450             const UnicodeString& relativeDateString,
451             const UnicodeString& timeString,
452             UnicodeString& appendTo,
453             UErrorCode& status) const;
454 
455     /**
456      * Returns the NumberFormat this object is using.
457      *
458      * @stable ICU 53
459      */
460     const NumberFormat& getNumberFormat() const;
461 
462     /**
463      * Returns the capitalization context.
464      *
465      * @stable ICU 54
466      */
467     UDisplayContext getCapitalizationContext() const;
468 
469     /**
470      * Returns the format style.
471      *
472      * @stable ICU 54
473      */
474     UDateRelativeDateTimeFormatterStyle getFormatStyle() const;
475 
476 private:
477     const RelativeDateTimeCacheData* fCache;
478     const SharedNumberFormat *fNumberFormat;
479     const SharedPluralRules *fPluralRules;
480     UDateRelativeDateTimeFormatterStyle fStyle;
481     UDisplayContext fContext;
482     const SharedBreakIterator *fOptBreakIterator;
483     Locale fLocale;
484     void init(
485             NumberFormat *nfToAdopt,
486             BreakIterator *brkIter,
487             UErrorCode &status);
488     void adjustForContext(UnicodeString &) const;
489 };
490 
491 U_NAMESPACE_END
492 
493 #endif /* !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION*/
494 #endif
495