]> granicus.if.org Git - icu/commitdiff
ICU-12072 RelativeDateTimeFormatter: Improve C++ format API, add plain C API (part...
authorPeter Edberg <pedberg@unicode.org>
Fri, 22 Jan 2016 07:20:54 +0000 (07:20 +0000)
committerPeter Edberg <pedberg@unicode.org>
Fri, 22 Jan 2016 07:20:54 +0000 (07:20 +0000)
X-SVN-Rev: 38189

.gitattributes
icu4c/source/i18n/i18n.vcxproj
icu4c/source/i18n/i18n.vcxproj.filters
icu4c/source/i18n/reldatefmt.cpp
icu4c/source/i18n/unicode/reldatefmt.h
icu4c/source/i18n/unicode/ureldatefmt.h [new file with mode: 0644]
icu4c/source/test/cintltst/Makefile.in
icu4c/source/test/cintltst/cformtst.c
icu4c/source/test/cintltst/cintltst.vcxproj
icu4c/source/test/cintltst/cintltst.vcxproj.filters
icu4c/source/test/cintltst/crelativedateformattest.c [new file with mode: 0644]

index bc31d74c8840a784243d30f56b3f78a4e1cb9fb1..064b997efa212c7ad0a80c6e51c79e5ec6c19bb9 100644 (file)
@@ -71,6 +71,7 @@ icu4c/source/data/region/pool.res -text
 icu4c/source/data/unit/pool.res -text
 icu4c/source/data/zone/pool.res -text
 icu4c/source/extra/uconv/uconv.vcxproj -text
+icu4c/source/i18n/unicode/ureldatefmt.h -text
 icu4c/source/samples/break/break.vcxproj -text
 icu4c/source/samples/case/case.vcxproj -text
 icu4c/source/samples/citer/citer.vcxproj -text
@@ -98,6 +99,7 @@ icu4c/source/samples/ugrep/ugrep.vcxproj -text
 icu4c/source/samples/uresb/resources.vcxproj -text
 icu4c/source/samples/uresb/uresb.vcxproj -text
 icu4c/source/samples/ustring/ustring.vcxproj -text
+icu4c/source/test/cintltst/crelativedateformattest.c -text
 icu4c/source/test/depstest/icu-dependencies-mode.el -text
 icu4c/source/test/iotest/iotest.vcxproj -text
 icu4c/source/test/letest/cletest.vcxproj -text
index 99c53dc14ecc6633813a3eea584a567f8e6ad24b..d91d7dd563cd42c4ac53eb229b3b083360261984 100644 (file)
 </Command>
       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
       <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
+</Command>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
+    </CustomBuild>
+    <CustomBuild Include="unicode\ureldatefmt.h">
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
+</Command>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
+</Command>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
+</Command>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
 </Command>
       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
     </CustomBuild>
index 9164f5a3ccac28eef4d64de6352e61c58a1ab458..a1040f5992143e8ef186ad174bc4f507c5ead2f3 100644 (file)
     <CustomBuild Include="unicode\upluralrules.h">
       <Filter>formatting</Filter>
     </CustomBuild>
+    <CustomBuild Include="unicode\ureldatefmt.h">
+      <Filter>formatting</Filter>
+    </CustomBuild>
     <CustomBuild Include="unicode\utmscale.h">
       <Filter>formatting</Filter>
     </CustomBuild>
index 4d8ca06f98a75242475ee71953ea2050fbd2929d..d8fdb3b375e2af01013d0df4b41df60616a8e09f 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ******************************************************************************
-* Copyright (C) 2014-2015, International Business Machines Corporation and
+* Copyright (C) 2014-2016, International Business Machines Corporation and
 * others. All Rights Reserved.
 ******************************************************************************
 *
@@ -12,6 +12,9 @@
 
 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION
 
+#include "unicode/ureldatefmt.h"
+#include "unicode/udisplaycontext.h"
+#include "unicode/unum.h"
 #include "unicode/localpointer.h"
 #include "quantityformatter.h"
 #include "unicode/plurrule.h"
@@ -805,6 +808,37 @@ UnicodeString& RelativeDateTimeFormatter::format(
     return appendTo.append(result);
 }
 
+UnicodeString& RelativeDateTimeFormatter::formatNumeric(
+        double offset, URelativeDateTimeUnit unit,
+        UnicodeString& appendTo, UErrorCode& status) const {
+    if (U_FAILURE(status)) {
+        return appendTo;
+    }
+    // For a quick bringup just call the above method; this leaves some
+    // holes (e.g. for handling quarter). Need to redo the data structure
+    // to support all necessary data items, and to be indexed by the
+    // newer enum.
+    UDateRelativeUnit relunit = UDAT_RELATIVE_UNIT_COUNT;
+    switch (unit) {
+        case UDAT_REL_UNIT_YEAR:    relunit = UDAT_RELATIVE_YEARS; break;
+        case UDAT_REL_UNIT_MONTH:   relunit = UDAT_RELATIVE_MONTHS; break;
+        case UDAT_REL_UNIT_WEEK:    relunit = UDAT_RELATIVE_WEEKS; break;
+        case UDAT_REL_UNIT_DAY:     relunit = UDAT_RELATIVE_DAYS; break;
+        case UDAT_REL_UNIT_HOUR:    relunit = UDAT_RELATIVE_HOURS; break;
+        case UDAT_REL_UNIT_MINUTE:  relunit = UDAT_RELATIVE_MINUTES; break;
+        case UDAT_REL_UNIT_SECOND:  relunit = UDAT_RELATIVE_SECONDS; break;
+        default: // a unit that the above method does not handle
+            status = U_MISSING_RESOURCE_ERROR;
+            return appendTo;
+    }
+    UDateDirection direction = UDAT_DIRECTION_NEXT;
+    if (offset < 0) {
+        direction = UDAT_DIRECTION_LAST;
+        offset = -offset;
+    }
+    return format(offset, direction, relunit, appendTo, status);
+}
+
 UnicodeString& RelativeDateTimeFormatter::format(
         UDateDirection direction, UDateAbsoluteUnit unit,
         UnicodeString& appendTo, UErrorCode& status) const {
@@ -823,6 +857,61 @@ UnicodeString& RelativeDateTimeFormatter::format(
     return appendTo.append(result);
 }
 
+UnicodeString& RelativeDateTimeFormatter::format(
+        double offset, URelativeDateTimeUnit unit,
+        UnicodeString& appendTo, UErrorCode& status) const {
+    if (U_FAILURE(status)) {
+        return appendTo;
+    }
+    // For a quick bringup just use the existing data structure; this leaves
+    // some holes (e.g. for handling quarter). Need to redo the data structure
+    // to support all necessary data items, and to be indexed by the
+    // newer enum.
+    UDateDirection direction = UDAT_DIRECTION_COUNT;
+    int32_t intoffset = (offset < 0)? (int32_t)(offset-0.5) : (int32_t)(offset+0.5);
+    switch (intoffset) {
+        case -2: direction = UDAT_DIRECTION_LAST_2; break;
+        case -1: direction = UDAT_DIRECTION_LAST; break;
+        case  0: direction = UDAT_DIRECTION_THIS; break;
+        case  1: direction = UDAT_DIRECTION_NEXT; break;
+        case  2: direction = UDAT_DIRECTION_NEXT_2; break;
+        default: break;
+    }
+    UDateAbsoluteUnit absunit = UDAT_ABSOLUTE_UNIT_COUNT;
+    switch (unit) {
+        case UDAT_REL_UNIT_YEAR:    absunit = UDAT_ABSOLUTE_YEAR; break;
+        case UDAT_REL_UNIT_MONTH:   absunit = UDAT_ABSOLUTE_MONTH; break;
+        case UDAT_REL_UNIT_WEEK:    absunit = UDAT_ABSOLUTE_WEEK; break;
+        case UDAT_REL_UNIT_DAY:     absunit = UDAT_ABSOLUTE_DAY; break;
+        case UDAT_REL_UNIT_MINUTE:
+        case UDAT_REL_UNIT_SECOND:
+            if (direction == UDAT_DIRECTION_THIS) {
+                absunit = UDAT_ABSOLUTE_NOW;
+                direction = UDAT_DIRECTION_PLAIN;
+            }
+            break;
+        case UDAT_REL_UNIT_SUNDAY:  absunit = UDAT_ABSOLUTE_SUNDAY; break;
+        case UDAT_REL_UNIT_MONDAY:  absunit = UDAT_ABSOLUTE_MONDAY; break;
+        case UDAT_REL_UNIT_TUESDAY:  absunit = UDAT_ABSOLUTE_TUESDAY; break;
+        case UDAT_REL_UNIT_WEDNESDAY:  absunit = UDAT_ABSOLUTE_WEDNESDAY; break;
+        case UDAT_REL_UNIT_THURSDAY:  absunit = UDAT_ABSOLUTE_THURSDAY; break;
+        case UDAT_REL_UNIT_FRIDAY:  absunit = UDAT_ABSOLUTE_FRIDAY; break;
+        case UDAT_REL_UNIT_SATURDAY:  absunit = UDAT_ABSOLUTE_SATURDAY; break;
+        default: break;
+    }
+    if (direction != UDAT_DIRECTION_COUNT && absunit != UDAT_ABSOLUTE_UNIT_COUNT) {
+        UnicodeString result(fCache->absoluteUnits[fStyle][absunit][direction]);
+        if (result.length() > 0) {
+            if (fOptBreakIterator != NULL) {
+                adjustForContext(result);
+            }
+            return appendTo.append(result);
+        }
+    }
+    // otherwise fallback to formatNumeric
+    return formatNumeric(offset, unit, appendTo, status);
+}
+
 UnicodeString& RelativeDateTimeFormatter::combineDateAndTime(
     const UnicodeString& relativeDateString, const UnicodeString& timeString,
     UnicodeString& appendTo, UErrorCode& status) const {
@@ -894,8 +983,126 @@ void RelativeDateTimeFormatter::init(
     }
 }
 
-
 U_NAMESPACE_END
 
+// Plain C API
+
+U_NAMESPACE_USE
+
+U_CAPI URelativeDateTimeFormatter* U_EXPORT2
+ureldatefmt_open( const char*          locale,
+                  UNumberFormat*       nfToAdopt,
+                  UDateRelativeDateTimeFormatterStyle width,
+                  UDisplayContext      capitalizationContext,
+                  UErrorCode*          status )
+{
+    if (U_FAILURE(*status)) {
+        return NULL;
+    }
+    LocalPointer<RelativeDateTimeFormatter> formatter(new RelativeDateTimeFormatter(Locale(locale),
+                                                              (NumberFormat*)nfToAdopt, width,
+                                                              capitalizationContext, *status));
+    if (U_FAILURE(*status)) {
+        return NULL;
+    }
+    return (URelativeDateTimeFormatter*)formatter.orphan();
+}
+
+U_CAPI void U_EXPORT2
+ureldatefmt_close(URelativeDateTimeFormatter *reldatefmt)
+{
+    delete (RelativeDateTimeFormatter*)reldatefmt;
+}
+
+U_CAPI int32_t U_EXPORT2
+ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt,
+                    double                offset,
+                    URelativeDateTimeUnit unit,
+                    UChar*                result,
+                    int32_t               resultCapacity,
+                    UErrorCode*           status)
+{
+    if (U_FAILURE(*status)) {
+        return 0;
+    }
+    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return 0;
+    }
+    UnicodeString res;
+    if (result != NULL) {
+        // NULL destination for pure preflighting: empty dummy string
+        // otherwise, alias the destination buffer (copied from udat_format)
+        res.setTo(result, 0, resultCapacity);
+    }
+    ((RelativeDateTimeFormatter*)reldatefmt)->formatNumeric(offset, unit, res, *status);
+    if (U_FAILURE(*status)) {
+        return 0;
+    }
+    return res.extract(result, resultCapacity, *status);
+}
+
+U_CAPI int32_t U_EXPORT2
+ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt,
+                    double                offset,
+                    URelativeDateTimeUnit unit,
+                    UChar*                result,
+                    int32_t               resultCapacity,
+                    UErrorCode*           status)
+{
+    if (U_FAILURE(*status)) {
+        return 0;
+    }
+    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return 0;
+    }
+    UnicodeString res;
+    if (result != NULL) {
+        // NULL destination for pure preflighting: empty dummy string
+        // otherwise, alias the destination buffer (copied from udat_format)
+        res.setTo(result, 0, resultCapacity);
+    }
+    ((RelativeDateTimeFormatter*)reldatefmt)->format(offset, unit, res, *status);
+    if (U_FAILURE(*status)) {
+        return 0;
+    }
+    return res.extract(result, resultCapacity, *status);
+}
+
+U_CAPI int32_t U_EXPORT2
+ureldatefmt_combineDateAndTime( const URelativeDateTimeFormatter* reldatefmt,
+                    const UChar *     relativeDateString,
+                    int32_t           relativeDateStringLen,
+                    const UChar *     timeString,
+                    int32_t           timeStringLen,
+                    UChar*            result,
+                    int32_t           resultCapacity,
+                    UErrorCode*       status )
+{
+    if (U_FAILURE(*status)) {
+        return 0;
+    }
+    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0 ||
+            relativeDateString == NULL || relativeDateStringLen < 1 ||
+            timeString == NULL || timeStringLen < -1) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return 0;
+    }
+    UnicodeString relDateStr((UBool)(relativeDateStringLen == -1), relativeDateString, relativeDateStringLen);
+    UnicodeString timeStr((UBool)(timeStringLen == -1), timeString, timeStringLen);
+    UnicodeString res;
+    if (result != NULL) {
+        // NULL destination for pure preflighting: empty dummy string
+        // otherwise, alias the destination buffer (copied from udat_format)
+        res.setTo(result, 0, resultCapacity);
+    }
+    ((RelativeDateTimeFormatter*)reldatefmt)->combineDateAndTime(relDateStr, timeStr, res, *status);
+    if (U_FAILURE(*status)) {
+        return 0;
+    }
+    return res.extract(result, resultCapacity, *status);
+}
+
 #endif /* !UCONFIG_NO_FORMATTING */
 
