1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *****************************************************************************************
5 * Copyright (C) 2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 *****************************************************************************************
8 */
9 
10 #ifndef URELDATEFMT_H
11 #define URELDATEFMT_H
12 
13 #include "unicode/utypes.h"
14 
15 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION
16 
17 #include "unicode/unum.h"
18 #include "unicode/udisplaycontext.h"
19 #include "unicode/uformattedvalue.h"
20 
21 #if U_SHOW_CPLUSPLUS_API
22 #include "unicode/localpointer.h"
23 #endif   // U_SHOW_CPLUSPLUS_API
24 
25 /**
26  * \file
27  * \brief C API: URelativeDateTimeFormatter, relative date formatting of unit + numeric offset.
28  *
29  * Provides simple formatting of relative dates, in two ways
30  * <ul>
31  *   <li>relative dates with a quantity e.g "in 5 days"</li>
32  *   <li>relative dates without a quantity e.g "next Tuesday"</li>
33  * </ul>
34  * <p>
35  * This does not provide compound formatting for multiple units,
36  * other than the ability to combine a time string with a relative date,
37  * as in "next Tuesday at 3:45 PM". It also does not provide support
38  * for determining which unit to use, such as deciding between "in 7 days"
39  * and "in 1 week".
40  *
41  * @stable ICU 57
42  */
43 
44 /**
45  * The formatting style
46  * @stable ICU 54
47  */
48 typedef enum UDateRelativeDateTimeFormatterStyle {
49   /**
50    * Everything spelled out.
51    * @stable ICU 54
52    */
53   UDAT_STYLE_LONG,
54 
55   /**
56    * Abbreviations used when possible.
57    * @stable ICU 54
58    */
59   UDAT_STYLE_SHORT,
60 
61   /**
62    * Use the shortest possible form.
63    * @stable ICU 54
64    */
65   UDAT_STYLE_NARROW,
66 
67 #ifndef U_HIDE_DEPRECATED_API
68     /**
69      * One more than the highest normal UDateRelativeDateTimeFormatterStyle value.
70      * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
71      */
72     UDAT_STYLE_COUNT
73 #endif  /* U_HIDE_DEPRECATED_API */
74 } UDateRelativeDateTimeFormatterStyle;
75 
76 /**
77  * Represents the unit for formatting a relative date. e.g "in 5 days"
78  * or "next year"
79  * @stable ICU 57
80  */
81 typedef enum URelativeDateTimeUnit {
82     /**
83      * Specifies that relative unit is year, e.g. "last year",
84      * "in 5 years".
85      * @stable ICU 57
86      */
87     UDAT_REL_UNIT_YEAR,
88     /**
89      * Specifies that relative unit is quarter, e.g. "last quarter",
90      * "in 5 quarters".
91      * @stable ICU 57
92      */
93     UDAT_REL_UNIT_QUARTER,
94     /**
95      * Specifies that relative unit is month, e.g. "last month",
96      * "in 5 months".
97      * @stable ICU 57
98      */
99     UDAT_REL_UNIT_MONTH,
100     /**
101      * Specifies that relative unit is week, e.g. "last week",
102      * "in 5 weeks".
103      * @stable ICU 57
104      */
105     UDAT_REL_UNIT_WEEK,
106     /**
107      * Specifies that relative unit is day, e.g. "yesterday",
108      * "in 5 days".
109      * @stable ICU 57
110      */
111     UDAT_REL_UNIT_DAY,
112     /**
113      * Specifies that relative unit is hour, e.g. "1 hour ago",
114      * "in 5 hours".
115      * @stable ICU 57
116      */
117     UDAT_REL_UNIT_HOUR,
118     /**
119      * Specifies that relative unit is minute, e.g. "1 minute ago",
120      * "in 5 minutes".
121      * @stable ICU 57
122      */
123     UDAT_REL_UNIT_MINUTE,
124     /**
125      * Specifies that relative unit is second, e.g. "1 second ago",
126      * "in 5 seconds".
127      * @stable ICU 57
128      */
129     UDAT_REL_UNIT_SECOND,
130     /**
131      * Specifies that relative unit is Sunday, e.g. "last Sunday",
132      * "this Sunday", "next Sunday", "in 5 Sundays".
133      * @stable ICU 57
134      */
135     UDAT_REL_UNIT_SUNDAY,
136     /**
137      * Specifies that relative unit is Monday, e.g. "last Monday",
138      * "this Monday", "next Monday", "in 5 Mondays".
139      * @stable ICU 57
140      */
141     UDAT_REL_UNIT_MONDAY,
142     /**
143      * Specifies that relative unit is Tuesday, e.g. "last Tuesday",
144      * "this Tuesday", "next Tuesday", "in 5 Tuesdays".
145      * @stable ICU 57
146      */
147     UDAT_REL_UNIT_TUESDAY,
148     /**
149      * Specifies that relative unit is Wednesday, e.g. "last Wednesday",
150      * "this Wednesday", "next Wednesday", "in 5 Wednesdays".
151      * @stable ICU 57
152      */
153     UDAT_REL_UNIT_WEDNESDAY,
154     /**
155      * Specifies that relative unit is Thursday, e.g. "last Thursday",
156      * "this Thursday", "next Thursday", "in 5 Thursdays".
157      * @stable ICU 57
158      */
159     UDAT_REL_UNIT_THURSDAY,
160     /**
161      * Specifies that relative unit is Friday, e.g. "last Friday",
162      * "this Friday", "next Friday", "in 5 Fridays".
163      * @stable ICU 57
164      */
165     UDAT_REL_UNIT_FRIDAY,
166     /**
167      * Specifies that relative unit is Saturday, e.g. "last Saturday",
168      * "this Saturday", "next Saturday", "in 5 Saturdays".
169      * @stable ICU 57
170      */
171     UDAT_REL_UNIT_SATURDAY,
172 #ifndef U_HIDE_DEPRECATED_API
173     /**
174      * One more than the highest normal URelativeDateTimeUnit value.
175      * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
176      */
177     UDAT_REL_UNIT_COUNT
178 #endif  /* U_HIDE_DEPRECATED_API */
179 } URelativeDateTimeUnit;
180 
181 /**
182  * FieldPosition and UFieldPosition selectors for format fields
183  * defined by RelativeDateTimeFormatter.
184  * @stable ICU 64
185  */
186 typedef enum URelativeDateTimeFormatterField {
187     /**
188      * Represents a literal text string, like "tomorrow" or "days ago".
189      * @stable ICU 64
190      */
191     UDAT_REL_LITERAL_FIELD,
192     /**
193      * Represents a number quantity, like "3" in "3 days ago".
194      * @stable ICU 64
195      */
196     UDAT_REL_NUMERIC_FIELD,
197 } URelativeDateTimeFormatterField;
198 
199 
200 /**
201  * Opaque URelativeDateTimeFormatter object for use in C programs.
202  * @stable ICU 57
203  */
204 struct URelativeDateTimeFormatter;
205 typedef struct URelativeDateTimeFormatter URelativeDateTimeFormatter;  /**< C typedef for struct URelativeDateTimeFormatter. @stable ICU 57 */
206 
207 
208 /**
209  * Open a new URelativeDateTimeFormatter object for a given locale using the
210  * specified width and capitalizationContext, along with a number formatter
211  * (if desired) to override the default formatter that would be used for
212  * display of numeric field offsets. The default formatter typically rounds
213  * toward 0 and has a minimum of 0 fraction digits and a maximum of 3
214  * fraction digits (i.e. it will show as many decimal places as necessary
215  * up to 3, without showing trailing 0s).
216  *
217  * @param locale
218  *          The locale
219  * @param nfToAdopt
220  *          A number formatter to set for this URelativeDateTimeFormatter
221  *          object (instead of the default decimal formatter). Ownership of
222  *          this UNumberFormat object will pass to the URelativeDateTimeFormatter
223  *          object (the URelativeDateTimeFormatter adopts the UNumberFormat),
224  *          which becomes responsible for closing it. If the caller wishes to
225  *          retain ownership of the UNumberFormat object, the caller must clone
226  *          it (with unum_clone) and pass the clone to ureldatefmt_open. May be
227  *          NULL to use the default decimal formatter.
228  * @param width
229  *          The width - wide, short, narrow, etc.
230  * @param capitalizationContext
231  *          A value from UDisplayContext that pertains to capitalization, e.g.
232  *          UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE.
233  * @param status
234  *          A pointer to a UErrorCode to receive any errors.
235  * @return
236  *          A pointer to a URelativeDateTimeFormatter object for the specified locale,
237  *          or NULL if an error occurred.
238  * @stable ICU 57
239  */
240 U_CAPI URelativeDateTimeFormatter* U_EXPORT2
241 ureldatefmt_open( const char*          locale,
242                   UNumberFormat*       nfToAdopt,
243                   UDateRelativeDateTimeFormatterStyle width,
244                   UDisplayContext      capitalizationContext,
245                   UErrorCode*          status );
246 
247 /**
248  * Close a URelativeDateTimeFormatter object. Once closed it may no longer be used.
249  * @param reldatefmt
250  *            The URelativeDateTimeFormatter object to close.
251  * @stable ICU 57
252  */
253 U_CAPI void U_EXPORT2
254 ureldatefmt_close(URelativeDateTimeFormatter *reldatefmt);
255 
256 struct UFormattedRelativeDateTime;
257 /**
258  * Opaque struct to contain the results of a URelativeDateTimeFormatter operation.
259  * @stable ICU 64
260  */
261 typedef struct UFormattedRelativeDateTime UFormattedRelativeDateTime;
262 
263 /**
264  * Creates an object to hold the result of a URelativeDateTimeFormatter
265  * operation. The object can be used repeatedly; it is cleared whenever
266  * passed to a format function.
267  *
268  * @param ec Set if an error occurs.
269  * @return A pointer needing ownership.
270  * @stable ICU 64
271  */
272 U_CAPI UFormattedRelativeDateTime* U_EXPORT2
273 ureldatefmt_openResult(UErrorCode* ec);
274 
275 /**
276  * Returns a representation of a UFormattedRelativeDateTime as a UFormattedValue,
277  * which can be subsequently passed to any API requiring that type.
278  *
279  * The returned object is owned by the UFormattedRelativeDateTime and is valid
280  * only as long as the UFormattedRelativeDateTime is present and unchanged in memory.
281  *
282  * You can think of this method as a cast between types.
283  *
284  * @param ufrdt The object containing the formatted string.
285  * @param ec Set if an error occurs.
286  * @return A UFormattedValue owned by the input object.
287  * @stable ICU 64
288  */
289 U_CAPI const UFormattedValue* U_EXPORT2
290 ureldatefmt_resultAsValue(const UFormattedRelativeDateTime* ufrdt, UErrorCode* ec);
291 
292 /**
293  * Releases the UFormattedRelativeDateTime created by ureldatefmt_openResult.
294  *
295  * @param ufrdt The object to release.
296  * @stable ICU 64
297  */
298 U_CAPI void U_EXPORT2
299 ureldatefmt_closeResult(UFormattedRelativeDateTime* ufrdt);
300 
301 
302 #if U_SHOW_CPLUSPLUS_API
303 
304 U_NAMESPACE_BEGIN
305 
306 /**
307  * \class LocalURelativeDateTimeFormatterPointer
308  * "Smart pointer" class, closes a URelativeDateTimeFormatter via ureldatefmt_close().
309  * For most methods see the LocalPointerBase base class.
310  *
311  * @see LocalPointerBase
312  * @see LocalPointer
313  * @stable ICU 57
314  */
315 U_DEFINE_LOCAL_OPEN_POINTER(LocalURelativeDateTimeFormatterPointer, URelativeDateTimeFormatter, ureldatefmt_close);
316 
317 /**
318  * \class LocalUFormattedRelativeDateTimePointer
319  * "Smart pointer" class, closes a UFormattedRelativeDateTime via ureldatefmt_closeResult().
320  * For most methods see the LocalPointerBase base class.
321  *
322  * @see LocalPointerBase
323  * @see LocalPointer
324  * @stable ICU 64
325  */
326 U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedRelativeDateTimePointer, UFormattedRelativeDateTime, ureldatefmt_closeResult);
327 
328 U_NAMESPACE_END
329 
330 #endif
331 
332 /**
333  * Format a combination of URelativeDateTimeUnit and numeric
334  * offset using a numeric style, e.g. "1 week ago", "in 1 week",
335  * "5 weeks ago", "in 5 weeks".
336  *
337  * @param reldatefmt
338  *          The URelativeDateTimeFormatter object specifying the
339  *          format conventions.
340  * @param offset
341  *          The signed offset for the specified unit. This will
342  *          be formatted according to this object's UNumberFormat
343  *          object.
344  * @param unit
345  *          The unit to use when formatting the relative
346  *          date, e.g. UDAT_REL_UNIT_WEEK, UDAT_REL_UNIT_FRIDAY.
347  * @param result
348  *          A pointer to a buffer to receive the formatted result.
349  * @param resultCapacity
350  *          The maximum size of result.
351  * @param status
352  *          A pointer to a UErrorCode to receive any errors. In
353  *          case of error status, the contents of result are
354  *          undefined.
355  * @return
356  *          The length of the formatted result; may be greater
357  *          than resultCapacity, in which case an error is returned.
358  * @stable ICU 57
359  */
360 U_CAPI int32_t U_EXPORT2
361 ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt,
362                     double                offset,
363                     URelativeDateTimeUnit unit,
364                     UChar*                result,
365                     int32_t               resultCapacity,
366                     UErrorCode*           status);
367 
368 /**
369  * Format a combination of URelativeDateTimeUnit and numeric
370  * offset using a numeric style, e.g. "1 week ago", "in 1 week",
371  * "5 weeks ago", "in 5 weeks".
372  *
373  * @param reldatefmt
374  *          The URelativeDateTimeFormatter object specifying the
375  *          format conventions.
376  * @param offset
377  *          The signed offset for the specified unit. This will
378  *          be formatted according to this object's UNumberFormat
379  *          object.
380  * @param unit
381  *          The unit to use when formatting the relative
382  *          date, e.g. UDAT_REL_UNIT_WEEK, UDAT_REL_UNIT_FRIDAY.
383  * @param result
384  *          A pointer to a UFormattedRelativeDateTime to populate.
385  * @param status
386  *          A pointer to a UErrorCode to receive any errors. In
387  *          case of error status, the contents of result are
388  *          undefined.
389  * @stable ICU 64
390  */
391 U_CAPI void U_EXPORT2
392 ureldatefmt_formatNumericToResult(
393     const URelativeDateTimeFormatter* reldatefmt,
394     double                            offset,
395     URelativeDateTimeUnit             unit,
396     UFormattedRelativeDateTime*       result,
397     UErrorCode*                       status);
398 
399 /**
400  * Format a combination of URelativeDateTimeUnit and numeric offset
401  * using a text style if possible, e.g. "last week", "this week",
402  * "next week", "yesterday", "tomorrow". Falls back to numeric
403  * style if no appropriate text term is available for the specified
404  * offset in the object's locale.
405  *
406  * @param reldatefmt
407  *          The URelativeDateTimeFormatter object specifying the
408  *          format conventions.
409  * @param offset
410  *          The signed offset for the specified unit.
411  * @param unit
412  *          The unit to use when formatting the relative
413  *          date, e.g. UDAT_REL_UNIT_WEEK, UDAT_REL_UNIT_FRIDAY.
414  * @param result
415  *          A pointer to a buffer to receive the formatted result.
416  * @param resultCapacity
417  *          The maximum size of result.
418  * @param status
419  *          A pointer to a UErrorCode to receive any errors. In
420  *          case of error status, the contents of result are
421  *          undefined.
422  * @return
423  *          The length of the formatted result; may be greater
424  *          than resultCapacity, in which case an error is returned.
425  * @stable ICU 57
426  */
427 U_CAPI int32_t U_EXPORT2
428 ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt,
429                     double                offset,
430                     URelativeDateTimeUnit unit,
431                     UChar*                result,
432                     int32_t               resultCapacity,
433                     UErrorCode*           status);
434 
435 /**
436  * Format a combination of URelativeDateTimeUnit and numeric offset
437  * using a text style if possible, e.g. "last week", "this week",
438  * "next week", "yesterday", "tomorrow". Falls back to numeric
439  * style if no appropriate text term is available for the specified
440  * offset in the object's locale.
441  *
442  * This method populates a UFormattedRelativeDateTime, which exposes more
443  * information than the string populated by format().
444  *
445  * @param reldatefmt
446  *          The URelativeDateTimeFormatter object specifying the
447  *          format conventions.
448  * @param offset
449  *          The signed offset for the specified unit.
450  * @param unit
451  *          The unit to use when formatting the relative
452  *          date, e.g. UDAT_REL_UNIT_WEEK, UDAT_REL_UNIT_FRIDAY.
453  * @param result
454  *          A pointer to a UFormattedRelativeDateTime to populate.
455  * @param status
456  *          A pointer to a UErrorCode to receive any errors. In
457  *          case of error status, the contents of result are
458  *          undefined.
459  * @stable ICU 64
460  */
461 U_CAPI void U_EXPORT2
462 ureldatefmt_formatToResult(
463     const URelativeDateTimeFormatter* reldatefmt,
464     double                            offset,
465     URelativeDateTimeUnit             unit,
466     UFormattedRelativeDateTime*       result,
467     UErrorCode*                       status);
468 
469 /**
470  * Combines a relative date string and a time string in this object's
471  * locale. This is done with the same date-time separator used for the
472  * default calendar in this locale to produce a result such as
473  * "yesterday at 3:45 PM".
474  *
475  * @param reldatefmt
476  *          The URelativeDateTimeFormatter object specifying the format conventions.
477  * @param relativeDateString
478  *          The relative date string.
479  * @param relativeDateStringLen
480  *          The length of relativeDateString; may be -1 if relativeDateString
481  *          is zero-terminated.
482  * @param timeString
483  *          The time string.
484  * @param timeStringLen
485  *          The length of timeString; may be -1 if timeString is zero-terminated.
486  * @param result
487  *          A pointer to a buffer to receive the formatted result.
488  * @param resultCapacity
489  *          The maximum size of result.
490  * @param status
491  *          A pointer to a UErrorCode to receive any errors. In case of error status,
492  *          the contents of result are undefined.
493  * @return
494  *          The length of the formatted result; may be greater than resultCapacity,
495  *          in which case an error is returned.
496  * @stable ICU 57
497  */
498 U_CAPI int32_t U_EXPORT2
499 ureldatefmt_combineDateAndTime( const URelativeDateTimeFormatter* reldatefmt,
500                     const UChar *     relativeDateString,
501                     int32_t           relativeDateStringLen,
502                     const UChar *     timeString,
503                     int32_t           timeStringLen,
504                     UChar*            result,
505                     int32_t           resultCapacity,
506                     UErrorCode*       status );
507 
508 #endif /* !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION */
509 
510 #endif
511