mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-05 05:25:34 +00:00
parent
cdf52396dc
commit
255eb4ef3e
6 changed files with 217 additions and 7 deletions
|
@ -446,8 +446,7 @@ int32_t startOfYear(int32_t year, UErrorCode &status)
|
|||
// If the 1st is on Sun, Wed, or Fri, postpone to the next day
|
||||
day += 1;
|
||||
wd = (day % 7);
|
||||
}
|
||||
if (wd == 1 && frac > 15*HOUR_PARTS+204 && !HebrewCalendar::isLeapYear(year) ) {
|
||||
} else 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.
|
||||
|
|
|
@ -40,7 +40,7 @@ U_NAMESPACE_BEGIN
|
|||
* solar year (approximately 365.24 days) is not an even multiple of
|
||||
* the lunar month (approximately 29.53 days) an extra "leap month" is
|
||||
* inserted in 7 out of every 19 years. To make matters even more
|
||||
* interesting, the start of a year can be delayed by up to three days
|
||||
* interesting, the start of a year can be delayed by up to two days
|
||||
* in order to prevent certain holidays from falling on the Sabbath and
|
||||
* to prevent certain illegal year lengths. Finally, the lengths of certain
|
||||
* months can vary depending on the number of days in the year.
|
||||
|
|
|
@ -208,6 +208,7 @@ void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
|
|||
TESTCASE_AUTO(Test22633RollTwiceGetTimeOverflow);
|
||||
|
||||
TESTCASE_AUTO(Test22633HebrewLargeNegativeDay);
|
||||
TESTCASE_AUTO(Test23069HebrewHanukkah);
|
||||
TESTCASE_AUTO(Test22730JapaneseOverflow);
|
||||
TESTCASE_AUTO(Test22730CopticOverflow);
|
||||
TESTCASE_AUTO(Test22962ComputeJulianDayOverflow);
|
||||
|
@ -5928,6 +5929,116 @@ void CalendarTest::Test22633HebrewLargeNegativeDay() {
|
|||
calendar->get(UCAL_HOUR, status);
|
||||
assertEquals("status return without hang", status, U_ILLEGAL_ARGUMENT_ERROR);
|
||||
}
|
||||
void CalendarTest::Test23069HebrewHanukkah() {
|
||||
// Based on Hanukkah data in
|
||||
// https://en.wikipedia.org/wiki/Jewish_and_Israeli_holidays_2000%E2%80%932050
|
||||
struct TestCase {
|
||||
int32_t hebrewYear;
|
||||
int32_t gregorianYear;
|
||||
int32_t gregorianMonth;
|
||||
int32_t gregorianDate;
|
||||
} cases[] = {
|
||||
{ 5760, 1999, UCAL_DECEMBER, 4},
|
||||
{ 5761, 2000, UCAL_DECEMBER, 22},
|
||||
{ 5762, 2001, UCAL_DECEMBER, 10},
|
||||
{ 5763, 2002, UCAL_NOVEMBER, 30},
|
||||
{ 5764, 2003, UCAL_DECEMBER, 20},
|
||||
{ 5765, 2004, UCAL_DECEMBER, 8},
|
||||
{ 5766, 2005, UCAL_DECEMBER, 26},
|
||||
{ 5767, 2006, UCAL_DECEMBER, 16},
|
||||
{ 5768, 2007, UCAL_DECEMBER, 5},
|
||||
{ 5769, 2008, UCAL_DECEMBER, 22},
|
||||
{ 5770, 2009, UCAL_DECEMBER, 12},
|
||||
{ 5771, 2010, UCAL_DECEMBER, 2},
|
||||
{ 5772, 2011, UCAL_DECEMBER, 21},
|
||||
{ 5773, 2012, UCAL_DECEMBER, 9},
|
||||
{ 5774, 2013, UCAL_NOVEMBER, 28},
|
||||
{ 5775, 2014, UCAL_DECEMBER, 17},
|
||||
{ 5776, 2015, UCAL_DECEMBER, 7},
|
||||
{ 5777, 2016, UCAL_DECEMBER, 25},
|
||||
{ 5778, 2017, UCAL_DECEMBER, 13},
|
||||
{ 5779, 2018, UCAL_DECEMBER, 3},
|
||||
{ 5780, 2019, UCAL_DECEMBER, 23},
|
||||
{ 5781, 2020, UCAL_DECEMBER, 11},
|
||||
{ 5782, 2021, UCAL_NOVEMBER, 29},
|
||||
{ 5783, 2022, UCAL_DECEMBER, 19},
|
||||
{ 5784, 2023, UCAL_DECEMBER, 8},
|
||||
{ 5785, 2024, UCAL_DECEMBER, 26},
|
||||
{ 5786, 2025, UCAL_DECEMBER, 15},
|
||||
{ 5787, 2026, UCAL_DECEMBER, 5},
|
||||
{ 5788, 2027, UCAL_DECEMBER, 25},
|
||||
{ 5789, 2028, UCAL_DECEMBER, 13},
|
||||
{ 5790, 2029, UCAL_DECEMBER, 2},
|
||||
{ 5791, 2030, UCAL_DECEMBER, 21},
|
||||
{ 5792, 2031, UCAL_DECEMBER, 10},
|
||||
{ 5793, 2032, UCAL_NOVEMBER, 28},
|
||||
{ 5794, 2033, UCAL_DECEMBER, 17},
|
||||
{ 5795, 2034, UCAL_DECEMBER, 7},
|
||||
{ 5796, 2035, UCAL_DECEMBER, 26},
|
||||
{ 5797, 2036, UCAL_DECEMBER, 14},
|
||||
{ 5798, 2037, UCAL_DECEMBER, 3},
|
||||
{ 5799, 2038, UCAL_DECEMBER, 22},
|
||||
{ 5800, 2039, UCAL_DECEMBER, 12},
|
||||
{ 5801, 2040, UCAL_NOVEMBER, 30},
|
||||
{ 5802, 2041, UCAL_DECEMBER, 18},
|
||||
{ 5803, 2042, UCAL_DECEMBER, 8},
|
||||
{ 5804, 2043, UCAL_DECEMBER, 27},
|
||||
{ 5805, 2044, UCAL_DECEMBER, 15},
|
||||
{ 5806, 2045, UCAL_DECEMBER, 4},
|
||||
{ 5807, 2046, UCAL_DECEMBER, 24},
|
||||
{ 5808, 2047, UCAL_DECEMBER, 13},
|
||||
{ 5809, 2048, UCAL_NOVEMBER, 30},
|
||||
{ 5810, 2049, UCAL_DECEMBER, 20},
|
||||
{ 5811, 2050, UCAL_DECEMBER, 10},
|
||||
};
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
LocalPointer<Calendar> hebrew(
|
||||
Calendar::createInstance(Locale("en-u-ca-hebrew"), status),
|
||||
status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
LocalPointer<GregorianCalendar> gregorian(
|
||||
new GregorianCalendar(hebrew->getTimeZone(), status), status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
for (auto& cas : cases) {
|
||||
hebrew->clear();
|
||||
// Test Hebrew Calendar to Gregorian Calendar.
|
||||
// Hanukkah is the 25th day of Kislev
|
||||
hebrew->set(UCAL_YEAR, cas.hebrewYear);
|
||||
hebrew->set(UCAL_MONTH, icu::HebrewCalendar::KISLEV);
|
||||
hebrew->set(UCAL_DATE, 25);
|
||||
gregorian->setTime(hebrew->getTime(status), status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
int32_t year = gregorian->get(UCAL_YEAR, status);
|
||||
int32_t month = gregorian->get(UCAL_MONTH, status);
|
||||
int32_t date = gregorian->get(UCAL_DATE, status);
|
||||
assertEquals("Hebrew to Gregorian Calendar year", year, cas.gregorianYear);
|
||||
assertEquals("Hebrew to Gregorian Calendar month", month, cas.gregorianMonth);
|
||||
assertEquals("Hebrew to Gregorian Calendar date", date, cas.gregorianDate);
|
||||
if (year != cas.gregorianYear || month != cas.gregorianMonth || date != cas.gregorianDate) {
|
||||
printf("Hebrew year %d Gregorain Date(%d/%d/%d) but should be Date(%d/%d/%d)\n",
|
||||
cas.hebrewYear, year, 1+month, date,
|
||||
cas.gregorianYear, 1+cas.gregorianMonth, cas.gregorianDate);
|
||||
}
|
||||
// Test Gregorian Calendar to Hebrew Calendar.
|
||||
gregorian->clear();
|
||||
gregorian->set(UCAL_YEAR, cas.gregorianYear);
|
||||
gregorian->set(UCAL_MONTH, cas.gregorianMonth);
|
||||
gregorian->set(UCAL_DATE, cas.gregorianDate);
|
||||
hebrew->setTime(gregorian->getTime(status), status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
year = hebrew->get(UCAL_YEAR, status);
|
||||
month = hebrew->get(UCAL_MONTH, status);
|
||||
date = hebrew->get(UCAL_DATE, status);
|
||||
assertEquals("Gregorian to Hebrew Calendar year", year, cas.hebrewYear);
|
||||
assertEquals("Gregorian to Hebrew Calendar month", month, icu::HebrewCalendar::KISLEV);
|
||||
assertEquals("Gregorian to Hebrew Calendar date", date, 25);
|
||||
if (year != cas.hebrewYear || month != icu::HebrewCalendar::KISLEV || date != 25) {
|
||||
printf("Gregorian year %d Hebrew Date(%d/%d/%d) but should be Date(%d/%d/25)\n",
|
||||
cas.gregorianYear, year, 1+month, date,
|
||||
cas.hebrewYear, 1+icu::HebrewCalendar::KISLEV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalendarTest::Test22730JapaneseOverflow() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
|
|
@ -363,6 +363,7 @@ public: // package
|
|||
|
||||
void TestChineseCalendarComputeMonthStart();
|
||||
void Test22633HebrewLargeNegativeDay();
|
||||
void Test23069HebrewHanukkah();
|
||||
|
||||
void RunChineseCalendarInTemporalLeapYearTest(Calendar* cal);
|
||||
void RunIslamicCalendarInTemporalLeapYearTest(Calendar* cal);
|
||||
|
|
|
@ -25,7 +25,7 @@ import com.ibm.icu.util.ULocale.Category;
|
|||
* solar year (approximately 365.24 days) is not an even multiple of
|
||||
* the lunar month (approximately 29.53 days) an extra "leap month" is
|
||||
* inserted in 7 out of every 19 years. To make matters even more
|
||||
* interesting, the start of a year can be delayed by up to three days
|
||||
* interesting, the start of a year can be delayed by up to two days
|
||||
* in order to prevent certain holidays from falling on the Sabbath and
|
||||
* to prevent certain illegal year lengths. Finally, the lengths of certain
|
||||
* months can vary depending on the number of days in the year.
|
||||
|
@ -630,7 +630,7 @@ public class HebrewCalendar extends Calendar {
|
|||
day += 1;
|
||||
wd = (int)(day % 7);
|
||||
}
|
||||
if (wd == 1 && frac > 15*HOUR_PARTS+204 && !isLeapYear(year) ) {
|
||||
else if (wd == 1 && frac > 15*HOUR_PARTS+204 && !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.
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.junit.runners.JUnit4;
|
|||
import com.ibm.icu.impl.LocaleUtility;
|
||||
import com.ibm.icu.text.DateFormat;
|
||||
import com.ibm.icu.util.Calendar;
|
||||
import com.ibm.icu.util.GregorianCalendar;
|
||||
import com.ibm.icu.util.HebrewCalendar;
|
||||
import com.ibm.icu.util.TimeZone;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
@ -332,7 +333,7 @@ public class HebrewTest extends CalendarTestFmwk {
|
|||
if (y2 != yact || m2 != mact) {
|
||||
errln("Fail: " + m + "/" + y +
|
||||
" -> add(MONTH, " + monthDelta + ") -> " +
|
||||
mact + "/" + yact + ", expected " +
|
||||
mact + "/" + yact + ", gregorian " +
|
||||
m2 + "/" + y2);
|
||||
cal.clear();
|
||||
cal.set(Calendar.YEAR, y);
|
||||
|
@ -353,7 +354,7 @@ public class HebrewTest extends CalendarTestFmwk {
|
|||
if (y3 != yact || m3 != mact) {
|
||||
errln("Fail: " + (m+monthDelta) + "/" + y +
|
||||
" -> complete() -> " +
|
||||
mact + "/" + yact + ", expected " +
|
||||
mact + "/" + yact + ", gregorian " +
|
||||
m3 + "/" + y3);
|
||||
}
|
||||
}
|
||||
|
@ -538,4 +539,102 @@ public class HebrewTest extends CalendarTestFmwk {
|
|||
logln("Info: IllegalArgumentException, because 5777 Adar I 1 is not a valid date.");
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void TestHanukkah() {
|
||||
HebrewCalendar hebrew = new HebrewCalendar();
|
||||
GregorianCalendar gregorian = new GregorianCalendar(hebrew.getTimeZone());
|
||||
hebrew.clear();
|
||||
// Based on the Hanukkah data in
|
||||
// https://en.wikipedia.org/wiki/Jewish_and_Israeli_holidays_2000%E2%80%932050
|
||||
Object[][] cases = {
|
||||
{ 5760, 1999, Calendar.DECEMBER, 4},
|
||||
{ 5761, 2000, Calendar.DECEMBER, 22},
|
||||
{ 5762, 2001, Calendar.DECEMBER, 10},
|
||||
{ 5763, 2002, Calendar.NOVEMBER, 30},
|
||||
{ 5764, 2003, Calendar.DECEMBER, 20},
|
||||
{ 5765, 2004, Calendar.DECEMBER, 8},
|
||||
{ 5766, 2005, Calendar.DECEMBER, 26},
|
||||
{ 5767, 2006, Calendar.DECEMBER, 16},
|
||||
{ 5768, 2007, Calendar.DECEMBER, 5},
|
||||
{ 5769, 2008, Calendar.DECEMBER, 22},
|
||||
{ 5770, 2009, Calendar.DECEMBER, 12},
|
||||
{ 5771, 2010, Calendar.DECEMBER, 2},
|
||||
{ 5772, 2011, Calendar.DECEMBER, 21},
|
||||
{ 5773, 2012, Calendar.DECEMBER, 9},
|
||||
{ 5774, 2013, Calendar.NOVEMBER, 28},
|
||||
{ 5775, 2014, Calendar.DECEMBER, 17},
|
||||
{ 5776, 2015, Calendar.DECEMBER, 7},
|
||||
{ 5777, 2016, Calendar.DECEMBER, 25},
|
||||
{ 5778, 2017, Calendar.DECEMBER, 13},
|
||||
{ 5779, 2018, Calendar.DECEMBER, 3},
|
||||
{ 5780, 2019, Calendar.DECEMBER, 23},
|
||||
{ 5781, 2020, Calendar.DECEMBER, 11},
|
||||
{ 5782, 2021, Calendar.NOVEMBER, 29},
|
||||
{ 5783, 2022, Calendar.DECEMBER, 19},
|
||||
{ 5784, 2023, Calendar.DECEMBER, 8},
|
||||
{ 5785, 2024, Calendar.DECEMBER, 26},
|
||||
{ 5786, 2025, Calendar.DECEMBER, 15},
|
||||
{ 5787, 2026, Calendar.DECEMBER, 5},
|
||||
{ 5788, 2027, Calendar.DECEMBER, 25},
|
||||
{ 5789, 2028, Calendar.DECEMBER, 13},
|
||||
{ 5790, 2029, Calendar.DECEMBER, 2},
|
||||
{ 5791, 2030, Calendar.DECEMBER, 21},
|
||||
{ 5792, 2031, Calendar.DECEMBER, 10},
|
||||
{ 5793, 2032, Calendar.NOVEMBER, 28},
|
||||
{ 5794, 2033, Calendar.DECEMBER, 17},
|
||||
{ 5795, 2034, Calendar.DECEMBER, 7},
|
||||
{ 5796, 2035, Calendar.DECEMBER, 26},
|
||||
{ 5797, 2036, Calendar.DECEMBER, 14},
|
||||
{ 5798, 2037, Calendar.DECEMBER, 3},
|
||||
{ 5799, 2038, Calendar.DECEMBER, 22},
|
||||
{ 5800, 2039, Calendar.DECEMBER, 12},
|
||||
{ 5801, 2040, Calendar.NOVEMBER, 30},
|
||||
{ 5802, 2041, Calendar.DECEMBER, 18},
|
||||
{ 5803, 2042, Calendar.DECEMBER, 8},
|
||||
{ 5804, 2043, Calendar.DECEMBER, 27},
|
||||
{ 5805, 2044, Calendar.DECEMBER, 15},
|
||||
{ 5806, 2045, Calendar.DECEMBER, 4},
|
||||
{ 5807, 2046, Calendar.DECEMBER, 24},
|
||||
{ 5808, 2047, Calendar.DECEMBER, 13},
|
||||
{ 5809, 2048, Calendar.NOVEMBER, 30},
|
||||
{ 5810, 2049, Calendar.DECEMBER, 20},
|
||||
{ 5811, 2050, Calendar.DECEMBER, 10},
|
||||
};
|
||||
for (Object[] cas : cases) {
|
||||
int hebrewYear = (Integer) cas[0];
|
||||
int gregorianYear = (Integer) cas[1];
|
||||
int gregorianMonth = (Integer) cas[2];
|
||||
int gregorianDate = (Integer) cas[3];
|
||||
// Test from Hebrew Calendar to Gregorian Calendar.
|
||||
// Rosh Hashanah/Hanukkah is the 25th day of Kislev
|
||||
hebrew.set(Calendar.YEAR, hebrewYear);
|
||||
hebrew.set(Calendar.MONTH, KISLEV);
|
||||
hebrew.set(Calendar.DATE, 25);
|
||||
gregorian.setTime(hebrew.getTime());
|
||||
int y = gregorian.get(Calendar.YEAR);
|
||||
int m = gregorian.get(Calendar.MONTH);
|
||||
int d = gregorian.get(Calendar.DATE);
|
||||
if (y != gregorianYear || m != gregorianMonth || d != gregorianDate) {
|
||||
errln("Fail: Hebrew year " + hebrewYear + " starts at Gregorian Date(" +
|
||||
y + "/" + (m+1) + "/" + d + ") should be Date(" +
|
||||
gregorianYear + "/" + (gregorianMonth+1) + "/" + gregorianDate + ")");
|
||||
}
|
||||
// Test from Gregorian Calendar to Hebrew Calendar.
|
||||
gregorian.clear();
|
||||
gregorian.set(Calendar.YEAR, gregorianYear);
|
||||
gregorian.set(Calendar.MONTH, gregorianMonth);
|
||||
gregorian.set(Calendar.DATE, gregorianDate);
|
||||
hebrew.setTime(gregorian.getTime());
|
||||
y = hebrew.get(Calendar.YEAR);
|
||||
m = hebrew.get(Calendar.MONTH);
|
||||
d = hebrew.get(Calendar.DATE);
|
||||
if (y != hebrewYear || m != KISLEV || d != 25) {
|
||||
errln("Fail: Gregorian Date(" +
|
||||
gregorianYear + "/" + (gregorianMonth+1) + "/" + gregorianDate + ") should get " +
|
||||
"Hebrew Date("+hebrewYear+"/"+(KISLEV+1)+"/25) but got Date(" +
|
||||
y + "/" + (m+1) + "/" + d + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue