Add 'quarter' support to RelativeDateFormat

1. Do not trim 'quarter'-related strings from the locale data
   and regenerate the ICU data files.
   ICU data file size is increased by 24 ~ 35 kB.

2. Chery-pick upstream patch to support quarter in RelativeDateFormat

upstream bug:
  https://unicode-org.atlassian.net/browse/ICU-20022
PR to fix:
   https://github.com/unicode-org/icu/pull/77

This will unblock the following CL:
  https://chromium-review.googlesource.com/c/v8/v8/+/1214522

TBR=ftang@chromium.org

Bug: v8:7869
Test: See the bug
Change-Id: I11740d9b2a1fdb9b2f7bb497eda2746353fa8428
Reviewed-on: https://chromium-review.googlesource.com/1214642
Reviewed-by: Jungshik Shin <jshin@chromium.org>
diff --git a/README.chromium b/README.chromium
index 287215f..b3e0738 100644
--- a/README.chromium
+++ b/README.chromium
@@ -267,3 +267,10 @@
   - patches/decimalformat_align.patch
   - upstream bug:
     https://unicode-org.atlassian.net/browse/ICU-20039
+
+12. Cherry-pick the upstream CL for quarter support in RelativeDate format
+
+  - patches/reldate_quarter.patch
+  - upstream bug:
+    https://unicode-org.atlassian.net/browse/ICU-20022
+  - fix: https://github.com/unicode-org/icu/pull/77
diff --git a/android/icudtl.dat b/android/icudtl.dat
index d076c78..ec23562 100644
--- a/android/icudtl.dat
+++ b/android/icudtl.dat
Binary files differ
diff --git a/cast/icudtl.dat b/cast/icudtl.dat
index 0c0158c..2240788 100644
--- a/cast/icudtl.dat
+++ b/cast/icudtl.dat
Binary files differ
diff --git a/common/icudtb.dat b/common/icudtb.dat
index 470b9a3..e94ea72 100644
--- a/common/icudtb.dat
+++ b/common/icudtb.dat
Binary files differ
diff --git a/common/icudtl.dat b/common/icudtl.dat
index 4ba503b..4a9d942 100644
--- a/common/icudtl.dat
+++ b/common/icudtl.dat
Binary files differ
diff --git a/flutter/icudtl.dat b/flutter/icudtl.dat
index d9677ab..0a0e10b 100644
--- a/flutter/icudtl.dat
+++ b/flutter/icudtl.dat
Binary files differ
diff --git a/ios/icudtl.dat b/ios/icudtl.dat
index 00b1935..2ad3994 100644
--- a/ios/icudtl.dat
+++ b/ios/icudtl.dat
Binary files differ
diff --git a/patches/reldate_quarter.patch b/patches/reldate_quarter.patch
new file mode 100644
index 0000000..80f1a45
--- /dev/null
+++ b/patches/reldate_quarter.patch
@@ -0,0 +1,542 @@
+diff --git a/icu4c/source/i18n/reldatefmt.cpp b/icu4c/source/i18n/reldatefmt.cpp
+index 0a28a743e2..0af9b47a19 100644
+--- a/icu4c/source/i18n/reldatefmt.cpp
++++ b/icu4c/source/i18n/reldatefmt.cpp
+@@ -51,13 +51,13 @@ U_NAMESPACE_BEGIN
+ // RelativeDateTimeFormatter specific data for a single locale
+ class RelativeDateTimeCacheData: public SharedObject {
+ public:
+-    RelativeDateTimeCacheData() : combinedDateAndTime(NULL) {
++    RelativeDateTimeCacheData() : combinedDateAndTime(nullptr) {
+         // Initialize the cache arrays
+         for (int32_t style = 0; style < UDAT_STYLE_COUNT; ++style) {
+-            for (int32_t relUnit = 0; relUnit < UDAT_RELATIVE_UNIT_COUNT; ++relUnit) {
++            for (int32_t relUnit = 0; relUnit < UDAT_REL_UNIT_COUNT; ++relUnit) {
+                 for (int32_t pl = 0; pl < StandardPlural::COUNT; ++pl) {
+-                    relativeUnitsFormatters[style][relUnit][0][pl] = NULL;
+-                    relativeUnitsFormatters[style][relUnit][1][pl] = NULL;
++                    relativeUnitsFormatters[style][relUnit][0][pl] = nullptr;
++                    relativeUnitsFormatters[style][relUnit][1][pl] = nullptr;
+                 }
+             }
+         }
+@@ -74,7 +74,7 @@ class RelativeDateTimeCacheData: public SharedObject {
+     // e.g., Next Tuesday; Yesterday; etc. For third index, 0
+     // means past, e.g., 5 days ago; 1 means future, e.g., in 5 days.
+     SimpleFormatter *relativeUnitsFormatters[UDAT_STYLE_COUNT]
+-        [UDAT_RELATIVE_UNIT_COUNT][2][StandardPlural::COUNT];
++        [UDAT_REL_UNIT_COUNT][2][StandardPlural::COUNT];
+ 
+     const UnicodeString& getAbsoluteUnitString(int32_t fStyle,
+                                                UDateAbsoluteUnit unit,
+@@ -83,6 +83,10 @@ class RelativeDateTimeCacheData: public SharedObject {
+                                                     UDateRelativeUnit unit,
+                                                     int32_t pastFutureIndex,
+                                                     int32_t pluralUnit) const;
++    const SimpleFormatter* getRelativeDateTimeUnitFormatter(int32_t fStyle,
++                                                    URelativeDateTimeUnit unit,
++                                                    int32_t pastFutureIndex,
++                                                    int32_t pluralUnit) const;
+ 
+     const UnicodeString emptyString;
+ 
+@@ -107,7 +111,7 @@ class RelativeDateTimeCacheData: public SharedObject {
+ RelativeDateTimeCacheData::~RelativeDateTimeCacheData() {
+     // clear out the cache arrays
+     for (int32_t style = 0; style < UDAT_STYLE_COUNT; ++style) {
+-        for (int32_t relUnit = 0; relUnit < UDAT_RELATIVE_UNIT_COUNT; ++relUnit) {
++        for (int32_t relUnit = 0; relUnit < UDAT_REL_UNIT_COUNT; ++relUnit) {
+             for (int32_t pl = 0; pl < StandardPlural::COUNT; ++pl) {
+                 delete relativeUnitsFormatters[style][relUnit][0][pl];
+                 delete relativeUnitsFormatters[style][relUnit][1][pl];
+@@ -131,20 +135,41 @@ const UnicodeString& RelativeDateTimeCacheData::getAbsoluteUnitString(
+     return emptyString;
+ }
+ 
+- // Use fallback cache for SimpleFormatter relativeUnits.
+  const SimpleFormatter* RelativeDateTimeCacheData::getRelativeUnitFormatter(
+         int32_t fStyle,
+         UDateRelativeUnit unit,
+         int32_t pastFutureIndex,
+         int32_t pluralUnit) const {
++   URelativeDateTimeUnit rdtunit = UDAT_REL_UNIT_COUNT;
++   switch (unit) {
++       case UDAT_RELATIVE_YEARS:   rdtunit = UDAT_REL_UNIT_YEAR; break;
++       case UDAT_RELATIVE_MONTHS:  rdtunit = UDAT_REL_UNIT_MONTH; break;
++       case UDAT_RELATIVE_WEEKS:   rdtunit = UDAT_REL_UNIT_WEEK; break;
++       case UDAT_RELATIVE_DAYS:    rdtunit = UDAT_REL_UNIT_DAY; break;
++       case UDAT_RELATIVE_HOURS:   rdtunit = UDAT_REL_UNIT_HOUR; break;
++       case UDAT_RELATIVE_MINUTES: rdtunit = UDAT_REL_UNIT_MINUTE; break;
++       case UDAT_RELATIVE_SECONDS: rdtunit = UDAT_REL_UNIT_SECOND; break;
++       default: // a unit that the above method does not handle
++            return nullptr;
++   }
++
++   return getRelativeDateTimeUnitFormatter(fStyle, rdtunit, pastFutureIndex, pluralUnit);
++ }
++
++ // Use fallback cache for SimpleFormatter relativeUnits.
++ const SimpleFormatter* RelativeDateTimeCacheData::getRelativeDateTimeUnitFormatter(
++        int32_t fStyle,
++        URelativeDateTimeUnit unit,
++        int32_t pastFutureIndex,
++        int32_t pluralUnit) const {
+     int32_t style = fStyle;
+     do {
+-        if (relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit] != NULL) {
++        if (relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit] != nullptr) {
+             return relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit];
+         }
+         style = fallBackCache[style];
+     } while (style != -1);
+-    return NULL;  // No formatter found.
++    return nullptr;  // No formatter found.
+  }
+ 
+ static UBool getStringWithFallback(
+@@ -217,23 +242,35 @@ struct RelDateTimeFmtDataSink : public ResourceSink {
+         // Converts the generic units to UDAT_RELATIVE version.
+         switch (genUnit) {
+             case SECOND:
+-                return UDAT_RELATIVE_SECONDS;
++                return UDAT_REL_UNIT_SECOND;
+             case MINUTE:
+-                return UDAT_RELATIVE_MINUTES;
++                return UDAT_REL_UNIT_MINUTE;
+             case HOUR:
+-                return UDAT_RELATIVE_HOURS;
++                return UDAT_REL_UNIT_HOUR;
+             case DAY:
+-                return UDAT_RELATIVE_DAYS;
++                return UDAT_REL_UNIT_DAY;
+             case WEEK:
+-                return UDAT_RELATIVE_WEEKS;
++                return UDAT_REL_UNIT_WEEK;
+             case MONTH:
+-                return UDAT_RELATIVE_MONTHS;
+-            /*
+-             * case QUARTER:
+-             * return UDATE_RELATIVE_QUARTERS;
+-             */
++                return UDAT_REL_UNIT_MONTH;
++            case QUARTER:
++                return UDAT_REL_UNIT_QUARTER;
+             case YEAR:
+-                return UDAT_RELATIVE_YEARS;
++                return UDAT_REL_UNIT_YEAR;
++            case SUNDAY:
++                return UDAT_REL_UNIT_SUNDAY;
++            case MONDAY:
++                return UDAT_REL_UNIT_MONDAY;
++            case TUESDAY:
++                return UDAT_REL_UNIT_TUESDAY;
++            case WEDNESDAY:
++                return UDAT_REL_UNIT_WEDNESDAY;
++            case THURSDAY:
++                return UDAT_REL_UNIT_THURSDAY;
++            case FRIDAY:
++                return UDAT_REL_UNIT_FRIDAY;
++            case SATURDAY:
++                return UDAT_REL_UNIT_SATURDAY;
+             default:
+                 return -1;
+         }
+@@ -248,10 +285,8 @@ struct RelDateTimeFmtDataSink : public ResourceSink {
+                 return UDAT_ABSOLUTE_WEEK;
+             case MONTH:
+                 return UDAT_ABSOLUTE_MONTH;
+-            /* TODO: Add in QUARTER
+-             *  case QUARTER:
+-             * return UDAT_ABSOLUTE_QUARTER;
+-             */
++            case QUARTER:
++                return UDAT_ABSOLUTE_QUARTER;
+             case YEAR:
+                 return UDAT_ABSOLUTE_YEAR;
+             case SUNDAY:
+@@ -430,7 +465,7 @@ struct RelDateTimeFmtDataSink : public ResourceSink {
+                 }
+ 
+                 int32_t relUnitIndex = relUnitFromGeneric(genericUnit);
+-                if (relUnitIndex == UDAT_RELATIVE_SECONDS && uprv_strcmp(key, "0") == 0 &&
++                if (relUnitIndex == UDAT_REL_UNIT_SECOND && uprv_strcmp(key, "0") == 0 &&
+                     outputData.absoluteUnits[style][UDAT_ABSOLUTE_NOW][UDAT_DIRECTION_PLAIN].isEmpty()) {
+                     // Handle "NOW"
+                     outputData.absoluteUnits[style][UDAT_ABSOLUTE_NOW]
+@@ -463,10 +498,10 @@ struct RelDateTimeFmtDataSink : public ResourceSink {
+                         outputData.relativeUnitsFormatters[style][relUnitIndex]
+                         [pastFutureIndex];
+                     // Only set if not already established.
+-                    if (patterns[pluralIndex] == NULL) {
++                    if (patterns[pluralIndex] == nullptr) {
+                         patterns[pluralIndex] = new SimpleFormatter(
+                             value.getUnicodeString(errorCode), 0, 1, errorCode);
+-                        if (patterns[pluralIndex] == NULL) {
++                        if (patterns[pluralIndex] == nullptr) {
+                             errorCode = U_MEMORY_ALLOCATION_ERROR;
+                         }
+                     }
+@@ -619,7 +654,7 @@ static UBool getDateTimePattern(
+             .append("/DateTimePatterns", status);
+     LocalUResourceBundlePointer topLevel(
+             ures_getByKeyWithFallback(
+-                    resource, pathBuffer.data(), NULL, &status));
++                    resource, pathBuffer.data(), nullptr, &status));
+     if (U_FAILURE(status)) {
+         return FALSE;
+     }
+@@ -636,68 +671,68 @@ static UBool getDateTimePattern(
+ template<> U_I18N_API
+ const RelativeDateTimeCacheData *LocaleCacheKey<RelativeDateTimeCacheData>::createObject(const void * /*unused*/, UErrorCode &status) const {
+     const char *localeId = fLoc.getName();
+-    LocalUResourceBundlePointer topLevel(ures_open(NULL, localeId, &status));
++    LocalUResourceBundlePointer topLevel(ures_open(nullptr, localeId, &status));
+     if (U_FAILURE(status)) {
+-        return NULL;
++        return nullptr;
+     }
+     LocalPointer<RelativeDateTimeCacheData> result(
+             new RelativeDateTimeCacheData());
+     if (result.isNull()) {
+         status = U_MEMORY_ALLOCATION_ERROR;
+-        return NULL;
++        return nullptr;
+     }
+     if (!loadUnitData(
+             topLevel.getAlias(),
+             *result,
+             localeId,
+             status)) {
+-        return NULL;
++        return nullptr;
+     }
+     UnicodeString dateTimePattern;
+     if (!getDateTimePattern(topLevel.getAlias(), dateTimePattern, status)) {
+-        return NULL;
++        return nullptr;
+     }
+     result->adoptCombinedDateAndTime(
+             new SimpleFormatter(dateTimePattern, 2, 2, status));
+     if (U_FAILURE(status)) {
+-        return NULL;
++        return nullptr;
+     }
+     result->addRef();
+     return result.orphan();
+ }
+ 
+ RelativeDateTimeFormatter::RelativeDateTimeFormatter(UErrorCode& status) :
+-        fCache(NULL),
+-        fNumberFormat(NULL),
+-        fPluralRules(NULL),
++        fCache(nullptr),
++        fNumberFormat(nullptr),
++        fPluralRules(nullptr),
+         fStyle(UDAT_STYLE_LONG),
+         fContext(UDISPCTX_CAPITALIZATION_NONE),
+-        fOptBreakIterator(NULL) {
+-    init(NULL, NULL, status);
++        fOptBreakIterator(nullptr) {
++    init(nullptr, nullptr, status);
+ }
+ 
+ RelativeDateTimeFormatter::RelativeDateTimeFormatter(
+         const Locale& locale, UErrorCode& status) :
+-        fCache(NULL),
+-        fNumberFormat(NULL),
+-        fPluralRules(NULL),
++        fCache(nullptr),
++        fNumberFormat(nullptr),
++        fPluralRules(nullptr),
+         fStyle(UDAT_STYLE_LONG),
+         fContext(UDISPCTX_CAPITALIZATION_NONE),
+-        fOptBreakIterator(NULL),
++        fOptBreakIterator(nullptr),
+         fLocale(locale) {
+-    init(NULL, NULL, status);
++    init(nullptr, nullptr, status);
+ }
+ 
+ RelativeDateTimeFormatter::RelativeDateTimeFormatter(
+         const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status) :
+-        fCache(NULL),
+-        fNumberFormat(NULL),
+-        fPluralRules(NULL),
++        fCache(nullptr),
++        fNumberFormat(nullptr),
++        fPluralRules(nullptr),
+         fStyle(UDAT_STYLE_LONG),
+         fContext(UDISPCTX_CAPITALIZATION_NONE),
+-        fOptBreakIterator(NULL),
++        fOptBreakIterator(nullptr),
+         fLocale(locale) {
+-    init(nfToAdopt, NULL, status);
++    init(nfToAdopt, nullptr, status);
+ }
+ 
+ RelativeDateTimeFormatter::RelativeDateTimeFormatter(
+@@ -706,12 +741,12 @@ RelativeDateTimeFormatter::RelativeDateTimeFormatter(
+         UDateRelativeDateTimeFormatterStyle styl,
+         UDisplayContext capitalizationContext,
+         UErrorCode& status) :
+-        fCache(NULL),
+-        fNumberFormat(NULL),
+-        fPluralRules(NULL),
++        fCache(nullptr),
++        fNumberFormat(nullptr),
++        fPluralRules(nullptr),
+         fStyle(styl),
+         fContext(capitalizationContext),
+-        fOptBreakIterator(NULL),
++        fOptBreakIterator(nullptr),
+         fLocale(locale) {
+     if (U_FAILURE(status)) {
+         return;
+@@ -727,7 +762,7 @@ RelativeDateTimeFormatter::RelativeDateTimeFormatter(
+         }
+         init(nfToAdopt, bi, status);
+     } else {
+-        init(nfToAdopt, NULL, status);
++        init(nfToAdopt, nullptr, status);
+     }
+ }
+ 
+@@ -744,7 +779,7 @@ RelativeDateTimeFormatter::RelativeDateTimeFormatter(
+     fCache->addRef();
+     fNumberFormat->addRef();
+     fPluralRules->addRef();
+-    if (fOptBreakIterator != NULL) {
++    if (fOptBreakIterator != nullptr) {
+       fOptBreakIterator->addRef();
+     }
+ }
+@@ -764,16 +799,16 @@ RelativeDateTimeFormatter& RelativeDateTimeFormatter::operator=(
+ }
+ 
+ RelativeDateTimeFormatter::~RelativeDateTimeFormatter() {
+-    if (fCache != NULL) {
++    if (fCache != nullptr) {
+         fCache->removeRef();
+     }
+-    if (fNumberFormat != NULL) {
++    if (fNumberFormat != nullptr) {
+         fNumberFormat->removeRef();
+     }
+-    if (fPluralRules != NULL) {
++    if (fPluralRules != nullptr) {
+         fPluralRules->removeRef();
+     }
+-    if (fOptBreakIterator != NULL) {
++    if (fOptBreakIterator != nullptr) {
+         fOptBreakIterator->removeRef();
+     }
+ }
+@@ -812,7 +847,7 @@ UnicodeString& RelativeDateTimeFormatter::format(
+ 
+     const SimpleFormatter* formatter =
+         fCache->getRelativeUnitFormatter(fStyle, unit, bFuture, pluralIndex);
+-    if (formatter == NULL) {
++    if (formatter == nullptr) {
+         // TODO: WARN - look at quantity formatter's action with an error.
+         status = U_INVALID_FORMAT_ERROR;
+         return appendTo;
+@@ -828,33 +863,35 @@ UnicodeString& RelativeDateTimeFormatter::formatNumeric(
+     if (U_FAILURE(status)) {
+         return appendTo;
+     }
+-    // TODO:
+-    // The full implementation of this depends on CLDR data that is not yet available,
+-    // see: http://unicode.org/cldr/trac/ticket/9165 Add more relative field data.
+-    // In the meantime do a quick bring-up by calling the old format method; this
+-    // leaves some holes (even for data that is currently available, such as quarter).
+-    // When the new CLDR data is available, update the data storage accordingly,
+-    // rewrite this to use it directly, and rewrite the old format method to call this
+-    // new one; that is covered by http://bugs.icu-project.org/trac/ticket/12171.
+-    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_UNSUPPORTED_ERROR;
+-            return appendTo;
+-    }
+     UDateDirection direction = UDAT_DIRECTION_NEXT;
+     if (std::signbit(offset)) { // needed to handle -0.0
+         direction = UDAT_DIRECTION_LAST;
+         offset = -offset;
+     }
+-    return format(offset, direction, relunit, appendTo, status);
++    if (direction != UDAT_DIRECTION_LAST && direction != UDAT_DIRECTION_NEXT) {
++        status = U_ILLEGAL_ARGUMENT_ERROR;
++        return appendTo;
++    }
++    int32_t bFuture = direction == UDAT_DIRECTION_NEXT ? 1 : 0;
++    FieldPosition pos(FieldPosition::DONT_CARE);
++
++    UnicodeString result;
++    UnicodeString formattedNumber;
++
++    StandardPlural::Form pluralIndex = QuantityFormatter::selectPlural(
++        offset, **fNumberFormat, **fPluralRules, formattedNumber, pos,
++        status);
++
++    const SimpleFormatter* formatter =
++        fCache->getRelativeDateTimeUnitFormatter(fStyle, unit, bFuture, pluralIndex);
++    if (formatter == nullptr) {
++        // TODO: WARN - look at quantity formatter's action with an error.
++        status = U_INVALID_FORMAT_ERROR;
++        return appendTo;
++    }
++    formatter->format(formattedNumber, result, status);
++    adjustForContext(result);
++    return appendTo.append(result);
+ }
+ 
+ UnicodeString& RelativeDateTimeFormatter::format(
+@@ -871,7 +908,7 @@ UnicodeString& RelativeDateTimeFormatter::format(
+     // Get string using fallback.
+     UnicodeString result;
+     result.fastCopyFrom(fCache->getAbsoluteUnitString(fStyle, unit, direction));
+-    if (fOptBreakIterator != NULL) {
++    if (fOptBreakIterator != nullptr) {
+         adjustForContext(result);
+     }
+     return appendTo.append(result);
+@@ -908,6 +945,7 @@ UnicodeString& RelativeDateTimeFormatter::format(
+     UDateAbsoluteUnit absunit = UDAT_ABSOLUTE_UNIT_COUNT;
+     switch (unit) {
+         case UDAT_REL_UNIT_YEAR:    absunit = UDAT_ABSOLUTE_YEAR; break;
++        case UDAT_REL_UNIT_QUARTER: absunit = UDAT_ABSOLUTE_QUARTER; 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;
+@@ -930,7 +968,7 @@ UnicodeString& RelativeDateTimeFormatter::format(
+         const UnicodeString &unitFormatString =
+             fCache->getAbsoluteUnitString(fStyle, absunit, direction);
+         if (!unitFormatString.isEmpty()) {
+-            if (fOptBreakIterator != NULL) {
++            if (fOptBreakIterator != nullptr) {
+                 UnicodeString result(unitFormatString);
+                 adjustForContext(result);
+                 return appendTo.append(result);
+@@ -951,7 +989,7 @@ UnicodeString& RelativeDateTimeFormatter::combineDateAndTime(
+ }
+ 
+ void RelativeDateTimeFormatter::adjustForContext(UnicodeString &str) const {
+-    if (fOptBreakIterator == NULL
++    if (fOptBreakIterator == nullptr
+         || str.length() == 0 || !u_islower(str.char32At(0))) {
+         return;
+     }
+@@ -992,7 +1030,7 @@ void RelativeDateTimeFormatter::init(
+         shared->removeRef();
+     } else {
+         SharedNumberFormat *shared = new SharedNumberFormat(nf.getAlias());
+-        if (shared == NULL) {
++        if (shared == nullptr) {
+             status = U_MEMORY_ALLOCATION_ERROR;
+             return;
+         }
+@@ -1003,7 +1041,7 @@ void RelativeDateTimeFormatter::init(
+         SharedObject::clearPtr(fOptBreakIterator);
+     } else {
+         SharedBreakIterator *shared = new SharedBreakIterator(bi.getAlias());
+-        if (shared == NULL) {
++        if (shared == nullptr) {
+             status = U_MEMORY_ALLOCATION_ERROR;
+             return;
+         }
+@@ -1026,13 +1064,13 @@ ureldatefmt_open( const char*          locale,
+                   UErrorCode*          status )
+ {
+     if (U_FAILURE(*status)) {
+-        return NULL;
++        return nullptr;
+     }
+     LocalPointer<RelativeDateTimeFormatter> formatter(new RelativeDateTimeFormatter(Locale(locale),
+                                                               (NumberFormat*)nfToAdopt, width,
+                                                               capitalizationContext, *status), *status);
+     if (U_FAILURE(*status)) {
+-        return NULL;
++        return nullptr;
+     }
+     return (URelativeDateTimeFormatter*)formatter.orphan();
+ }
+@@ -1054,13 +1092,13 @@ ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt,
+     if (U_FAILURE(*status)) {
+         return 0;
+     }
+-    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0) {
++    if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0) {
+         *status = U_ILLEGAL_ARGUMENT_ERROR;
+         return 0;
+     }
+     UnicodeString res;
+-    if (result != NULL) {
+-        // NULL destination for pure preflighting: empty dummy string
++    if (result != nullptr) {
++        // nullptr destination for pure preflighting: empty dummy string
+         // otherwise, alias the destination buffer (copied from udat_format)
+         res.setTo(result, 0, resultCapacity);
+     }
+@@ -1082,13 +1120,13 @@ ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt,
+     if (U_FAILURE(*status)) {
+         return 0;
+     }
+-    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0) {
++    if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0) {
+         *status = U_ILLEGAL_ARGUMENT_ERROR;
+         return 0;
+     }
+     UnicodeString res;
+-    if (result != NULL) {
+-        // NULL destination for pure preflighting: empty dummy string
++    if (result != nullptr) {
++        // nullptr destination for pure preflighting: empty dummy string
+         // otherwise, alias the destination buffer (copied from udat_format)
+         res.setTo(result, 0, resultCapacity);
+     }
+@@ -1112,9 +1150,9 @@ ureldatefmt_combineDateAndTime( const URelativeDateTimeFormatter* reldatefmt,
+     if (U_FAILURE(*status)) {
+         return 0;
+     }
+-    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0 ||
+-            (relativeDateString == NULL ? relativeDateStringLen != 0 : relativeDateStringLen < -1) ||
+-            (timeString == NULL ? timeStringLen != 0 : timeStringLen < -1)) {
++    if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0 ||
++            (relativeDateString == nullptr ? relativeDateStringLen != 0 : relativeDateStringLen < -1) ||
++            (timeString == nullptr ? timeStringLen != 0 : timeStringLen < -1)) {
+         *status = U_ILLEGAL_ARGUMENT_ERROR;
+         return 0;
+     }
+diff --git a/icu4c/source/i18n/unicode/reldatefmt.h b/icu4c/source/i18n/unicode/reldatefmt.h
+index 918d43e67a..be06b1013d 100644
+--- a/icu4c/source/i18n/unicode/reldatefmt.h
++++ b/icu4c/source/i18n/unicode/reldatefmt.h
+@@ -165,12 +165,20 @@ typedef enum UDateAbsoluteUnit {
+      */
+     UDAT_ABSOLUTE_NOW,
+ 
++#ifndef U_HIDE_DRAFT_API
++    /**
++     * Quarter
++     * @draft ICU 63
++     */
++    UDAT_ABSOLUTE_QUARTER,
++#endif // U_HIDE_DRAFT_API
++
+ #ifndef U_HIDE_DEPRECATED_API
+     /**
+      * One more than the highest normal UDateAbsoluteUnit value.
+      * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
+      */
+-    UDAT_ABSOLUTE_UNIT_COUNT
++    UDAT_ABSOLUTE_UNIT_COUNT = UDAT_ABSOLUTE_NOW + 2
+ #endif  // U_HIDE_DEPRECATED_API
+ } UDateAbsoluteUnit;
+ 
diff --git a/scripts/trim_data.sh b/scripts/trim_data.sh
index a949755..41e539e 100755
--- a/scripts/trim_data.sh
+++ b/scripts/trim_data.sh
@@ -17,7 +17,7 @@
        /^    AuxExemplarCharacters\{$/, /^    \}$/d
        /^    ExemplarCharacters\{.*\}$/d
        /^    ExemplarCharacters\{$/, /^    \}$/d
-       /^        (mon|tue|wed|thu|fri|sat|sun|quarter)(|-short|-narrow)\{$/, /^        \}$/d' ${langpath}
+       /^        (mon|tue|wed|thu|fri|sat|sun)(|-short|-narrow)\{$/, /^        \}$/d' ${langpath}
   done
 }
 
diff --git a/source/i18n/reldatefmt.cpp b/source/i18n/reldatefmt.cpp
index aad026c..8e2a8d1 100644
--- a/source/i18n/reldatefmt.cpp
+++ b/source/i18n/reldatefmt.cpp
@@ -51,13 +51,13 @@
 // RelativeDateTimeFormatter specific data for a single locale
 class RelativeDateTimeCacheData: public SharedObject {
 public:
-    RelativeDateTimeCacheData() : combinedDateAndTime(NULL) {
+    RelativeDateTimeCacheData() : combinedDateAndTime(nullptr) {
         // Initialize the cache arrays
         for (int32_t style = 0; style < UDAT_STYLE_COUNT; ++style) {
-            for (int32_t relUnit = 0; relUnit < UDAT_RELATIVE_UNIT_COUNT; ++relUnit) {
+            for (int32_t relUnit = 0; relUnit < UDAT_REL_UNIT_COUNT; ++relUnit) {
                 for (int32_t pl = 0; pl < StandardPlural::COUNT; ++pl) {
-                    relativeUnitsFormatters[style][relUnit][0][pl] = NULL;
-                    relativeUnitsFormatters[style][relUnit][1][pl] = NULL;
+                    relativeUnitsFormatters[style][relUnit][0][pl] = nullptr;
+                    relativeUnitsFormatters[style][relUnit][1][pl] = nullptr;
                 }
             }
         }
@@ -74,7 +74,7 @@
     // e.g., Next Tuesday; Yesterday; etc. For third index, 0
     // means past, e.g., 5 days ago; 1 means future, e.g., in 5 days.
     SimpleFormatter *relativeUnitsFormatters[UDAT_STYLE_COUNT]
-        [UDAT_RELATIVE_UNIT_COUNT][2][StandardPlural::COUNT];
+        [UDAT_REL_UNIT_COUNT][2][StandardPlural::COUNT];
 
     const UnicodeString& getAbsoluteUnitString(int32_t fStyle,
                                                UDateAbsoluteUnit unit,
@@ -83,6 +83,10 @@
                                                     UDateRelativeUnit unit,
                                                     int32_t pastFutureIndex,
                                                     int32_t pluralUnit) const;
+    const SimpleFormatter* getRelativeDateTimeUnitFormatter(int32_t fStyle,
+                                                    URelativeDateTimeUnit unit,
+                                                    int32_t pastFutureIndex,
+                                                    int32_t pluralUnit) const;
 
     const UnicodeString emptyString;
 
@@ -107,7 +111,7 @@
 RelativeDateTimeCacheData::~RelativeDateTimeCacheData() {
     // clear out the cache arrays
     for (int32_t style = 0; style < UDAT_STYLE_COUNT; ++style) {
-        for (int32_t relUnit = 0; relUnit < UDAT_RELATIVE_UNIT_COUNT; ++relUnit) {
+        for (int32_t relUnit = 0; relUnit < UDAT_REL_UNIT_COUNT; ++relUnit) {
             for (int32_t pl = 0; pl < StandardPlural::COUNT; ++pl) {
                 delete relativeUnitsFormatters[style][relUnit][0][pl];
                 delete relativeUnitsFormatters[style][relUnit][1][pl];
@@ -131,20 +135,41 @@
     return emptyString;
 }
 
- // Use fallback cache for SimpleFormatter relativeUnits.
  const SimpleFormatter* RelativeDateTimeCacheData::getRelativeUnitFormatter(
         int32_t fStyle,
         UDateRelativeUnit unit,
         int32_t pastFutureIndex,
         int32_t pluralUnit) const {
+   URelativeDateTimeUnit rdtunit = UDAT_REL_UNIT_COUNT;
+   switch (unit) {
+       case UDAT_RELATIVE_YEARS:   rdtunit = UDAT_REL_UNIT_YEAR; break;
+       case UDAT_RELATIVE_MONTHS:  rdtunit = UDAT_REL_UNIT_MONTH; break;
+       case UDAT_RELATIVE_WEEKS:   rdtunit = UDAT_REL_UNIT_WEEK; break;
+       case UDAT_RELATIVE_DAYS:    rdtunit = UDAT_REL_UNIT_DAY; break;
+       case UDAT_RELATIVE_HOURS:   rdtunit = UDAT_REL_UNIT_HOUR; break;
+       case UDAT_RELATIVE_MINUTES: rdtunit = UDAT_REL_UNIT_MINUTE; break;
+       case UDAT_RELATIVE_SECONDS: rdtunit = UDAT_REL_UNIT_SECOND; break;
+       default: // a unit that the above method does not handle
+            return nullptr;
+   }
+
+   return getRelativeDateTimeUnitFormatter(fStyle, rdtunit, pastFutureIndex, pluralUnit);
+ }
+
+ // Use fallback cache for SimpleFormatter relativeUnits.
+ const SimpleFormatter* RelativeDateTimeCacheData::getRelativeDateTimeUnitFormatter(
+        int32_t fStyle,
+        URelativeDateTimeUnit unit,
+        int32_t pastFutureIndex,
+        int32_t pluralUnit) const {
     int32_t style = fStyle;
     do {
-        if (relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit] != NULL) {
+        if (relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit] != nullptr) {
             return relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit];
         }
         style = fallBackCache[style];
     } while (style != -1);
-    return NULL;  // No formatter found.
+    return nullptr;  // No formatter found.
  }
 
 static UBool getStringWithFallback(
@@ -217,23 +242,35 @@
         // Converts the generic units to UDAT_RELATIVE version.
         switch (genUnit) {
             case SECOND:
-                return UDAT_RELATIVE_SECONDS;
+                return UDAT_REL_UNIT_SECOND;
             case MINUTE:
-                return UDAT_RELATIVE_MINUTES;
+                return UDAT_REL_UNIT_MINUTE;
             case HOUR:
-                return UDAT_RELATIVE_HOURS;
+                return UDAT_REL_UNIT_HOUR;
             case DAY:
-                return UDAT_RELATIVE_DAYS;
+                return UDAT_REL_UNIT_DAY;
             case WEEK:
-                return UDAT_RELATIVE_WEEKS;
+                return UDAT_REL_UNIT_WEEK;
             case MONTH:
-                return UDAT_RELATIVE_MONTHS;
-            /*
-             * case QUARTER:
-             * return UDATE_RELATIVE_QUARTERS;
-             */
+                return UDAT_REL_UNIT_MONTH;
+            case QUARTER:
+                return UDAT_REL_UNIT_QUARTER;
             case YEAR:
-                return UDAT_RELATIVE_YEARS;
+                return UDAT_REL_UNIT_YEAR;
+            case SUNDAY:
+                return UDAT_REL_UNIT_SUNDAY;
+            case MONDAY:
+                return UDAT_REL_UNIT_MONDAY;
+            case TUESDAY:
+                return UDAT_REL_UNIT_TUESDAY;
+            case WEDNESDAY:
+                return UDAT_REL_UNIT_WEDNESDAY;
+            case THURSDAY:
+                return UDAT_REL_UNIT_THURSDAY;
+            case FRIDAY:
+                return UDAT_REL_UNIT_FRIDAY;
+            case SATURDAY:
+                return UDAT_REL_UNIT_SATURDAY;
             default:
                 return -1;
         }
@@ -248,10 +285,8 @@
                 return UDAT_ABSOLUTE_WEEK;
             case MONTH:
                 return UDAT_ABSOLUTE_MONTH;
-            /* TODO: Add in QUARTER
-             *  case QUARTER:
-             * return UDAT_ABSOLUTE_QUARTER;
-             */
+            case QUARTER:
+                return UDAT_ABSOLUTE_QUARTER;
             case YEAR:
                 return UDAT_ABSOLUTE_YEAR;
             case SUNDAY:
@@ -430,7 +465,7 @@
                 }
 
                 int32_t relUnitIndex = relUnitFromGeneric(genericUnit);
-                if (relUnitIndex == UDAT_RELATIVE_SECONDS && uprv_strcmp(key, "0") == 0 &&
+                if (relUnitIndex == UDAT_REL_UNIT_SECOND && uprv_strcmp(key, "0") == 0 &&
                     outputData.absoluteUnits[style][UDAT_ABSOLUTE_NOW][UDAT_DIRECTION_PLAIN].isEmpty()) {
                     // Handle "NOW"
                     outputData.absoluteUnits[style][UDAT_ABSOLUTE_NOW]
@@ -463,10 +498,10 @@
                         outputData.relativeUnitsFormatters[style][relUnitIndex]
                         [pastFutureIndex];
                     // Only set if not already established.
-                    if (patterns[pluralIndex] == NULL) {
+                    if (patterns[pluralIndex] == nullptr) {
                         patterns[pluralIndex] = new SimpleFormatter(
                             value.getUnicodeString(errorCode), 0, 1, errorCode);
-                        if (patterns[pluralIndex] == NULL) {
+                        if (patterns[pluralIndex] == nullptr) {
                             errorCode = U_MEMORY_ALLOCATION_ERROR;
                         }
                     }
@@ -619,7 +654,7 @@
             .append("/DateTimePatterns", status);
     LocalUResourceBundlePointer topLevel(
             ures_getByKeyWithFallback(
-                    resource, pathBuffer.data(), NULL, &status));
+                    resource, pathBuffer.data(), nullptr, &status));
     if (U_FAILURE(status)) {
         return FALSE;
     }
@@ -636,68 +671,68 @@
 template<> U_I18N_API
 const RelativeDateTimeCacheData *LocaleCacheKey<RelativeDateTimeCacheData>::createObject(const void * /*unused*/, UErrorCode &status) const {
     const char *localeId = fLoc.getName();
-    LocalUResourceBundlePointer topLevel(ures_open(NULL, localeId, &status));
+    LocalUResourceBundlePointer topLevel(ures_open(nullptr, localeId, &status));
     if (U_FAILURE(status)) {
-        return NULL;
+        return nullptr;
     }
     LocalPointer<RelativeDateTimeCacheData> result(
             new RelativeDateTimeCacheData());
     if (result.isNull()) {
         status = U_MEMORY_ALLOCATION_ERROR;
-        return NULL;
+        return nullptr;
     }
     if (!loadUnitData(
             topLevel.getAlias(),
             *result,
             localeId,
             status)) {
-        return NULL;
+        return nullptr;
     }
     UnicodeString dateTimePattern;
     if (!getDateTimePattern(topLevel.getAlias(), dateTimePattern, status)) {
-        return NULL;
+        return nullptr;
     }
     result->adoptCombinedDateAndTime(
             new SimpleFormatter(dateTimePattern, 2, 2, status));
     if (U_FAILURE(status)) {
-        return NULL;
+        return nullptr;
     }
     result->addRef();
     return result.orphan();
 }
 
 RelativeDateTimeFormatter::RelativeDateTimeFormatter(UErrorCode& status) :
-        fCache(NULL),
-        fNumberFormat(NULL),
-        fPluralRules(NULL),
+        fCache(nullptr),
+        fNumberFormat(nullptr),
+        fPluralRules(nullptr),
         fStyle(UDAT_STYLE_LONG),
         fContext(UDISPCTX_CAPITALIZATION_NONE),
-        fOptBreakIterator(NULL) {
-    init(NULL, NULL, status);
+        fOptBreakIterator(nullptr) {
+    init(nullptr, nullptr, status);
 }
 
 RelativeDateTimeFormatter::RelativeDateTimeFormatter(
         const Locale& locale, UErrorCode& status) :
-        fCache(NULL),
-        fNumberFormat(NULL),
-        fPluralRules(NULL),
+        fCache(nullptr),
+        fNumberFormat(nullptr),
+        fPluralRules(nullptr),
         fStyle(UDAT_STYLE_LONG),
         fContext(UDISPCTX_CAPITALIZATION_NONE),
-        fOptBreakIterator(NULL),
+        fOptBreakIterator(nullptr),
         fLocale(locale) {
-    init(NULL, NULL, status);
+    init(nullptr, nullptr, status);
 }
 
 RelativeDateTimeFormatter::RelativeDateTimeFormatter(
         const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status) :
-        fCache(NULL),
-        fNumberFormat(NULL),
-        fPluralRules(NULL),
+        fCache(nullptr),
+        fNumberFormat(nullptr),
+        fPluralRules(nullptr),
         fStyle(UDAT_STYLE_LONG),
         fContext(UDISPCTX_CAPITALIZATION_NONE),
-        fOptBreakIterator(NULL),
+        fOptBreakIterator(nullptr),
         fLocale(locale) {
-    init(nfToAdopt, NULL, status);
+    init(nfToAdopt, nullptr, status);
 }
 
 RelativeDateTimeFormatter::RelativeDateTimeFormatter(
@@ -706,12 +741,12 @@
         UDateRelativeDateTimeFormatterStyle styl,
         UDisplayContext capitalizationContext,
         UErrorCode& status) :
-        fCache(NULL),
-        fNumberFormat(NULL),
-        fPluralRules(NULL),
+        fCache(nullptr),
+        fNumberFormat(nullptr),
+        fPluralRules(nullptr),
         fStyle(styl),
         fContext(capitalizationContext),
-        fOptBreakIterator(NULL),
+        fOptBreakIterator(nullptr),
         fLocale(locale) {
     if (U_FAILURE(status)) {
         return;
@@ -727,7 +762,7 @@
         }
         init(nfToAdopt, bi, status);
     } else {
-        init(nfToAdopt, NULL, status);
+        init(nfToAdopt, nullptr, status);
     }
 }
 
@@ -744,7 +779,7 @@
     fCache->addRef();
     fNumberFormat->addRef();
     fPluralRules->addRef();
-    if (fOptBreakIterator != NULL) {
+    if (fOptBreakIterator != nullptr) {
       fOptBreakIterator->addRef();
     }
 }
@@ -764,16 +799,16 @@
 }
 
 RelativeDateTimeFormatter::~RelativeDateTimeFormatter() {
-    if (fCache != NULL) {
+    if (fCache != nullptr) {
         fCache->removeRef();
     }
-    if (fNumberFormat != NULL) {
+    if (fNumberFormat != nullptr) {
         fNumberFormat->removeRef();
     }
-    if (fPluralRules != NULL) {
+    if (fPluralRules != nullptr) {
         fPluralRules->removeRef();
     }
-    if (fOptBreakIterator != NULL) {
+    if (fOptBreakIterator != nullptr) {
         fOptBreakIterator->removeRef();
     }
 }
@@ -812,7 +847,7 @@
 
     const SimpleFormatter* formatter =
         fCache->getRelativeUnitFormatter(fStyle, unit, bFuture, pluralIndex);
-    if (formatter == NULL) {
+    if (formatter == nullptr) {
         // TODO: WARN - look at quantity formatter's action with an error.
         status = U_INVALID_FORMAT_ERROR;
         return appendTo;
@@ -828,33 +863,35 @@
     if (U_FAILURE(status)) {
         return appendTo;
     }
-    // TODO:
-    // The full implementation of this depends on CLDR data that is not yet available,
-    // see: http://unicode.org/cldr/trac/ticket/9165 Add more relative field data.
-    // In the meantime do a quick bring-up by calling the old format method; this
-    // leaves some holes (even for data that is currently available, such as quarter).
-    // When the new CLDR data is available, update the data storage accordingly,
-    // rewrite this to use it directly, and rewrite the old format method to call this
-    // new one; that is covered by http://bugs.icu-project.org/trac/ticket/12171.
-    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_UNSUPPORTED_ERROR;
-            return appendTo;
-    }
     UDateDirection direction = UDAT_DIRECTION_NEXT;
     if (std::signbit(offset)) { // needed to handle -0.0
         direction = UDAT_DIRECTION_LAST;
         offset = -offset;
     }
-    return format(offset, direction, relunit, appendTo, status);
+    if (direction != UDAT_DIRECTION_LAST && direction != UDAT_DIRECTION_NEXT) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return appendTo;
+    }
+    int32_t bFuture = direction == UDAT_DIRECTION_NEXT ? 1 : 0;
+    FieldPosition pos(FieldPosition::DONT_CARE);
+
+    UnicodeString result;
+    UnicodeString formattedNumber;
+
+    StandardPlural::Form pluralIndex = QuantityFormatter::selectPlural(
+        offset, **fNumberFormat, **fPluralRules, formattedNumber, pos,
+        status);
+
+    const SimpleFormatter* formatter =
+        fCache->getRelativeDateTimeUnitFormatter(fStyle, unit, bFuture, pluralIndex);
+    if (formatter == nullptr) {
+        // TODO: WARN - look at quantity formatter's action with an error.
+        status = U_INVALID_FORMAT_ERROR;
+        return appendTo;
+    }
+    formatter->format(formattedNumber, result, status);
+    adjustForContext(result);
+    return appendTo.append(result);
 }
 
 UnicodeString& RelativeDateTimeFormatter::format(
@@ -871,7 +908,7 @@
     // Get string using fallback.
     UnicodeString result;
     result.fastCopyFrom(fCache->getAbsoluteUnitString(fStyle, unit, direction));
-    if (fOptBreakIterator != NULL) {
+    if (fOptBreakIterator != nullptr) {
         adjustForContext(result);
     }
     return appendTo.append(result);
@@ -908,6 +945,7 @@
     UDateAbsoluteUnit absunit = UDAT_ABSOLUTE_UNIT_COUNT;
     switch (unit) {
         case UDAT_REL_UNIT_YEAR:    absunit = UDAT_ABSOLUTE_YEAR; break;
+        case UDAT_REL_UNIT_QUARTER: absunit = UDAT_ABSOLUTE_QUARTER; 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;
@@ -930,7 +968,7 @@
         const UnicodeString &unitFormatString =
             fCache->getAbsoluteUnitString(fStyle, absunit, direction);
         if (!unitFormatString.isEmpty()) {
-            if (fOptBreakIterator != NULL) {
+            if (fOptBreakIterator != nullptr) {
                 UnicodeString result(unitFormatString);
                 adjustForContext(result);
                 return appendTo.append(result);
@@ -951,7 +989,7 @@
 }
 
 void RelativeDateTimeFormatter::adjustForContext(UnicodeString &str) const {
-    if (fOptBreakIterator == NULL
+    if (fOptBreakIterator == nullptr
         || str.length() == 0 || !u_islower(str.char32At(0))) {
         return;
     }
@@ -992,7 +1030,7 @@
         shared->removeRef();
     } else {
         SharedNumberFormat *shared = new SharedNumberFormat(nf.getAlias());
-        if (shared == NULL) {
+        if (shared == nullptr) {
             status = U_MEMORY_ALLOCATION_ERROR;
             return;
         }
@@ -1003,7 +1041,7 @@
         SharedObject::clearPtr(fOptBreakIterator);
     } else {
         SharedBreakIterator *shared = new SharedBreakIterator(bi.getAlias());
-        if (shared == NULL) {
+        if (shared == nullptr) {
             status = U_MEMORY_ALLOCATION_ERROR;
             return;
         }
@@ -1026,13 +1064,13 @@
                   UErrorCode*          status )
 {
     if (U_FAILURE(*status)) {
-        return NULL;
+        return nullptr;
     }
     LocalPointer<RelativeDateTimeFormatter> formatter(new RelativeDateTimeFormatter(Locale(locale),
                                                               (NumberFormat*)nfToAdopt, width,
                                                               capitalizationContext, *status), *status);
     if (U_FAILURE(*status)) {
-        return NULL;
+        return nullptr;
     }
     return (URelativeDateTimeFormatter*)formatter.orphan();
 }
@@ -1054,13 +1092,13 @@
     if (U_FAILURE(*status)) {
         return 0;
     }
-    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0) {
+    if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0) {
         *status = U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
     }
     UnicodeString res;
-    if (result != NULL) {
-        // NULL destination for pure preflighting: empty dummy string
+    if (result != nullptr) {
+        // nullptr destination for pure preflighting: empty dummy string
         // otherwise, alias the destination buffer (copied from udat_format)
         res.setTo(result, 0, resultCapacity);
     }
@@ -1082,13 +1120,13 @@
     if (U_FAILURE(*status)) {
         return 0;
     }
-    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0) {
+    if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0) {
         *status = U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
     }
     UnicodeString res;
-    if (result != NULL) {
-        // NULL destination for pure preflighting: empty dummy string
+    if (result != nullptr) {
+        // nullptr destination for pure preflighting: empty dummy string
         // otherwise, alias the destination buffer (copied from udat_format)
         res.setTo(result, 0, resultCapacity);
     }
@@ -1112,9 +1150,9 @@
     if (U_FAILURE(*status)) {
         return 0;
     }
-    if (result == NULL ? resultCapacity != 0 : resultCapacity < 0 ||
-            (relativeDateString == NULL ? relativeDateStringLen != 0 : relativeDateStringLen < -1) ||
-            (timeString == NULL ? timeStringLen != 0 : timeStringLen < -1)) {
+    if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0 ||
+            (relativeDateString == nullptr ? relativeDateStringLen != 0 : relativeDateStringLen < -1) ||
+            (timeString == nullptr ? timeStringLen != 0 : timeStringLen < -1)) {
         *status = U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
     }
diff --git a/source/i18n/unicode/reldatefmt.h b/source/i18n/unicode/reldatefmt.h
index 09d9620..987fddd 100644
--- a/source/i18n/unicode/reldatefmt.h
+++ b/source/i18n/unicode/reldatefmt.h
@@ -165,12 +165,20 @@
      */
     UDAT_ABSOLUTE_NOW,
 
+#ifndef U_HIDE_DRAFT_API
+    /**
+     * Quarter
+     * @draft ICU 63
+     */
+    UDAT_ABSOLUTE_QUARTER,
+#endif // U_HIDE_DRAFT_API
+
 #ifndef U_HIDE_DEPRECATED_API
     /**
      * One more than the highest normal UDateAbsoluteUnit value.
      * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
      */
-    UDAT_ABSOLUTE_UNIT_COUNT
+    UDAT_ABSOLUTE_UNIT_COUNT = UDAT_ABSOLUTE_NOW + 2
 #endif  // U_HIDE_DEPRECATED_API
 } UDateAbsoluteUnit;