index c3350c516c4e6fb79b12c2c5371110506e23d662..ffd485ec12717725dbb1a453109e98516d1570f4 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *****************************************************************************
-* Copyright (C) 2014-2015, International Business Machines Corporation and
+* Copyright (C) 2014-2016, International Business Machines Corporation and
 * others.
 * All Rights Reserved.
 *****************************************************************************
@@ -15,6 +15,7 @@
 #include "unicode/utypes.h"
 #include "unicode/uobject.h"
 #include "unicode/udisplaycontext.h"
+#include "unicode/ureldatefmt.h"
 #include "unicode/locid.h"
 
 /**
 
 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION
 
-/**
- * The formatting style
- * @stable ICU 54
- */
-typedef enum UDateRelativeDateTimeFormatterStyle {
-  /**
-   * Everything spelled out.
-   * @stable ICU 54
-   */
-  UDAT_STYLE_LONG,
-
-  /**
-   * Abbreviations used when possible.
-   * @stable ICU 54
-   */
-  UDAT_STYLE_SHORT,
-
-  /**
-   * Use the shortest possible form.
-   * @stable ICU 54
-   */
-  UDAT_STYLE_NARROW,
-
-  /**
-   * The number of styles.
-   * @stable ICU 54
-   */
-  UDAT_STYLE_COUNT
-} UDateRelativeDateTimeFormatterStyle;
-
 /**
  * Represents the unit for formatting a relative date. e.g "in 5 days"
  * or "in 3 months"
@@ -434,6 +405,54 @@ public:
             UnicodeString& appendTo,
             UErrorCode& status) const;
 
+#ifndef U_HIDE_DRAFT_API
+    /**
+     * Format a combination of URelativeDateTimeUnit and numeric offset
+     * using a numeric style, e.g. "1 week ago", "in 1 week",
+     * "5 weeks ago", "in 5 weeks".
+     * 
+     * @param offset    The signed offset for the specified unit. This
+     *                  will be formatted according to this object's
+     *                  NumberFormat object.
+     * @param unit      The unit to use when formatting the relative
+     *                  date, e.g. UDAT_REL_UNIT_WEEK,
+     *                  UDAT_REL_UNIT_FRIDAY.
+     * @param appendTo  The string to which the formatted result will be
+     *                  appended.
+     * @param status    ICU error code returned here.
+     * @return          appendTo
+     * @draft ICU 57
+     */
+    UnicodeString& formatNumeric(
+            double offset,
+            URelativeDateTimeUnit unit,
+            UnicodeString& appendTo,
+            UErrorCode& status) const;
+
+    /**
+     * Format a combination of URelativeDateTimeUnit and numeric offset
+     * using a text style if possible, e.g. "last week", "this week",
+     * "next week", "yesterday", "tomorrow". Falls back to numeric
+     * style if no appropriate text term is available for the specified
+     * offset in the object’s locale.
+     *
+     * @param offset    The signed offset for the specified unit.
+     * @param unit      The unit to use when formatting the relative
+     *                  date, e.g. UDAT_REL_UNIT_WEEK,
+     *                  UDAT_REL_UNIT_FRIDAY.
+     * @param appendTo  The string to which the formatted result will be
+     *                  appended.
+     * @param status    ICU error code returned here.
+     * @return          appendTo
+     * @draft ICU 57
+     */
+    UnicodeString& format(
+            double offset,
+            URelativeDateTimeUnit unit,
+            UnicodeString& appendTo,
+            UErrorCode& status) const;
+#endif  /* U_HIDE_DRAFT_API */
+
     /**
      * Combines a relative date string and a time string in this object's
      * locale. This is done with the same date-time separator used for the
diff --git a/icu4c/source/i18n/unicode/ureldatefmt.h b/icu4c/source/i18n/unicode/ureldatefmt.h
new file mode 100644 (file)
index 0000000..ba4f989
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+*****************************************************************************************
+* Copyright (C) 2016, International Business Machines
+* Corporation and others. All Rights Reserved.
+*****************************************************************************************
+*/
+
+#ifndef URELDATEFMT_H
+#define URELDATEFMT_H
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION
+
+#include "unicode/unum.h"
+#include "unicode/udisplaycontext.h"
+#include "unicode/localpointer.h"
+
+/**
+ * \file
+ * \brief C API: URelativeDateTimeFormatter, relative date formatting of unit + numeric offset.
+ *
+ * Provides simple formatting of relative dates, in two ways
+ * <ul>
+ *   <li>relative dates with a quantity e.g "in 5 days"</li>
+ *   <li>relative dates without a quantity e.g "next Tuesday"</li>
+ * </ul>
+ * <p>
+ * This does not provide compound formatting for multiple units,
+ * other than the ability to combine a time string with a relative date,
+ * as in "next Tuesday at 3:45 PM". It also does not provide support
+ * for determining which unit to use, such as deciding between "in 7 days"
+ * and "in 1 week".
+ *
+ * @draft ICU 57
+ */
+
+/**
+ * The formatting style
+ * @stable ICU 54
+ */
+typedef enum UDateRelativeDateTimeFormatterStyle {
+  /**
+   * Everything spelled out.
+   * @stable ICU 54
+   */
+  UDAT_STYLE_LONG,
+
+  /**
+   * Abbreviations used when possible.
+   * @stable ICU 54
+   */
+  UDAT_STYLE_SHORT,
+
+  /**
+   * Use the shortest possible form.
+   * @stable ICU 54
+   */
+  UDAT_STYLE_NARROW,
+
+  /**
+   * The number of styles.
+   * @stable ICU 54
+   */
+  UDAT_STYLE_COUNT
+} UDateRelativeDateTimeFormatterStyle;
+
+#ifndef U_HIDE_DRAFT_API
+/**
+ * Represents the unit for formatting a relative date. e.g "in 5 days"
+ * or "next year"
+ * @draft ICU 57
+ */
+typedef enum URelativeDateTimeUnit {
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_YEAR,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_QUARTER,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_MONTH,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_WEEK,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_DAY,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_HOUR,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_MINUTE,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_SECOND,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_SUNDAY,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_MONDAY,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_TUESDAY,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_WEDNESDAY,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_THURSDAY,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_FRIDAY,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_SATURDAY,
+    /** @draft ICU 57 */
+    UDAT_REL_UNIT_COUNT
+} URelativeDateTimeUnit;
+#endif  /* U_HIDE_DRAFT_API */
+
+#ifndef U_HIDE_DRAFT_API
+
+/**
+ * Opaque URelativeDateTimeFormatter object for use in C programs.
+ * @draft ICU 57
+ */
+struct URelativeDateTimeFormatter;
+typedef struct URelativeDateTimeFormatter URelativeDateTimeFormatter;  /**< C typedef for struct URelativeDateTimeFormatter. @draft ICU 57 */
+
+
+/**
+ * Open a new URelativeDateTimeFormatter object for a given locale using the
+ * specified width and capitalizationContext, along with a number formatter
+ * (if desired) to override the default formatter that would be used for
+ * display of numeric field offsets. The default formatter typically rounds
+ * toward 0 and has a minimum of 0 fraction digits and a maximum of 3
+ * fraction digits (i.e. it will show as many decimal places as necessary
+ * up to 3, without showing trailing 0s).
+ *
+ * @param locale
+ *          The locale
+ * @param nfToAdopt
+ *          A number formatter to set for this URelativeDateTimeFormatter
+ *          object (instead of the default decimal formatter). Ownership of
+ *          this UNumberFormat object will pass to the URelativeDateTimeFormatter
+ *          object (the URelativeDateTimeFormatter adopts the UNumberFormat),
+ *          which becomes responsible for closing it. If the caller wishes to
+ *          retain ownership of the UNumberFormat object, the caller must clone
+ *          it (with unum_clone) and pass the clone to ureldatefmt_open. May be
+ *          NULL to use the default decimal formatter.
+ * @param width
+ *          The width - wide, short, narrow, etc.
+ * @param capitalizationContext
+ *          A value from UDisplayContext that pertains to capitalization, e.g.
+ *          UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE.
+ * @param status
+ *          A pointer to a UErrorCode to receive any errors.
+ * @return
+ *          A pointer to a URelativeDateTimeFormatter object for the specified locale,
+ *          or NULL if an error occurred.
+ * @draft ICU 57
+ */
+U_DRAFT URelativeDateTimeFormatter* U_EXPORT2
+ureldatefmt_open( const char*          locale,
+                  UNumberFormat*       nfToAdopt,
+                  UDateRelativeDateTimeFormatterStyle width,
+                  UDisplayContext      capitalizationContext,
+                  UErrorCode*          status );
+
+/**
+ * Close a URelativeDateTimeFormatter object. Once closed it may no longer be used.
+ * @param reldatefmt
+ *            The URelativeDateTimeFormatter object to close.
+ * @draft ICU 57
+ */
+U_DRAFT void U_EXPORT2
+ureldatefmt_close(URelativeDateTimeFormatter *reldatefmt);
+
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalURelativeDateTimeFormatterPointer
+ * "Smart pointer" class, closes a URelativeDateTimeFormatter via ureldatefmt_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @draft ICU 57
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalURelativeDateTimeFormatterPointer, URelativeDateTimeFormatter, ureldatefmt_close);
+
+U_NAMESPACE_END
+
+#endif
+
+/**
+ * Format a combination of URelativeDateTimeUnit and numeric
+ * offset using a numeric style, e.g. "1 week ago", "in 1 week",
+ * "5 weeks ago", "in 5 weeks".
+ *
+ * @param reldatefmt
+ *          The URelativeDateTimeFormatter object specifying the
+ *          format conventions.
+ * @param offset
+ *          The signed offset for the specified unit. This will
+ *          be formatted according to this object's UNumberFormat
+ *          object.
+ * @param unit
+ *          The unit to use when formatting the relative
+ *          date, e.g. UDAT_REL_UNIT_WEEK, UDAT_REL_UNIT_FRIDAY.
+ * @param result
+ *          A pointer to a buffer to receive the formatted result.
+ * @param resultCapacity
+ *          The maximum size of result.
+ * @param status
+ *          A pointer to a UErrorCode to receive any errors. In
+ *          case of error status, the contents of result are
+ *          undefined.
+ * @return
+ *          The length of the formatted result; may be greater
+ *          than resultCapacity, in which case an error is returned.
+ * @draft ICU 57
+ */
+U_DRAFT int32_t U_EXPORT2
+ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt,
+                    double                offset,
+                    URelativeDateTimeUnit unit,
+                    UChar*                result,
+                    int32_t               resultCapacity,
+                    UErrorCode*           status);
+
+/**
+ * Format a combination of URelativeDateTimeUnit and numeric offset
+ * using a text style if possible, e.g. "last week", "this week",
+ * "next week", "yesterday", "tomorrow". Falls back to numeric
+ * style if no appropriate text term is available for the specified
+ * offset in the object’s locale.
+ *
+ * @param reldatefmt
+ *          The URelativeDateTimeFormatter object specifying the
+ *          format conventions.
+ * @param offset
+ *          The signed offset for the specified unit.
+ * @param unit
+ *          The unit to use when formatting the relative
+ *          date, e.g. UDAT_REL_UNIT_WEEK, UDAT_REL_UNIT_FRIDAY.
+ * @param result
+ *          A pointer to a buffer to receive the formatted result.
+ * @param resultCapacity
+ *          The maximum size of result.
+ * @param status
+ *          A pointer to a UErrorCode to receive any errors. In
+ *          case of error status, the contents of result are
+ *          undefined.
+ * @return
+ *          The length of the formatted result; may be greater
+ *          than resultCapacity, in which case an error is returned.
+ * @draft ICU 57
+ */
+U_DRAFT int32_t U_EXPORT2
+ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt,
+                    double                offset,
+                    URelativeDateTimeUnit unit,
+                    UChar*                result,
+                    int32_t               resultCapacity,
+                    UErrorCode*           status);
+
+/**
+ * Combines a relative date string and a time string in this object's
+ * locale. This is done with the same date-time separator used for the
+ * default calendar in this locale to produce a result such as
+ * "yesterday at 3:45 PM".
+ *
+ * @param reldatefmt
+ *          The URelativeDateTimeFormatter object specifying the format conventions.
+ * @param relativeDateString
+ *          The relative date string.
+ * @param relativeDateStringLen
+ *          The length of relativeDateString; may be -1 if relativeDateString
+ *          is zero-terminated.
+ * @param timeString
+ *          The time string.
+ * @param timeStringLen
+ *          The length of timeString; may be -1 if timeString is zero-terminated.
+ * @param result
+ *          A pointer to a buffer to receive the formatted result.
+ * @param resultCapacity
+ *          The maximum size of result.
+ * @param status
+ *          A pointer to a UErrorCode to receive any errors. In case of error status,
+ *          the contents of result are undefined.
+ * @return
+ *          The length of the formatted result; may be greater than resultCapacity,
+ *          in which case an error is returned.
+ * @draft ICU 57
+ */
+U_DRAFT int32_t U_EXPORT2
+ureldatefmt_combineDateAndTime( const URelativeDateTimeFormatter* reldatefmt,
+                    const UChar *     relativeDateString,
+                    int32_t           relativeDateStringLen,
+                    const UChar *     timeString,
+                    int32_t           timeStringLen,
+                    UChar*            result,
+                    int32_t           resultCapacity,
+                    UErrorCode*       status );
+
+#endif  /* U_HIDE_DRAFT_API */
+
+#endif /* !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION */
+
+#endif
index b15274ca755faaf7fb0997a1fef86313557d3d12..e19874f74fbdbaae3163de1bd45533840ecbf330 100644 (file)
@@ -1,6 +1,6 @@
 #******************************************************************************
 #
