ICU-10858 Fix missing fTimeZoneFormat assignment in SimpleDateFormat::operator= (#963)
diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp
index 6246e8f..d704642 100644
--- a/icu4c/source/i18n/smpdtfmt.cpp
+++ b/icu4c/source/i18n/smpdtfmt.cpp
@@ -583,11 +583,14 @@
fHasMinute = other.fHasMinute;
fHasSecond = other.fHasSecond;
- // TimeZoneFormat in ICU4C only depends on a locale for now
- if (fLocale != other.fLocale) {
- delete fTimeZoneFormat;
- fTimeZoneFormat = NULL; // forces lazy instantiation with the other locale
- fLocale = other.fLocale;
+ fLocale = other.fLocale;
+
+ // TimeZoneFormat can now be set independently via setter.
+ // If it is NULL, it will be lazily initialized from locale
+ delete fTimeZoneFormat;
+ fTimeZoneFormat = NULL;
+ if (other.fTimeZoneFormat) {
+ fTimeZoneFormat = new TimeZoneFormat(*other.fTimeZoneFormat);
}
#if !UCONFIG_NO_BREAK_ITERATION
diff --git a/icu4c/source/test/intltest/dtfmrgts.cpp b/icu4c/source/test/intltest/dtfmrgts.cpp
index 7b772f1..b72f0df 100644
--- a/icu4c/source/test/intltest/dtfmrgts.cpp
+++ b/icu4c/source/test/intltest/dtfmrgts.cpp
@@ -63,8 +63,9 @@
CASE(30,TestT10334)
CASE(31,TestT10619)
CASE(32,TestT10855)
- CASE(33,TestT10906)
- CASE(34,TestT13380)
+ CASE(33,TestT10858)
+ CASE(34,TestT10906)
+ CASE(35,TestT13380)
default: name = ""; break;
}
}
@@ -1762,6 +1763,45 @@
}
}
+void DateFormatRegressionTest::TestT10858(void) {
+ // test for assignment operator on instances with the same locale but different TimeZoneFormat
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString pattern("VVVV");
+ Locale loc("en_US");
+
+ // Make two identical Formats
+ SimpleDateFormat fmt_rhs(pattern, loc, status);
+ SimpleDateFormat fmt_lhs(pattern, loc, status);
+
+ // Setup a custom TimeZoneFormat
+ TimeZoneFormat* tzFmt = TimeZoneFormat::createInstance(Locale("de_DE"), status);
+ tzFmt->setGMTPattern(UnicodeString("UTC{0}"), status);
+ tzFmt->setGMTZeroFormat(UnicodeString("UTC"), status);
+
+ // Set custom TimeZoneFormat in fmt1 before assignment. Use
+ // adoptTimeZoneFormat instead of setTimeZoneFormat to delegate
+ // cleanup of tzFmt to SimpleDateFormat
+ fmt_rhs.adoptTimeZoneFormat(tzFmt);
+
+ // Make sure TimeZoneFormat is DIFFERENT between fmt_lhs & fmt_rhs at this point.
+ // Direct comparison with TimeZoneFormat::operator== does not suffice as it only
+ // checks for 'semantically equal' rather than 'identical' -- compare results of
+ // SimpleDateFormat::format() instead
+ UnicodeString res_rhs; fmt_rhs.format(0.0, res_rhs);
+ UnicodeString res_lhs_pre_assign; fmt_lhs.format(0.0, res_lhs_pre_assign);
+ if (res_lhs_pre_assign == res_rhs) {
+ errln(UnicodeString("Error: adoptTimeZoneFormat failed to set custom TimeZoneFormat into 'fmt_rhs'"));
+ }
+
+ // Invoke assignment operator and make sure formatted outputs from both objects are
+ // now identical (i.e. TimeZoneFormat, among other members, is correctly copied to LHS)
+ fmt_lhs = fmt_rhs;
+ UnicodeString res_lhs_post_assign; fmt_lhs.format(0.0, res_lhs_post_assign);
+ if (res_lhs_post_assign != res_rhs) {
+ errln(UnicodeString("Error: assigned instance did not take up TimeZoneFormat from original"));
+ }
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
//eof
diff --git a/icu4c/source/test/intltest/dtfmrgts.h b/icu4c/source/test/intltest/dtfmrgts.h
index 305487d..ecad431 100644
--- a/icu4c/source/test/intltest/dtfmrgts.h
+++ b/icu4c/source/test/intltest/dtfmrgts.h
@@ -59,6 +59,7 @@
void TestT10334(void);
void TestT10619(void);
void TestT10855(void);
+ void TestT10858(void);
void TestT10906(void);
void TestT13380(void);
};