Home | History | Annotate | Download | only in cintltst
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /********************************************************************
      4  * Copyright (c) 2016, International Business Machines Corporation
      5  * and others. All Rights Reserved.
      6  ********************************************************************/
      7 /* C API TEST FOR DATE INTERVAL FORMAT */
      8 
      9 #include "unicode/utypes.h"
     10 
     11 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION
     12 
     13 #include "unicode/ureldatefmt.h"
     14 #include "unicode/unum.h"
     15 #include "unicode/udisplaycontext.h"
     16 #include "unicode/ustring.h"
     17 #include "cintltst.h"
     18 #include "cmemory.h"
     19 
     20 static void TestRelDateFmt(void);
     21 static void TestCombineDateTime(void);
     22 
     23 void addRelativeDateFormatTest(TestNode** root);
     24 
     25 #define TESTCASE(x) addTest(root, &x, "tsformat/crelativedateformattest/" #x)
     26 
     27 void addRelativeDateFormatTest(TestNode** root)
     28 {
     29     TESTCASE(TestRelDateFmt);
     30     TESTCASE(TestCombineDateTime);
     31 }
     32 
     33 static const double offsets[] = { -5.0, -2.2, -2.0, -1.0, -0.7, 0.0, 0.7, 1.0, 2.0, 5.0 };
     34 enum { kNumOffsets = UPRV_LENGTHOF(offsets) };
     35 
     36 static const char* en_decDef_long_midSent_week[kNumOffsets*2] = {
     37 /*  text                    numeric */
     38     "5 weeks ago",          "5 weeks ago",        /* -5   */
     39     "2.2 weeks ago",        "2.2 weeks ago",      /* -2.2 */
     40     "2 weeks ago",          "2 weeks ago",        /* -2   */
     41     "last week",            "1 week ago",         /* -1   */
     42     "0.7 weeks ago",        "0.7 weeks ago",      /* -0.7 */
     43     "this week",            "in 0 weeks",         /*  0   */
     44     "in 0.7 weeks",         "in 0.7 weeks",       /*  0.7 */
     45     "next week",            "in 1 week",          /*  1   */
     46     "in 2 weeks",           "in 2 weeks",         /*  2   */
     47     "in 5 weeks",           "in 5 weeks"          /*  5   */
     48 };
     49 
     50 static const char* en_dec0_long_midSent_week[kNumOffsets*2] = {
     51 /*  text                    numeric */
     52     "5 weeks ago",          "5 weeks ago",        /* -5   */
     53     "2 weeks ago",          "2 weeks ago",        /* -2.2 */
     54     "2 weeks ago",          "2 weeks ago",        /* -2  */
     55     "last week",            "1 week ago",         /* -1   */
     56     "0 weeks ago",          "0 weeks ago",        /* -0.7 */
     57     "this week",            "in 0 weeks",         /*  0   */
     58     "in 0 weeks",           "in 0 weeks",         /*  0.7 */
     59     "next week",            "in 1 week",          /*  1   */
     60     "in 2 weeks",           "in 2 weeks",         /*  2   */
     61     "in 5 weeks",           "in 5 weeks"          /*  5   */
     62 };
     63 
     64 static const char* en_decDef_short_midSent_week[kNumOffsets*2] = {
     65 /*  text                    numeric */
     66     "5 wk. ago",            "5 wk. ago",          /* -5   */
     67     "2.2 wk. ago",          "2.2 wk. ago",        /* -2.2 */
     68     "2 wk. ago",            "2 wk. ago",          /* -2   */
     69     "last wk.",             "1 wk. ago",          /* -1   */
     70     "0.7 wk. ago",          "0.7 wk. ago",        /* -0.7 */
     71     "this wk.",             "in 0 wk.",           /*  0   */
     72     "in 0.7 wk.",           "in 0.7 wk.",         /*  0.7 */
     73     "next wk.",             "in 1 wk.",           /*  1   */
     74     "in 2 wk.",             "in 2 wk.",           /*  2   */
     75     "in 5 wk.",             "in 5 wk."            /*  5   */
     76 };
     77 
     78 static const char* en_decDef_long_midSent_min[kNumOffsets*2] = {
     79 /*  text                    numeric */
     80     "5 minutes ago",        "5 minutes ago",      /* -5   */
     81     "2.2 minutes ago",      "2.2 minutes ago",    /* -2.2 */
     82     "2 minutes ago",        "2 minutes ago",      /* -2   */
     83     "1 minute ago",         "1 minute ago",       /* -1   */
     84     "0.7 minutes ago",      "0.7 minutes ago",    /* -0.7 */
     85     "in 0 minutes",         "in 0 minutes",       /*  0   */
     86     "in 0.7 minutes",       "in 0.7 minutes",     /*  0.7 */
     87     "in 1 minute",          "in 1 minute",        /*  1   */
     88     "in 2 minutes",         "in 2 minutes",       /*  2   */
     89     "in 5 minutes",         "in 5 minutes"        /*  5   */
     90 };
     91 
     92 static const char* en_dec0_long_midSent_tues[kNumOffsets*2] = {
     93 /*  text                    numeric */
     94     ""/*no data */,         ""/*no data */,       /* -5   */
     95     ""/*no data */,         ""/*no data */,       /* -2.2 */
     96     ""/*no data */,         ""/*no data */,       /* -2   */
     97     "last Tuesday",         ""/*no data */,       /* -1   */
     98     ""/*no data */,         ""/*no data */,       /* -0.7 */
     99     "this Tuesday",         ""/*no data */,       /*  0   */
    100     ""/*no data */,         ""/*no data */,       /*  0.7 */
    101     "next Tuesday",         ""/*no data */,       /*  1   */
    102     ""/*no data */,         ""/*no data */,       /*  2   */
    103     ""/*no data */,         ""/*no data */,       /*  5   */
    104 };
    105 
    106 static const char* fr_decDef_long_midSent_day[kNumOffsets*2] = {
    107 /*  text                    numeric */
    108     "il y a 5 jours",       "il y a 5 jours",     /* -5   */
    109     "il y a 2,2 jours",     "il y a 2,2 jours",   /* -2.2 */
    110     "avant-hier",           "il y a 2 jours",     /* -2   */
    111     "hier",                 "il y a 1 jour",      /* -1   */
    112     "il y a 0,7 jour",      "il y a 0,7 jour",    /* -0.7 */
    113     "aujourd\\u2019hui",    "dans 0 jour",        /*  0   */
    114     "dans 0,7 jour",        "dans 0,7 jour",      /*  0.7 */
    115     "demain",               "dans 1 jour",        /*  1   */
    116     "apr\\u00E8s-demain",   "dans 2 jours",       /*  2   */
    117     "dans 5 jours",         "dans 5 jours"        /*  5   */
    118 };
    119 
    120 
    121 typedef struct {
    122     const char*                         locale;
    123     int32_t                             decPlaces; /* fixed decimal places; -1 to use default num formatter */
    124     UDateRelativeDateTimeFormatterStyle width;
    125     UDisplayContext                     capContext;
    126     URelativeDateTimeUnit               unit;
    127     const char **                       expectedResults; /* for the various offsets */
    128 } RelDateTimeFormatTestItem;
    129 
    130 static const RelDateTimeFormatTestItem fmtTestItems[] = {
    131     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_decDef_long_midSent_week  },
    132     { "en",  0, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_dec0_long_midSent_week    },
    133     { "en", -1, UDAT_STYLE_SHORT, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_decDef_short_midSent_week },
    134     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_MINUTE,  en_decDef_long_midSent_min   },
    135     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_TUESDAY, en_dec0_long_midSent_tues    },
    136     { "fr", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_DAY,     fr_decDef_long_midSent_day   },
    137     { NULL,  0, (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, (URelativeDateTimeUnit)0, NULL } /* terminator */
    138 };
    139 
    140 enum { kUBufMax = 64, kBBufMax = 256 };
    141 
    142 static void TestRelDateFmt()
    143 {
    144     const RelDateTimeFormatTestItem *itemPtr;
    145     log_verbose("\nTesting ureldatefmt_open(), ureldatefmt_format(), ureldatefmt_formatNumeric() with various parameters\n");
    146     for (itemPtr = fmtTestItems; itemPtr->locale != NULL; itemPtr++) {
    147         URelativeDateTimeFormatter *reldatefmt = NULL;
    148         UNumberFormat* nfToAdopt = NULL;
    149         UErrorCode status = U_ZERO_ERROR;
    150         int32_t iOffset;
    151 
    152         if (itemPtr->decPlaces >= 0) {
    153             nfToAdopt = unum_open(UNUM_DECIMAL, NULL, 0, itemPtr->locale, NULL, &status);
    154             if ( U_FAILURE(status) ) {
    155                 log_data_err("FAIL: unum_open(UNUM_DECIMAL, ...) for locale %s: %s\n", itemPtr->locale, myErrorName(status));
    156                 continue;
    157             }
    158 		    unum_setAttribute(nfToAdopt, UNUM_MIN_FRACTION_DIGITS, itemPtr->decPlaces);
    159 		    unum_setAttribute(nfToAdopt, UNUM_MAX_FRACTION_DIGITS, itemPtr->decPlaces);
    160 		    unum_setAttribute(nfToAdopt, UNUM_ROUNDING_MODE, UNUM_ROUND_DOWN);
    161         }
    162         reldatefmt = ureldatefmt_open(itemPtr->locale, nfToAdopt, itemPtr->width, itemPtr->capContext, &status);
    163         if ( U_FAILURE(status) ) {
    164             log_data_err("FAIL: ureldatefmt_open() for locale %s, decPlaces %d, width %d, capContext %d: %s\n",
    165                     itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
    166                     myErrorName(status) );
    167             continue;
    168         }
    169 
    170         for (iOffset = 0; iOffset < kNumOffsets; iOffset++) {
    171             UChar ubufget[kUBufMax];
    172             int32_t ulenget;
    173 
    174             if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY && offsets[iOffset] != -1.0 && offsets[iOffset] != 0.0 && offsets[iOffset] != 1.0) {
    175                 continue; /* we do not currently have data for this */
    176             }
    177 
    178             status = U_ZERO_ERROR;
    179             ulenget = ureldatefmt_format(reldatefmt, offsets[iOffset], itemPtr->unit, ubufget, kUBufMax, &status);
    180             if ( U_FAILURE(status) ) {
    181                 log_err("FAIL: ureldatefmt_format() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
    182                     itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
    183                     offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
    184             } else {
    185                 UChar ubufexp[kUBufMax];
    186                 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2], ubufexp, kUBufMax);
    187                 if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
    188                     char  bbufget[kBBufMax];
    189                     u_austrncpy(bbufget, ubufget, kUBufMax);
    190                     log_err("ERROR: ureldatefmt_format() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d;\n      expected %s\n      get      %s\n",
    191                         itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
    192                         offsets[iOffset], (int)itemPtr->unit, itemPtr->expectedResults[iOffset*2], bbufget );
    193                 }
    194             }
    195 
    196             if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY) {
    197                 continue; /* we do not currently have numeric-style data for this */
    198             }
    199 
    200             status = U_ZERO_ERROR;
    201             ulenget = ureldatefmt_formatNumeric(reldatefmt, offsets[iOffset], itemPtr->unit, ubufget, kUBufMax, &status);
    202             if ( U_FAILURE(status) ) {
    203                 log_err("FAIL: ureldatefmt_formatNumeric() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
    204                     itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
    205                     offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
    206             } else {
    207                 UChar ubufexp[kUBufMax];
    208                 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2 + 1], ubufexp, kUBufMax);
    209                 if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
    210                     char  bbufget[kBBufMax];
    211                     u_austrncpy(bbufget, ubufget, kUBufMax);
    212                     log_err("ERROR: ureldatefmt_formatNumeric() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d;\n      expected %s\n      get      %s\n",
    213                         itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
    214                         offsets[iOffset], (int)itemPtr->unit, itemPtr->expectedResults[iOffset*2 + 1], bbufget );
    215                 }
    216             }
    217         }
    218 
    219         ureldatefmt_close(reldatefmt);
    220     }
    221 }
    222 
    223 typedef struct {
    224     const char*                         locale;
    225     UDateRelativeDateTimeFormatterStyle width;
    226     UDisplayContext                     capContext;
    227     const char *                        relativeDateString;
    228     const char *                        timeString;
    229     const char *                        expectedResult;
    230 } CombineDateTimeTestItem;
    231 
    232 static const CombineDateTimeTestItem combTestItems[] = {
    233     { "en",  UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, "yesterday",  "3:45 PM",  "yesterday, 3:45 PM" },
    234     { NULL,  (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, NULL, NULL, NULL } /* terminator */
    235 };
    236 
    237 static void TestCombineDateTime()
    238 {
    239     const CombineDateTimeTestItem *itemPtr;
    240     log_verbose("\nTesting ureldatefmt_combineDateAndTime() with various parameters\n");
    241     for (itemPtr = combTestItems; itemPtr->locale != NULL; itemPtr++) {
    242         URelativeDateTimeFormatter *reldatefmt = NULL;
    243         UErrorCode status = U_ZERO_ERROR;
    244         UChar ubufreldate[kUBufMax];
    245         UChar ubuftime[kUBufMax];
    246         UChar ubufget[kUBufMax];
    247         int32_t ulenreldate, ulentime, ulenget;
    248 
    249         reldatefmt = ureldatefmt_open(itemPtr->locale, NULL, itemPtr->width, itemPtr->capContext, &status);
    250         if ( U_FAILURE(status) ) {
    251             log_data_err("FAIL: ureldatefmt_open() for locale %s, width %d, capContext %d: %s\n",
    252                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
    253             continue;
    254         }
    255 
    256         ulenreldate = u_unescape(itemPtr->relativeDateString, ubufreldate, kUBufMax);
    257         ulentime    = u_unescape(itemPtr->timeString,         ubuftime,    kUBufMax);
    258         ulenget     = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, ubufget, kUBufMax, &status);
    259         if ( U_FAILURE(status) ) {
    260             log_err("FAIL: ureldatefmt_combineDateAndTime() for locale %s, width %d, capContext %d: %s\n",
    261                 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
    262         } else {
    263             UChar ubufexp[kUBufMax];
    264             int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax);
    265             if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
    266                 char  bbufget[kBBufMax];
    267                 u_austrncpy(bbufget, ubufget, kUBufMax);
    268                 log_err("ERROR: ureldatefmt_combineDateAndTime() for locale %s, width %d, capContext %d;\n      expected %s\n      get      %s\n",
    269                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, itemPtr->expectedResult, bbufget );
    270             }
    271         }
    272         // preflight test
    273         status = U_ZERO_ERROR;
    274         ulenget = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, NULL, 0, &status);
    275         if ( status != U_BUFFER_OVERFLOW_ERROR) {
    276             log_err("FAIL: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d: expected U_BUFFER_OVERFLOW_ERROR, got %s\n",
    277                 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
    278         } else {
    279             UChar ubufexp[kUBufMax];
    280             int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax);
    281             if (ulenget != ulenexp) {
    282                 log_err("ERROR: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d;\n      expected len %d, get len %d\n",
    283                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, ulenexp, ulenget );
    284             }
    285         }
    286 
    287         ureldatefmt_close(reldatefmt);
    288     }
    289 }
    290 
    291 #endif /* #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION */
    292