-#   Copyright (C) 1999-2015, International Business Machines
+#   Copyright (C) 1999-2016, International Business Machines
 #   Corporation and others.  All Rights Reserved.
 #
 #******************************************************************************
@@ -42,7 +42,7 @@ ccaltst.o ucnvseltst.o cctest.o ccapitst.o ccolltst.o encoll.o cconvtst.o ccurrt
 cdateintervalformattest.o cdattst.o cdetst.o cdtdptst.o cdtrgtst.o cestst.o cfintst.o \
 cformtst.o cfrtst.o cg7coll.o chashtst.o cintltst.o citertst.o cjaptst.o cloctst.o \
 cmsccoll.o cmsgtst.o cpluralrulestest.o cposxtst.o cldrtest.o \
-cnmdptst.o cnormtst.o cnumtst.o crestst.o creststn.o cturtst.o \
+cnmdptst.o cnormtst.o cnumtst.o crelativedateformattest.o crestst.o creststn.o cturtst.o \
 cucdapi.o cucdtst.o custrtst.o cstrcase.o cutiltst.o nucnvtst.o nccbtst.o bocu1tst.o \
 cbiditst.o cbididat.o eurocreg.o udatatst.o utf16tst.o utransts.o \
 ncnvfbts.o ncnvtst.o putiltst.o cstrtest.o udatpg_test.o utf8tst.o \
