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