Skip to content

Commit

Permalink
ICU-22994 Remove misuage of Calendar::getType
Browse files Browse the repository at this point in the history
Use getDynamicClassID and getStaticClassID for calendar type comparision
instead of strcmp.
Hide some Hebrew adjustment by using rencently added Calendar API.
  • Loading branch information
FrankYFTang committed Dec 18, 2024
1 parent 81d0475 commit 2fb4782
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 28 deletions.
8 changes: 2 additions & 6 deletions icu4c/source/i18n/datefmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,7 @@ UnicodeString&
DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const {
if (fCalendar != nullptr) {
UErrorCode ec = U_ZERO_ERROR;
const auto* calType = fCalendar->getType();
// Avoid a heap allocation and corresponding free for the common case
if (uprv_strcmp(calType, "gregorian") == 0) {
if (GregorianCalendar::getStaticClassID() == fCalendar->getDynamicClassID()) {
GregorianCalendar cal(*static_cast<GregorianCalendar*>(fCalendar));
cal.setTime(date, ec);
if (U_SUCCESS(ec)) {
Expand Down Expand Up @@ -309,9 +307,7 @@ DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator* p
UErrorCode& status) const {
if (fCalendar != nullptr) {
UErrorCode ec = U_ZERO_ERROR;
const auto* calType = fCalendar->getType();
// Avoid a heap allocation and corresponding free for the common case
if (uprv_strcmp(calType, "gregorian") == 0) {
if (GregorianCalendar::getStaticClassID() == fCalendar->getDynamicClassID()) {
GregorianCalendar cal(*static_cast<GregorianCalendar*>(fCalendar));
cal.setTime(date, ec);
if (U_SUCCESS(ec)) {
Expand Down
41 changes: 21 additions & 20 deletions icu4c/source/i18n/smpdtfmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@
#include "dayperiodrules.h"
#include "tznames_impl.h" // ZONE_NAME_U16_MAX
#include "number_utypes.h"
#include "chnsecal.h"
#include "dangical.h"
#include "japancal.h"

#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
#include <stdio.h>
Expand Down Expand Up @@ -945,7 +948,7 @@ SimpleDateFormat::initialize(const Locale& locale,
// if format is non-numeric (includes 年) and fDateOverride is not already specified.
// Now this does get updated if applyPattern subsequently changes the pattern type.
if (fDateOverride.isBogus() && fHasHanYearChar &&
fCalendar != nullptr && uprv_strcmp(fCalendar->getType(),"japanese") == 0 &&
fCalendar != nullptr && fCalendar->getDynamicClassID() == JapaneseCalendar::getStaticClassID() &&
uprv_strcmp(fLocale.getLanguage(),"ja") == 0) {
fDateOverride.setTo(u"y=jpanyear", -1);
}
Expand Down Expand Up @@ -1050,7 +1053,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
}
Calendar* workCal = &cal;
Calendar* calClone = nullptr;
if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
if (&cal != fCalendar && cal.getDynamicClassID() != fCalendar->getDynamicClassID()) {
// Different calendar type
// We use the time and time zone from the input calendar, but
// do not use the input calendar for field calculation.
Expand Down Expand Up @@ -1523,8 +1526,9 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
// "GGGG" is wide era name, "GGGGG" is narrow era name, anything else is abbreviated name
case UDAT_ERA_FIELD:
{
const auto* calType = cal.getType();
if (uprv_strcmp(calType,"chinese") == 0 || uprv_strcmp(calType,"dangi") == 0) {
bool zeroPadEra = cal.getDynamicClassID() == ChineseCalendar::getStaticClassID() ||
cal.getDynamicClassID() == DangiCalendar::getStaticClassID();
if (zeroPadEra) {
zeroPaddingNumber(currentNumberFormat,appendTo, value, 1, 9); // as in ICU4J
} else {
if (count == 5) {
Expand Down Expand Up @@ -1575,10 +1579,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
// for "MMMMM"/"LLLLL", use the narrow form
case UDAT_MONTH_FIELD:
case UDAT_STANDALONE_MONTH_FIELD:
if (uprv_strcmp(cal.getType(),"hebrew") == 0) {
if (HebrewCalendar::isLeapYear(cal.get(UCAL_YEAR,status)) && value == 6 && count >= 3 )
if (cal.getDynamicClassID() == HebrewCalendar::getStaticClassID()) {
bool inLeapYear = cal.inTemporalLeapYear(status);
if (inLeapYear && value == 6 && count >= 3 )
value = 13; // Show alternate form for Adar II in leap years in Hebrew calendar.
if (!HebrewCalendar::isLeapYear(cal.get(UCAL_YEAR,status)) && value >= 6 && count < 3 )
if (!inLeapYear && value >= 6 && count < 3 )
value--; // Adjust the month number down 1 in Hebrew non-leap years, i.e. Adar is 6, not 7.
}
{
Expand Down Expand Up @@ -2272,7 +2277,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&

Calendar* calClone = nullptr;
Calendar *workCal = &cal;
if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
if (&cal != fCalendar && cal.getDynamicClassID() != fCalendar->getDynamicClassID()) {
// Different calendar type
// We use the time/zone from the input calendar, but
// do not use the input calendar for field calculation.
Expand Down Expand Up @@ -2903,7 +2908,7 @@ int32_t SimpleDateFormat::matchAlphaMonthStrings(const UnicodeString& text,

if (bestMatch >= 0) {
// Adjustment for Hebrew Calendar month Adar II
if (!strcmp(cal.getType(),"hebrew") && bestMatch==13) {
if (cal.getDynamicClassID() == HebrewCalendar::getStaticClassID() && bestMatch==13) {
cal.set(UCAL_MONTH,6);
} else {
cal.set(UCAL_MONTH, bestMatch);
Expand Down Expand Up @@ -2963,7 +2968,7 @@ int32_t SimpleDateFormat::matchString(const UnicodeString& text,
if (bestMatch >= 0) {
if (field < UCAL_FIELD_COUNT) {
// Adjustment for Hebrew Calendar month Adar II
if (!strcmp(cal.getType(),"hebrew") && field==UCAL_MONTH && bestMatch==13) {
if (cal.getDynamicClassID() == HebrewCalendar::getStaticClassID() && field==UCAL_MONTH && bestMatch==13) {
cal.set(field,6);
} else {
if (field == UCAL_YEAR) {
Expand Down Expand Up @@ -3052,7 +3057,6 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch
if (numericLeapMonthFormatter != nullptr) {
numericLeapMonthFormatter->setFormats(reinterpret_cast<const Format**>(&currentNumberFormat), 1);
}
UBool isChineseCalendar = (uprv_strcmp(cal.getType(),"chinese") == 0 || uprv_strcmp(cal.getType(),"dangi") == 0);

// If there are any spaces here, skip over them. If we hit the end
// of the string, then fail.
Expand All @@ -3068,6 +3072,8 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch
}
pos.setIndex(start);

UBool isChineseCalendar = cal.getDynamicClassID() == ChineseCalendar::getStaticClassID() ||
cal.getDynamicClassID() == DangiCalendar::getStaticClassID();
// We handle a few special cases here where we need to parse
// a number value. We handle further, more generic cases below. We need
// to handle some of them here because some fields require extra processing on
Expand Down Expand Up @@ -3242,12 +3248,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch

// Delayed checking for adjustment of Hebrew month numbers in non-leap years.
if (saveHebrewMonth >= 0) {
HebrewCalendar *hc = (HebrewCalendar*)&cal;
if (!hc->isLeapYear(value) && saveHebrewMonth >= 6) {
cal.set(UCAL_MONTH,saveHebrewMonth);
} else {
cal.set(UCAL_MONTH,saveHebrewMonth-1);
}
cal.set(UCAL_ORDINAL_MONTH, saveHebrewMonth);
saveHebrewMonth = -1;
}
return pos.getIndex();
Expand Down Expand Up @@ -3289,7 +3290,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch
// When parsing month numbers from the Hebrew Calendar, we might need to adjust the month depending on whether
// or not it was a leap year. We may or may not yet know what year it is, so might have to delay checking until
// the year is parsed.
if (!strcmp(cal.getType(),"hebrew")) {
if (cal.getDynamicClassID() == HebrewCalendar::getStaticClassID()) {
HebrewCalendar *hc = (HebrewCalendar*)&cal;
if (cal.isSet(UCAL_YEAR)) {
UErrorCode monthStatus = U_ZERO_ERROR;
Expand Down Expand Up @@ -3852,7 +3853,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch
switch (patternCharIndex) {
case UDAT_MONTH_FIELD:
// See notes under UDAT_MONTH_FIELD case above
if (!strcmp(cal.getType(),"hebrew")) {
if (cal.getDynamicClassID() == HebrewCalendar::getStaticClassID()) {
HebrewCalendar *hc = (HebrewCalendar*)&cal;
if (cal.isSet(UCAL_YEAR)) {
UErrorCode monthStatus = U_ZERO_ERROR;
Expand Down Expand Up @@ -4034,7 +4035,7 @@ SimpleDateFormat::applyPattern(const UnicodeString& pattern)

// Hack to update use of Gannen year numbering for ja@calendar=japanese -
// use only if format is non-numeric (includes 年) and no other fDateOverride.
if (fCalendar != nullptr && uprv_strcmp(fCalendar->getType(),"japanese") == 0 &&
if (fCalendar != nullptr && fCalendar->getDynamicClassID() == JapaneseCalendar::getStaticClassID() &&
uprv_strcmp(fLocale.getLanguage(),"ja") == 0) {
if (fDateOverride==UnicodeString(u"y=jpanyear") && !fHasHanYearChar) {
// Gannen numbering is set but new pattern should not use it, unset;
Expand Down
4 changes: 2 additions & 2 deletions icu4c/source/i18n/windtfmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ UnicodeString &Win32DateFormat::format(Calendar &cal, UnicodeString &appendTo, F
formatDate(&st_local, date);
formatTime(&st_local, time);

if (strcmp(fCalendar->getType(), cal.getType()) != 0) {
if (fCalendar->getDynamicClassID() != fcal.getDynamicClassID()) {
pattern = getTimeDateFormat(&cal, &fLocale, status);
}

Expand All @@ -272,7 +272,7 @@ void Win32DateFormat::parse(const UnicodeString& /* text */, Calendar& /* cal */

void Win32DateFormat::adoptCalendar(Calendar *newCalendar)
{
if (fCalendar == nullptr || strcmp(fCalendar->getType(), newCalendar->getType()) != 0) {
if (fCalendar == nullptr || fCalendar->getDynamicClassID() != newCalendar->getDynamicClassID()) {
UErrorCode status = U_ZERO_ERROR;

if (fDateStyle != DateFormat::kNone && fTimeStyle != DateFormat::kNone) {
Expand Down

0 comments on commit 2fb4782

Please sign in to comment.