Skip to content

Commit

Permalink
ICU-22743 Change internal functions to propagate errors up.
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankYFTang committed Apr 18, 2024
1 parent 5e35ffc commit 0c02f8c
Show file tree
Hide file tree
Showing 11 changed files with 372 additions and 183 deletions.
7 changes: 5 additions & 2 deletions icu4c/source/i18n/calendar.cpp
Expand Up @@ -3446,7 +3446,10 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
if(isSet(UCAL_DAY_OF_MONTH)) {
dayOfMonth = internalGet(UCAL_DAY_OF_MONTH,1);
} else {
dayOfMonth = getDefaultDayInMonth(year, month);
dayOfMonth = getDefaultDayInMonth(year, month, status);
if (U_FAILURE(status)) {
return 0;
}
}
if (uprv_add32_overflow(dayOfMonth, julianDay, &dayOfMonth)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
Expand Down Expand Up @@ -3654,7 +3657,7 @@ Calendar::getDefaultMonthInYear(int32_t /*eyear*/, UErrorCode& /* status */)
}

int32_t
Calendar::getDefaultDayInMonth(int32_t /*eyear*/, int32_t /*month*/)
Calendar::getDefaultDayInMonth(int32_t /*eyear*/, int32_t /*month*/, UErrorCode& /* status */)
{
return 1;
}
Expand Down
251 changes: 187 additions & 64 deletions icu4c/source/i18n/chnsecal.cpp

Large diffs are not rendered by default.

103 changes: 68 additions & 35 deletions icu4c/source/i18n/hebrwcal.cpp
Expand Up @@ -304,6 +304,12 @@ void HebrewCalendar::add(EDateFields field, int32_t amount, UErrorCode& status)
add((UCalendarDateFields)field, amount, status);
}

namespace {

int32_t monthsInYear(int32_t year);

} // namespace

/**
* Rolls (up/down) a specified amount time on the given field. For
* example, to roll the current date up by three days, you can call
Expand Down Expand Up @@ -396,6 +402,8 @@ static const int32_t MONTH_PARTS = MONTH_DAYS*DAY_PARTS + MONTH_FRACT;
// Bet (Monday), Hey (5 hours from sunset), Resh-Daled (204).
static const int32_t BAHARAD = 11*HOUR_PARTS + 204;

namespace {

/**
* Finds the day # of the first day in the given Hebrew year.
* To do this, we want to calculate the time of the Tishri 1 new moon
Expand All @@ -416,7 +424,7 @@ static const int32_t BAHARAD = 11*HOUR_PARTS + 204;
* http:https://www.faqs.org/faqs/calendars/faq/</a>
* </ul>
*/
int32_t HebrewCalendar::startOfYear(int32_t year, UErrorCode &status)
int32_t startOfYear(int32_t year, UErrorCode &status)
{
ucln_i18n_registerCleanup(UCLN_I18N_HEBREW_CALENDAR, calendar_hebrew_cleanup);
int64_t day = CalendarCache::get(&gCache, year, status);
Expand All @@ -440,13 +448,13 @@ int32_t HebrewCalendar::startOfYear(int32_t year, UErrorCode &status)
day += 1;
wd = (day % 7);
}
if (wd == 1 && frac > 15*HOUR_PARTS+204 && !isLeapYear(year) ) {
if (wd == 1 && frac > 15*HOUR_PARTS+204 && !HebrewCalendar::isLeapYear(year) ) {
// If the new moon falls after 3:11:20am (15h204p from the previous noon)
// on a Tuesday and it is not a leap year, postpone by 2 days.
// This prevents 356-day years.
day += 2;
}
else if (wd == 0 && frac > 21*HOUR_PARTS+589 && isLeapYear(year-1) ) {
else if (wd == 0 && frac > 21*HOUR_PARTS+589 && HebrewCalendar::isLeapYear(year-1) ) {
// If the new moon falls after 9:32:43 1/3am (21h589p from yesterday noon)
// on a Monday and *last* year was a leap year, postpone by 1 day.
// Prevents 382-day years.
Expand All @@ -463,16 +471,11 @@ int32_t HebrewCalendar::startOfYear(int32_t year, UErrorCode &status)
return day;
}

/**
* Find the day of the week for a given day
*
* @param day The # of days since the start of the Hebrew calendar,
* 1-based (i.e. 1/1/1 AM is day 1).
*/
int32_t HebrewCalendar::absoluteDayToDayOfWeek(int32_t day)
{
// We know that 1/1/1 AM is a Monday, which makes the math easy...
return (day % 7) + 1;
int32_t daysInYear(int32_t eyear, UErrorCode& status) {
if (U_FAILURE(status)) {
return 0;
}
return startOfYear(eyear+1, status) - startOfYear(eyear, status);
}

/**
Expand All @@ -481,9 +484,15 @@ int32_t HebrewCalendar::absoluteDayToDayOfWeek(int32_t day)
* 1 "Normal" year with 354 or 384 days
* 2 "Complete" year with 355 or 385 days
*/
int32_t HebrewCalendar::yearType(int32_t year) const
int32_t yearType(int32_t year, UErrorCode& status)
{
int32_t yearLength = handleGetYearLength(year);
if (U_FAILURE(status)) {
return 0;
}
int32_t yearLength = daysInYear(year, status);
if (U_FAILURE(status)) {
return 0;
}

if (yearLength > 380) {
yearLength -= 30; // Subtract length of leap month.
Expand All @@ -505,6 +514,8 @@ int32_t HebrewCalendar::yearType(int32_t year) const
return type;
}

} // namespace
//
/**
* Determine whether a given Hebrew year is a leap year
*
Expand All @@ -517,10 +528,14 @@ UBool HebrewCalendar::isLeapYear(int32_t year) {
return x >= ((x < 0) ? -7 : 12);
}

int32_t HebrewCalendar::monthsInYear(int32_t year) {
return isLeapYear(year) ? 13 : 12;
namespace{

int32_t monthsInYear(int32_t year) {
return HebrewCalendar::isLeapYear(year) ? 13 : 12;
}

} // namespace

//-------------------------------------------------------------------------
// Calendar framework
//-------------------------------------------------------------------------
Expand Down Expand Up @@ -557,8 +572,14 @@ int32_t HebrewCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month
switch (month) {
case HESHVAN:
case KISLEV:
// These two month lengths can vary
return MONTH_LENGTH[month][yearType(extendedYear)];
{
// These two month lengths can vary
int32_t type = yearType(extendedYear, status);
if(U_FAILURE(status)) {
return 0;
}
return MONTH_LENGTH[month][type];
}

default:
// The rest are a fixed length
Expand All @@ -572,7 +593,11 @@ int32_t HebrewCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month
*/
int32_t HebrewCalendar::handleGetYearLength(int32_t eyear) const {
UErrorCode status = U_ZERO_ERROR;
return startOfYear(eyear+1, status) - startOfYear(eyear, status);
int32_t len = daysInYear(eyear, status);
if (U_FAILURE(status)) {
return 12;
}
return len;
}

void HebrewCalendar::validateField(UCalendarDateFields field, UErrorCode &status) {
Expand Down Expand Up @@ -635,12 +660,16 @@ void HebrewCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status)
}

// Now figure out which month we're in, and the date within that month
int32_t type = yearType(year);
int32_t type = yearType(year, status);
if (U_FAILURE(status)) {
return;
}
UBool isLeap = isLeapYear(year);

int32_t month = 0;
int32_t momax = UPRV_LENGTHOF(MONTH_START);
while (month < momax && dayOfYear > ( isLeap ? LEAP_MONTH_START[month][type] : MONTH_START[month][type] ) ) {
while (month < momax &&
dayOfYear > ( isLeap ? LEAP_MONTH_START[month][type] : MONTH_START[month][type] ) ) {
month++;
}
if (month >= momax || month<=0) {
Expand All @@ -663,25 +692,25 @@ void HebrewCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status)
// Check out of bound year
int32_t min_year = handleGetLimit(UCAL_EXTENDED_YEAR, UCAL_LIMIT_MINIMUM);
if (year < min_year) {
if (!isLenient()) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
year = min_year;
if (!isLenient()) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
year = min_year;
}
int32_t max_year = handleGetLimit(UCAL_EXTENDED_YEAR, UCAL_LIMIT_MAXIMUM);
if (max_year < year) {
if (!isLenient()) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
year = max_year;
if (!isLenient()) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
year = max_year;
}
internalSet(UCAL_YEAR, year);
internalSet(UCAL_EXTENDED_YEAR, year);
int32_t ordinal_month = month;
if (!isLeap && ordinal_month > ADAR_1) {
ordinal_month--;
ordinal_month--;
}
internalSet(UCAL_ORDINAL_MONTH, ordinal_month);
internalSet(UCAL_MONTH, month);
Expand Down Expand Up @@ -754,10 +783,14 @@ int64_t HebrewCalendar::handleComputeMonthStart(
}

if (month != 0) {
int32_t type = yearType(eyear, status);
if (U_FAILURE(status)) {
return 0;
}
if (isLeapYear(eyear)) {
day += LEAP_MONTH_START[month][yearType(eyear)];
day += LEAP_MONTH_START[month][type];
} else {
day += MONTH_START[month][yearType(eyear)];
day += MONTH_START[month][type];
}
}

Expand Down
39 changes: 1 addition & 38 deletions icu4c/source/i18n/hebrwcal.h
Expand Up @@ -329,6 +329,7 @@ class U_I18N_API HebrewCalendar : public Calendar {
* @stable ICU 2.0
*/
virtual int32_t handleGetYearLength(int32_t eyear) const override;

/**
* Subclasses may override this method to compute several fields
* specific to each calendar system. These are:
Expand Down Expand Up @@ -427,44 +428,6 @@ class U_I18N_API HebrewCalendar : public Calendar {

protected:
virtual int32_t internalGetMonth(UErrorCode& status) const override;

private: // Calendar-specific implementation
/**
* Finds the day # of the first day in the given Hebrew year.
* To do this, we want to calculate the time of the Tishri 1 new moon
* in that year.
* <p>
* The algorithm here is similar to ones described in a number of
* references, including:
* <ul>
* <li>"Calendrical Calculations", by Nachum Dershowitz & Edward Reingold,
* Cambridge University Press, 1997, pages 85-91.
*
* <li>Hebrew Calendar Science and Myths,
* <a href="http:https://www.geocities.com/Athens/1584/">
* http:https://www.geocities.com/Athens/1584/</a>
*
* <li>The Calendar FAQ,
* <a href="http:https://www.faqs.org/faqs/calendars/faq/">
* http:https://www.faqs.org/faqs/calendars/faq/</a>
* </ul>
* @param year extended year
* @return day number (JD)
* @internal
*/
static int32_t startOfYear(int32_t year, UErrorCode& status);

static int32_t absoluteDayToDayOfWeek(int32_t day) ;

/**
* @internal
*/
int32_t yearType(int32_t year) const;

/**
* @internal
*/
static int32_t monthsInYear(int32_t year) ;
};

U_NAMESPACE_END
Expand Down

0 comments on commit 0c02f8c

Please sign in to comment.