index bf8d4018695d846f29c782abb72215770a637863..4fe5c0f7697d5a2eefb093b59fdd99940537b7d4 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 1997-2015, International Business Machines
+ * Copyright (c) 1997-2016, International Business Machines
  * Corporation and others. All Rights Reserved.
  ********************************************************************/
 /********************************************************************************
@@ -26,6 +26,7 @@ void addCalTest(TestNode**);
 void addDateForTest(TestNode**);
 void addDateTimePatternGeneratorTest(TestNode**);
 void addDateIntervalFormatTest(TestNode**);
+void addRelativeDateFormatTest(TestNode**);
 void addNumForTest(TestNode**);
 void addMsgForTest(TestNode**);
 void addDateForRgrTest(TestNode**);
@@ -45,6 +46,7 @@ void addFormatTest(TestNode** root)
     addDateForTest(root);
     addDateTimePatternGeneratorTest(root);
     addDateIntervalFormatTest(root);
+    addRelativeDateFormatTest(root);
     addNumForTest(root);
     addNumFrDepTest(root);
     addMsgForTest(root);
index 33b93b9b3207117f52cc6ff0040f70217c25daf1..07943e8df6aebda92e3c8f8e03d883d264b05071 100644 (file)
     <ClCompile Include="cldrtest.c" />
     <ClCompile Include="cloctst.c" />
     <ClCompile Include="cposxtst.c" />
+    <ClCompile Include="crelativedateformattest.c" />
     <ClCompile Include="crestst.c" />
     <ClCompile Include="creststn.c" />
     <ClCompile Include="calltest.c" />
index 95e48ed2c3171cfa2f7790b868bc19d1feb6b90a..b8a340e76c98e3dd87ee869869d774f96a1b8320 100644 (file)
     <ClCompile Include="cpluralrulestest.c">
       <Filter>formatting</Filter>
     </ClCompile>
+    <ClCompile Include="crelativedateformattest.c">
+      <Filter>formatting</Filter>
+    </ClCompile>
     <ClCompile Include="currtest.c">
       <Filter>formatting</Filter>
     </ClCompile>
diff --git a/icu4c/source/test/cintltst/crelativedateformattest.c b/icu4c/source/test/cintltst/crelativedateformattest.c
new file mode 100644 (file)
index 0000000..f0ef247
--- /dev/null
@@ -0,0 +1,111 @@
+/********************************************************************
+ * Copyright (c) 2016, International Business Machines Corporation
+ * and others. All Rights Reserved.
+ ********************************************************************/
+/* C API TEST FOR DATE INTERVAL FORMAT */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION
+
+#include "unicode/ureldatefmt.h"
+#include "unicode/unum.h"
+#include "unicode/udisplaycontext.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "cmemory.h"
+
+static void TestRelDateFmtx(void);
+
+#define LEN(a) (sizeof(a)/sizeof(a[0]))
+
+void addRelativeDateFormatTest(TestNode** root);
+
+#define TESTCASE(x) addTest(root, &x, "tsformat/crelativedateformattest/" #x)
+
+void addRelativeDateFormatTest(TestNode** root)
+{
+    TESTCASE(TestRelDateFmtx);
+}
+
+static const double offsets[] = { -5.0, -2.2, -1.0, -0.7, 0.0, 0.7, 1.0, 2.2, 5.0 };
+enum { kNumOffsets = UPRV_LENGTHOF(offsets) };
+
+static const char* en_defNum_long_midSent_week[kNumOffsets*2] = {
+/*  text             numeric */
+    "5 weeks ago",   "5 weeks ago",
+    "2.2 weeks ago", "2.2 weeks ago",
+    "last week",     "1 week ago",
+    "last week",     "0.7 weeks ago",
+    "this week",     "in 0 weeks",
+    "next week",     "in 0.7 weeks",
+    "next week",     "in 1 week",
+    "in 2.2 weeks",  "in 2.2 weeks",
+    "in 5 weeks",    "in 5 weeks",
+};
+
+typedef struct {
+    const char*                         locale;
+    int32_t                             decPlaces; /* fixed decimal places; -1 to use default num formatter */
+    UDateRelativeDateTimeFormatterStyle width;
+    UDisplayContext                     capContext;
+    URelativeDateTimeUnit               unit;
+    const char **                       expectedResults; /* for the various offsets */
+} RelDateTimeFormatTestItem;
+
+static const RelDateTimeFormatTestItem testItems[] = {
+    { "en", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK, en_defNum_long_midSent_week },
+    { NULL, 0, (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, (URelativeDateTimeUnit)0, NULL } /* terminator */
+};
+
+enum { kMaxUBuf = 64 };
+
+static void TestRelDateFmtx()
+{
+    const RelDateTimeFormatTestItem *itemPtr;
+    log_verbose("\nTesting ureldatefmt_open(), ureldatefmt_format(), ureldatefmt_formatNumeric() with various parameters\n");
+    for (itemPtr = testItems; itemPtr->locale != NULL; itemPtr++) {
+        URelativeDateTimeFormatter *reldatefmt = NULL;
+        UNumberFormat* nfToAdopt = NULL;
+        UErrorCode status = U_ZERO_ERROR;
+        int32_t iOffset;
+
+        if (itemPtr->decPlaces >= 0) {
+            nfToAdopt = unum_open(UNUM_DECIMAL, NULL, 0, itemPtr->locale, NULL, &status);
+            if ( U_FAILURE(status) ) {
+                log_data_err("FAIL: unum_open(UNUM_DECIMAL, ...) for locale %s: %s\n", itemPtr->locale, myErrorName(status));
+            }
+                   unum_setAttribute(nfToAdopt, UNUM_MIN_FRACTION_DIGITS, itemPtr->decPlaces);
+                   unum_setAttribute(nfToAdopt, UNUM_MAX_FRACTION_DIGITS, itemPtr->decPlaces);
+                   unum_setAttribute(nfToAdopt, UNUM_ROUNDING_MODE, UNUM_ROUND_DOWN);
+        }
+        reldatefmt = ureldatefmt_open(itemPtr->locale, nfToAdopt, itemPtr->width, itemPtr->capContext, &status);
+        if ( U_FAILURE(status) ) {
+            log_data_err("FAIL: ureldatefmt_open() for locale %s: %s\n", itemPtr->locale, myErrorName(status));
+        }
+
+        for (iOffset = 0; iOffset < kNumOffsets; iOffset++) {
+            UChar ubuf[kMaxUBuf];
+            int32_t ulen;
+
+            status = U_ZERO_ERROR;
+            ulen = ureldatefmt_format(reldatefmt, offsets[iOffset], itemPtr->unit, ubuf, kMaxUBuf, &status);
+            /* check results */
+
+            status = U_ZERO_ERROR;
+            ulen = ureldatefmt_formatNumeric(reldatefmt, offsets[iOffset], itemPtr->unit, ubuf, kMaxUBuf, &status);
+            /* check results */
+        }
+        
+        ureldatefmt_close(reldatefmt);
+    }
+
+
+/*
+log_err("ERROR: udtitvfmt_format for locale %s, skeleton %s, tzid %s, from %.1f, to %.1f: expect %s, get %s\n",
+log_err("FAIL: udtitvfmt_format for locale %s, skeleton %s, tzid %s, from %.1f, to %.1f: %s\n",
+log_data_err("FAIL: udtitvfmt_open for locale %s, skeleton %s, tzid %s - %s\n",
+*/
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION */