mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-21 12:40:02 +00:00
ICU-22736 Fix Persian calendar
ICU-22736 Add tests for java and make correction Update icu4c/source/i18n/persncal.cpp Co-authored-by: Markus Scherer <markus.icu@gmail.com>
This commit is contained in:
parent
36b552737f
commit
73956e9cf3
6 changed files with 985 additions and 13 deletions
|
@ -25,6 +25,9 @@
|
|||
#include "umutex.h"
|
||||
#include "gregoimp.h" // Math
|
||||
#include <float.h>
|
||||
#include "cmemory.h"
|
||||
#include "ucln_in.h"
|
||||
#include "unicode/uniset.h"
|
||||
|
||||
static const int16_t kPersianNumDays[]
|
||||
= {0,31,62,93,124,155,186,216,246,276,306,336}; // 0-based, for day-in-year
|
||||
|
@ -62,6 +65,45 @@ static const int32_t kPersianCalendarLimits[UCAL_FIELD_COUNT][4] = {
|
|||
{ 0, 0, 11, 11}, // ORDINAL_MONTH
|
||||
};
|
||||
|
||||
namespace { // anonymous
|
||||
|
||||
static icu::UnicodeSet *gLeapCorrection = nullptr;
|
||||
static icu::UInitOnce gCorrectionInitOnce {};
|
||||
static int32_t gMinCorrection;
|
||||
} // namespace
|
||||
U_CDECL_BEGIN
|
||||
static UBool calendar_persian_cleanup() {
|
||||
if (gLeapCorrection) {
|
||||
delete gLeapCorrection;
|
||||
gLeapCorrection = nullptr;
|
||||
}
|
||||
gCorrectionInitOnce.reset();
|
||||
return true;
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
namespace { // anonymous
|
||||
static void U_CALLCONV initLeapCorrection() {
|
||||
static int16_t nonLeapYears[] = {
|
||||
1502, 1601, 1634, 1667, 1700, 1733, 1766, 1799, 1832, 1865, 1898, 1931, 1964, 1997, 2030, 2059,
|
||||
2063, 2096, 2129, 2158, 2162, 2191, 2195, 2224, 2228, 2257, 2261, 2290, 2294, 2323, 2327, 2356,
|
||||
2360, 2389, 2393, 2422, 2426, 2455, 2459, 2488, 2492, 2521, 2525, 2554, 2558, 2587, 2591, 2620,
|
||||
2624, 2653, 2657, 2686, 2690, 2719, 2723, 2748, 2752, 2756, 2781, 2785, 2789, 2818, 2822, 2847,
|
||||
2851, 2855, 2880, 2884, 2888, 2913, 2917, 2921, 2946, 2950, 2954, 2979, 2983, 2987,
|
||||
};
|
||||
gMinCorrection = nonLeapYears[0];
|
||||
icu::UnicodeSet prefab;
|
||||
for (auto year : nonLeapYears) {
|
||||
prefab.add(year);
|
||||
}
|
||||
gLeapCorrection = prefab.cloneAsThawed();
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_PERSIAN_CALENDAR, calendar_persian_cleanup);
|
||||
}
|
||||
const icu::UnicodeSet* getLeapCorrection() {
|
||||
umtx_initOnce(gCorrectionInitOnce, &initLeapCorrection);
|
||||
return gLeapCorrection;
|
||||
}
|
||||
} // namespace anonymous
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
static const int32_t PERSIAN_EPOCH = 1948320;
|
||||
|
@ -111,8 +153,15 @@ int32_t PersianCalendar::handleGetLimit(UCalendarDateFields field, ELimitType li
|
|||
*/
|
||||
UBool PersianCalendar::isLeapYear(int32_t year)
|
||||
{
|
||||
if (year >= gMinCorrection && getLeapCorrection()->contains(year)) {
|
||||
return false;
|
||||
}
|
||||
if (year > gMinCorrection && getLeapCorrection()->contains(year-1)) {
|
||||
return true;
|
||||
}
|
||||
int64_t y = static_cast<int64_t>(year) * 25LL + 11LL;
|
||||
return (y % 33L < 8);
|
||||
bool res = (y % 33L < 8);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,6 +214,15 @@ int32_t PersianCalendar::handleGetYearLength(int32_t extendedYear) const {
|
|||
// Functions for converting from field values to milliseconds....
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
static int64_t firstJulianOfYear(int64_t year) {
|
||||
int64_t julianDay = 365LL * (year - 1LL) + ClockMath::floorDivide(8LL * year + 21, 33);
|
||||
if (year > gMinCorrection && getLeapCorrection()->contains(year-1)) {
|
||||
julianDay--;
|
||||
}
|
||||
return julianDay;
|
||||
}
|
||||
|
||||
|
||||
// Return JD of start of given month/year
|
||||
int64_t PersianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /*useMonth*/, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
|
@ -179,7 +237,7 @@ int64_t PersianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, U
|
|||
}
|
||||
}
|
||||
|
||||
int64_t julianDay = PERSIAN_EPOCH - 1LL + 365LL * (eyear - 1LL) + ClockMath::floorDivide(8LL * eyear + 21, 33);
|
||||
int64_t julianDay = PERSIAN_EPOCH - 1LL + firstJulianOfYear(eyear);
|
||||
|
||||
if (month != 0) {
|
||||
julianDay += kPersianNumDays[month];
|
||||
|
@ -219,6 +277,7 @@ int32_t PersianCalendar::handleGetExtendedYear(UErrorCode& status) {
|
|||
void PersianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) {
|
||||
int64_t daysSinceEpoch = julianDay;
|
||||
daysSinceEpoch -= PERSIAN_EPOCH;
|
||||
|
||||
int64_t year = ClockMath::floorDivideInt64(
|
||||
33LL * daysSinceEpoch + 3LL, 12053LL) + 1LL;
|
||||
if (year > INT32_MAX || year < INT32_MIN) {
|
||||
|
@ -226,11 +285,16 @@ void PersianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
|
|||
return;
|
||||
}
|
||||
|
||||
int64_t farvardin1 = 365LL * (year - 1) + ClockMath::floorDivide(8LL * year + 21, 33);
|
||||
int64_t farvardin1 = firstJulianOfYear(year);
|
||||
|
||||
int32_t dayOfYear = daysSinceEpoch - farvardin1; // 0-based
|
||||
U_ASSERT(dayOfYear >= 0);
|
||||
U_ASSERT(dayOfYear < 366);
|
||||
//
|
||||
|
||||
if (dayOfYear == 365 && year >= gMinCorrection && getLeapCorrection()->contains(year)) {
|
||||
year++;
|
||||
dayOfYear = 0;
|
||||
}
|
||||
int32_t month;
|
||||
if (dayOfYear < 216) { // Compute 0-based month
|
||||
month = dayOfYear / 31;
|
||||
|
@ -240,11 +304,11 @@ void PersianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
|
|||
U_ASSERT(month >= 0);
|
||||
U_ASSERT(month < 12);
|
||||
|
||||
int32_t dayOfMonth = dayOfYear - kPersianNumDays[month] + 1;
|
||||
++dayOfYear; // Make it 1-based now
|
||||
int32_t dayOfMonth = dayOfYear - kPersianNumDays[month];
|
||||
U_ASSERT(dayOfMonth > 0);
|
||||
U_ASSERT(dayOfMonth <= 31);
|
||||
|
||||
++dayOfYear; // Make it 1-based now
|
||||
|
||||
internalSet(UCAL_ERA, 0);
|
||||
internalSet(UCAL_YEAR, year);
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef enum ECleanupI18NType {
|
|||
UCLN_I18N_HEBREW_CALENDAR,
|
||||
UCLN_I18N_ASTRO_CALENDAR,
|
||||
UCLN_I18N_DANGI_CALENDAR,
|
||||
UCLN_I18N_PERSIAN_CALENDAR,
|
||||
UCLN_I18N_CALENDAR,
|
||||
UCLN_I18N_TIMEZONEFORMAT,
|
||||
UCLN_I18N_TZDBTIMEZONENAMES,
|
||||
|
|
|
@ -86,6 +86,10 @@ void IntlCalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &n
|
|||
TESTCASE_AUTO(TestJapanese3860);
|
||||
TESTCASE_AUTO(TestForceGannenNumbering);
|
||||
TESTCASE_AUTO(TestPersian);
|
||||
TESTCASE_AUTO(TestPersianJulianDayToYMD);
|
||||
TESTCASE_AUTO(TestPersianYMDToJulianDay);
|
||||
TESTCASE_AUTO(TestPersianJan1ToGregorian);
|
||||
TESTCASE_AUTO(TestGregorianToPersian);
|
||||
TESTCASE_AUTO(TestPersianFormat);
|
||||
TESTCASE_AUTO(TestTaiwan);
|
||||
TESTCASE_AUTO(TestConsistencyGregorian);
|
||||
|
@ -896,6 +900,433 @@ void IntlCalendarTest::TestPersian() {
|
|||
delete grego;
|
||||
}
|
||||
|
||||
// Test data copy from
|
||||
// https://github.com/unicode-org/icu4x/blob/main/components/calendar/src/persian.rs#L299
|
||||
static struct PersianTestCase1 {
|
||||
int32_t rd;
|
||||
int32_t year;
|
||||
int32_t month;
|
||||
int32_t day;
|
||||
} persianTestCases1[]{
|
||||
{656786, 1178, 1, 1},
|
||||
{664224, 1198, 5, 10},
|
||||
{671401, 1218, 1, 7},
|
||||
{694799, 1282, 1, 29},
|
||||
{702806, 1304, 1, 1},
|
||||
{704424, 1308, 6, 3},
|
||||
{708842, 1320, 7, 7},
|
||||
{709409, 1322, 1, 29},
|
||||
{709580, 1322, 7, 14},
|
||||
{727274, 1370, 12, 27},
|
||||
{728714, 1374, 12, 6},
|
||||
{739330, 1403, 12, 30},
|
||||
{739331, 1404, 1, 1},
|
||||
{744313, 1417, 8, 19},
|
||||
{763436, 1469, 12, 30},
|
||||
{763437, 1470, 1, 1},
|
||||
{764652, 1473, 4, 28},
|
||||
{775123, 1501, 12, 29},
|
||||
{775488, 1502, 12, 29},
|
||||
{775487, 1502, 12, 28},
|
||||
{775488, 1502, 12, 29},
|
||||
{775489, 1503, 1, 1},
|
||||
{775490, 1503, 1, 2},
|
||||
{1317873, 2987, 12, 29},
|
||||
{1317874, 2988, 1, 1},
|
||||
{1317875, 2988, 1, 2},
|
||||
};
|
||||
|
||||
void IntlCalendarTest::TestPersianJulianDayToYMD() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::unique_ptr<Calendar> cal(Calendar::createInstance(TimeZone::createTimeZone("Asia/Tehran"), "fa_IR@calendar=persian", status));
|
||||
|
||||
for (const auto &testCase : persianTestCases1) {
|
||||
status = U_ZERO_ERROR;
|
||||
int32_t jday = testCase.rd + 1721425;
|
||||
cal->clear();
|
||||
cal->set(UCAL_JULIAN_DAY, jday);
|
||||
int32_t actualYear = cal->get(UCAL_YEAR, status);
|
||||
int32_t actualMonth = cal->get(UCAL_MONTH, status)+1;
|
||||
int32_t actualDay = cal->get(UCAL_DAY_OF_MONTH, status);
|
||||
if (actualYear != testCase.year || actualMonth != testCase.month || actualDay != testCase.day) {
|
||||
errln(UnicodeString("rd ") + testCase.rd + " = jday " + jday + " -> expect Persian(" +
|
||||
testCase.year + "/" + testCase.month + "/" + testCase.day + ") " +
|
||||
"actual Persian(" + actualYear + "/" + actualMonth + "/" + actualDay + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntlCalendarTest::TestPersianYMDToJulianDay() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::unique_ptr<Calendar> cal(Calendar::createInstance(TimeZone::createTimeZone("Asia/Tehran"), "fa_IR@calendar=persian", status));
|
||||
|
||||
for (const auto &testCase : persianTestCases1) {
|
||||
status = U_ZERO_ERROR;
|
||||
cal->clear();
|
||||
cal->set(UCAL_YEAR, testCase.year);
|
||||
cal->set(UCAL_MONTH, testCase.month-1);
|
||||
cal->set(UCAL_DAY_OF_MONTH, testCase.day);
|
||||
int32_t actualJday = cal->get(UCAL_JULIAN_DAY, status);
|
||||
int32_t actualRD = actualJday - 1721425;
|
||||
if (actualRD != testCase.rd) {
|
||||
errln(UnicodeString("Persian(") + testCase.year + "/" + testCase.month + "/" + testCase.day + ") => "+
|
||||
"expect rd " + testCase.rd + " but actual jd: " + actualJday + " = rd " + actualRD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test data copy from
|
||||
// https://github.com/unicode-org/icu4x/blob/main/components/calendar/src/persian.rs#L534
|
||||
// From https://calendar.ut.ac.ir/Fa/News/Data/Doc/KabiseShamsi1206-1498-new.pdf
|
||||
// Plain text version at https://github.com/roozbehp/persiancalendar/blob/main/kabise.txt
|
||||
static struct PersianTestCase2 {
|
||||
int32_t pYear;
|
||||
bool pLeap;
|
||||
int32_t year;
|
||||
int32_t month;
|
||||
int32_t day;
|
||||
} persianTestCases2[]{
|
||||
{1206, false, 1827, 3, 22},
|
||||
{1207, false, 1828, 3, 21},
|
||||
{1208, false, 1829, 3, 21},
|
||||
{1209, false, 1830, 3, 21},
|
||||
{1210, true, 1831, 3, 21},
|
||||
{1211, false, 1832, 3, 21},
|
||||
{1212, false, 1833, 3, 21},
|
||||
{1213, false, 1834, 3, 21},
|
||||
{1214, true, 1835, 3, 21},
|
||||
{1215, false, 1836, 3, 21},
|
||||
{1216, false, 1837, 3, 21},
|
||||
{1217, false, 1838, 3, 21},
|
||||
{1218, true, 1839, 3, 21},
|
||||
{1219, false, 1840, 3, 21},
|
||||
{1220, false, 1841, 3, 21},
|
||||
{1221, false, 1842, 3, 21},
|
||||
{1222, true, 1843, 3, 21},
|
||||
{1223, false, 1844, 3, 21},
|
||||
{1224, false, 1845, 3, 21},
|
||||
{1225, false, 1846, 3, 21},
|
||||
{1226, true, 1847, 3, 21},
|
||||
{1227, false, 1848, 3, 21},
|
||||
{1228, false, 1849, 3, 21},
|
||||
{1229, false, 1850, 3, 21},
|
||||
{1230, true, 1851, 3, 21},
|
||||
{1231, false, 1852, 3, 21},
|
||||
{1232, false, 1853, 3, 21},
|
||||
{1233, false, 1854, 3, 21},
|
||||
{1234, true, 1855, 3, 21},
|
||||
{1235, false, 1856, 3, 21},
|
||||
{1236, false, 1857, 3, 21},
|
||||
{1237, false, 1858, 3, 21},
|
||||
{1238, true, 1859, 3, 21},
|
||||
{1239, false, 1860, 3, 21},
|
||||
{1240, false, 1861, 3, 21},
|
||||
{1241, false, 1862, 3, 21},
|
||||
{1242, false, 1863, 3, 21},
|
||||
{1243, true, 1864, 3, 20},
|
||||
{1244, false, 1865, 3, 21},
|
||||
{1245, false, 1866, 3, 21},
|
||||
{1246, false, 1867, 3, 21},
|
||||
{1247, true, 1868, 3, 20},
|
||||
{1248, false, 1869, 3, 21},
|
||||
{1249, false, 1870, 3, 21},
|
||||
{1250, false, 1871, 3, 21},
|
||||
{1251, true, 1872, 3, 20},
|
||||
{1252, false, 1873, 3, 21},
|
||||
{1253, false, 1874, 3, 21},
|
||||
{1254, false, 1875, 3, 21},
|
||||
{1255, true, 1876, 3, 20},
|
||||
{1256, false, 1877, 3, 21},
|
||||
{1257, false, 1878, 3, 21},
|
||||
{1258, false, 1879, 3, 21},
|
||||
{1259, true, 1880, 3, 20},
|
||||
{1260, false, 1881, 3, 21},
|
||||
{1261, false, 1882, 3, 21},
|
||||
{1262, false, 1883, 3, 21},
|
||||
{1263, true, 1884, 3, 20},
|
||||
{1264, false, 1885, 3, 21},
|
||||
{1265, false, 1886, 3, 21},
|
||||
{1266, false, 1887, 3, 21},
|
||||
{1267, true, 1888, 3, 20},
|
||||
{1268, false, 1889, 3, 21},
|
||||
{1269, false, 1890, 3, 21},
|
||||
{1270, false, 1891, 3, 21},
|
||||
{1271, true, 1892, 3, 20},
|
||||
{1272, false, 1893, 3, 21},
|
||||
{1273, false, 1894, 3, 21},
|
||||
{1274, false, 1895, 3, 21},
|
||||
{1275, false, 1896, 3, 20},
|
||||
{1276, true, 1897, 3, 20},
|
||||
{1277, false, 1898, 3, 21},
|
||||
{1278, false, 1899, 3, 21},
|
||||
{1279, false, 1900, 3, 21},
|
||||
{1280, true, 1901, 3, 21},
|
||||
{1281, false, 1902, 3, 22},
|
||||
{1282, false, 1903, 3, 22},
|
||||
{1283, false, 1904, 3, 21},
|
||||
{1284, true, 1905, 3, 21},
|
||||
{1285, false, 1906, 3, 22},
|
||||
{1286, false, 1907, 3, 22},
|
||||
{1287, false, 1908, 3, 21},
|
||||
{1288, true, 1909, 3, 21},
|
||||
{1289, false, 1910, 3, 22},
|
||||
{1290, false, 1911, 3, 22},
|
||||
{1291, false, 1912, 3, 21},
|
||||
{1292, true, 1913, 3, 21},
|
||||
{1293, false, 1914, 3, 22},
|
||||
{1294, false, 1915, 3, 22},
|
||||
{1295, false, 1916, 3, 21},
|
||||
{1296, true, 1917, 3, 21},
|
||||
{1297, false, 1918, 3, 22},
|
||||
{1298, false, 1919, 3, 22},
|
||||
{1299, false, 1920, 3, 21},
|
||||
{1300, true, 1921, 3, 21},
|
||||
{1301, false, 1922, 3, 22},
|
||||
{1302, false, 1923, 3, 22},
|
||||
{1303, false, 1924, 3, 21},
|
||||
{1304, true, 1925, 3, 21},
|
||||
{1305, false, 1926, 3, 22},
|
||||
{1306, false, 1927, 3, 22},
|
||||
{1307, false, 1928, 3, 21},
|
||||
{1308, false, 1929, 3, 21},
|
||||
{1309, true, 1930, 3, 21},
|
||||
{1310, false, 1931, 3, 22},
|
||||
{1311, false, 1932, 3, 21},
|
||||
{1312, false, 1933, 3, 21},
|
||||
{1313, true, 1934, 3, 21},
|
||||
{1314, false, 1935, 3, 22},
|
||||
{1315, false, 1936, 3, 21},
|
||||
{1316, false, 1937, 3, 21},
|
||||
{1317, true, 1938, 3, 21},
|
||||
{1318, false, 1939, 3, 22},
|
||||
{1319, false, 1940, 3, 21},
|
||||
{1320, false, 1941, 3, 21},
|
||||
{1321, true, 1942, 3, 21},
|
||||
{1322, false, 1943, 3, 22},
|
||||
{1323, false, 1944, 3, 21},
|
||||
{1324, false, 1945, 3, 21},
|
||||
{1325, true, 1946, 3, 21},
|
||||
{1326, false, 1947, 3, 22},
|
||||
{1327, false, 1948, 3, 21},
|
||||
{1328, false, 1949, 3, 21},
|
||||
{1329, true, 1950, 3, 21},
|
||||
{1330, false, 1951, 3, 22},
|
||||
{1331, false, 1952, 3, 21},
|
||||
{1332, false, 1953, 3, 21},
|
||||
{1333, true, 1954, 3, 21},
|
||||
{1334, false, 1955, 3, 22},
|
||||
{1335, false, 1956, 3, 21},
|
||||
{1336, false, 1957, 3, 21},
|
||||
{1337, true, 1958, 3, 21},
|
||||
{1338, false, 1959, 3, 22},
|
||||
{1339, false, 1960, 3, 21},
|
||||
{1340, false, 1961, 3, 21},
|
||||
{1341, false, 1962, 3, 21},
|
||||
{1342, true, 1963, 3, 21},
|
||||
{1343, false, 1964, 3, 21},
|
||||
{1344, false, 1965, 3, 21},
|
||||
{1345, false, 1966, 3, 21},
|
||||
{1346, true, 1967, 3, 21},
|
||||
{1347, false, 1968, 3, 21},
|
||||
{1348, false, 1969, 3, 21},
|
||||
{1349, false, 1970, 3, 21},
|
||||
{1350, true, 1971, 3, 21},
|
||||
{1351, false, 1972, 3, 21},
|
||||
{1352, false, 1973, 3, 21},
|
||||
{1353, false, 1974, 3, 21},
|
||||
{1354, true, 1975, 3, 21},
|
||||
{1355, false, 1976, 3, 21},
|
||||
{1356, false, 1977, 3, 21},
|
||||
{1357, false, 1978, 3, 21},
|
||||
{1358, true, 1979, 3, 21},
|
||||
{1359, false, 1980, 3, 21},
|
||||
{1360, false, 1981, 3, 21},
|
||||
{1361, false, 1982, 3, 21},
|
||||
{1362, true, 1983, 3, 21},
|
||||
{1363, false, 1984, 3, 21},
|
||||
{1364, false, 1985, 3, 21},
|
||||
{1365, false, 1986, 3, 21},
|
||||
{1366, true, 1987, 3, 21},
|
||||
{1367, false, 1988, 3, 21},
|
||||
{1368, false, 1989, 3, 21},
|
||||
{1369, false, 1990, 3, 21},
|
||||
{1370, true, 1991, 3, 21},
|
||||
{1371, false, 1992, 3, 21},
|
||||
{1372, false, 1993, 3, 21},
|
||||
{1373, false, 1994, 3, 21},
|
||||
{1374, false, 1995, 3, 21},
|
||||
{1375, true, 1996, 3, 20},
|
||||
{1376, false, 1997, 3, 21},
|
||||
{1377, false, 1998, 3, 21},
|
||||
{1378, false, 1999, 3, 21},
|
||||
{1379, true, 2000, 3, 20},
|
||||
{1380, false, 2001, 3, 21},
|
||||
{1381, false, 2002, 3, 21},
|
||||
{1382, false, 2003, 3, 21},
|
||||
{1383, true, 2004, 3, 20},
|
||||
{1384, false, 2005, 3, 21},
|
||||
{1385, false, 2006, 3, 21},
|
||||
{1386, false, 2007, 3, 21},
|
||||
{1387, true, 2008, 3, 20},
|
||||
{1388, false, 2009, 3, 21},
|
||||
{1389, false, 2010, 3, 21},
|
||||
{1390, false, 2011, 3, 21},
|
||||
{1391, true, 2012, 3, 20},
|
||||
{1392, false, 2013, 3, 21},
|
||||
{1393, false, 2014, 3, 21},
|
||||
{1394, false, 2015, 3, 21},
|
||||
{1395, true, 2016, 3, 20},
|
||||
{1396, false, 2017, 3, 21},
|
||||
{1397, false, 2018, 3, 21},
|
||||
{1398, false, 2019, 3, 21},
|
||||
{1399, true, 2020, 3, 20},
|
||||
{1400, false, 2021, 3, 21},
|
||||
{1401, false, 2022, 3, 21},
|
||||
{1402, false, 2023, 3, 21},
|
||||
{1403, true, 2024, 3, 20},
|
||||
{1404, false, 2025, 3, 21},
|
||||
{1405, false, 2026, 3, 21},
|
||||
{1406, false, 2027, 3, 21},
|
||||
{1407, false, 2028, 3, 20},
|
||||
{1408, true, 2029, 3, 20},
|
||||
{1409, false, 2030, 3, 21},
|
||||
{1410, false, 2031, 3, 21},
|
||||
{1411, false, 2032, 3, 20},
|
||||
{1412, true, 2033, 3, 20},
|
||||
{1413, false, 2034, 3, 21},
|
||||
{1414, false, 2035, 3, 21},
|
||||
{1415, false, 2036, 3, 20},
|
||||
{1416, true, 2037, 3, 20},
|
||||
{1417, false, 2038, 3, 21},
|
||||
{1418, false, 2039, 3, 21},
|
||||
{1419, false, 2040, 3, 20},
|
||||
{1420, true, 2041, 3, 20},
|
||||
{1421, false, 2042, 3, 21},
|
||||
{1422, false, 2043, 3, 21},
|
||||
{1423, false, 2044, 3, 20},
|
||||
{1424, true, 2045, 3, 20},
|
||||
{1425, false, 2046, 3, 21},
|
||||
{1426, false, 2047, 3, 21},
|
||||
{1427, false, 2048, 3, 20},
|
||||
{1428, true, 2049, 3, 20},
|
||||
{1429, false, 2050, 3, 21},
|
||||
{1430, false, 2051, 3, 21},
|
||||
{1431, false, 2052, 3, 20},
|
||||
{1432, true, 2053, 3, 20},
|
||||
{1433, false, 2054, 3, 21},
|
||||
{1434, false, 2055, 3, 21},
|
||||
{1435, false, 2056, 3, 20},
|
||||
{1436, true, 2057, 3, 20},
|
||||
{1437, false, 2058, 3, 21},
|
||||
{1438, false, 2059, 3, 21},
|
||||
{1439, false, 2060, 3, 20},
|
||||
{1440, false, 2061, 3, 20},
|
||||
{1441, true, 2062, 3, 20},
|
||||
{1442, false, 2063, 3, 21},
|
||||
{1443, false, 2064, 3, 20},
|
||||
{1444, false, 2065, 3, 20},
|
||||
{1445, true, 2066, 3, 20},
|
||||
{1446, false, 2067, 3, 21},
|
||||
{1447, false, 2068, 3, 20},
|
||||
{1448, false, 2069, 3, 20},
|
||||
{1449, true, 2070, 3, 20},
|
||||
{1450, false, 2071, 3, 21},
|
||||
{1451, false, 2072, 3, 20},
|
||||
{1452, false, 2073, 3, 20},
|
||||
{1453, true, 2074, 3, 20},
|
||||
{1454, false, 2075, 3, 21},
|
||||
{1455, false, 2076, 3, 20},
|
||||
{1456, false, 2077, 3, 20},
|
||||
{1457, true, 2078, 3, 20},
|
||||
{1458, false, 2079, 3, 21},
|
||||
{1459, false, 2080, 3, 20},
|
||||
{1460, false, 2081, 3, 20},
|
||||
{1461, true, 2082, 3, 20},
|
||||
{1462, false, 2083, 3, 21},
|
||||
{1463, false, 2084, 3, 20},
|
||||
{1464, false, 2085, 3, 20},
|
||||
{1465, true, 2086, 3, 20},
|
||||
{1466, false, 2087, 3, 21},
|
||||
{1467, false, 2088, 3, 20},
|
||||
{1468, false, 2089, 3, 20},
|
||||
{1469, true, 2090, 3, 20},
|
||||
{1470, false, 2091, 3, 21},
|
||||
{1471, false, 2092, 3, 20},
|
||||
{1472, false, 2093, 3, 20},
|
||||
{1473, false, 2094, 3, 20},
|
||||
{1474, true, 2095, 3, 20},
|
||||
{1475, false, 2096, 3, 20},
|
||||
{1476, false, 2097, 3, 20},
|
||||
{1477, false, 2098, 3, 20},
|
||||
{1478, true, 2099, 3, 20},
|
||||
{1479, false, 2100, 3, 21},
|
||||
{1480, false, 2101, 3, 21},
|
||||
{1481, false, 2102, 3, 21},
|
||||
{1482, true, 2103, 3, 21},
|
||||
{1483, false, 2104, 3, 21},
|
||||
{1484, false, 2105, 3, 21},
|
||||
{1485, false, 2106, 3, 21},
|
||||
{1486, true, 2107, 3, 21},
|
||||
{1487, false, 2108, 3, 21},
|
||||
{1488, false, 2109, 3, 21},
|
||||
{1489, false, 2110, 3, 21},
|
||||
{1490, true, 2111, 3, 21},
|
||||
{1491, false, 2112, 3, 21},
|
||||
{1492, false, 2113, 3, 21},
|
||||
{1493, false, 2114, 3, 21},
|
||||
{1494, true, 2115, 3, 21},
|
||||
{1495, false, 2116, 3, 21},
|
||||
{1496, false, 2117, 3, 21},
|
||||
{1497, false, 2118, 3, 21},
|
||||
{1498, true, 2119, 3, 21},
|
||||
};
|
||||
|
||||
void IntlCalendarTest::TestPersianJan1ToGregorian() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::unique_ptr<Calendar> gcal(Calendar::createInstance(TimeZone::createTimeZone("Asia/Tehran"), "en", status));
|
||||
std::unique_ptr<Calendar> cal(Calendar::createInstance(TimeZone::createTimeZone("Asia/Tehran"), "fa_IR@calendar=persian", status));
|
||||
|
||||
for (const auto &testCase : persianTestCases2) {
|
||||
status = U_ZERO_ERROR;
|
||||
cal->clear();
|
||||
cal->set(UCAL_YEAR, testCase.pYear);
|
||||
cal->set(UCAL_MONTH, 0);
|
||||
cal->set(UCAL_DAY_OF_MONTH, 1);
|
||||
gcal->setTime(cal->getTime(status), status);
|
||||
int32_t actualYear = gcal->get(UCAL_YEAR, status);
|
||||
int32_t actualMonth = gcal->get(UCAL_MONTH, status)+1;
|
||||
int32_t actualDay = gcal->get(UCAL_DAY_OF_MONTH, status);
|
||||
if (actualYear != testCase.year || actualMonth != testCase.month || actualDay != testCase.day) {
|
||||
errln(UnicodeString("Persian(") + testCase.pYear + ", 1, 1) => " +
|
||||
"expect Gregorian(" + testCase.year + "/" + testCase.month + "/" + testCase.day + ") " +
|
||||
"actual Gregorian(" + actualYear + "/" + actualMonth + "/" + actualDay + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntlCalendarTest::TestGregorianToPersian() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::unique_ptr<Calendar> gcal(Calendar::createInstance(TimeZone::createTimeZone("Asia/Tehran"), "en", status));
|
||||
std::unique_ptr<Calendar> cal(Calendar::createInstance(TimeZone::createTimeZone("Asia/Tehran"), "fa_IR@calendar=persian", status));
|
||||
|
||||
for (const auto &testCase : persianTestCases2) {
|
||||
status = U_ZERO_ERROR;
|
||||
gcal->clear();
|
||||
gcal->set(UCAL_YEAR, testCase.year);
|
||||
gcal->set(UCAL_MONTH, testCase.month-1);
|
||||
gcal->set(UCAL_DAY_OF_MONTH, testCase.day);
|
||||
cal->setTime(gcal->getTime(status), status);
|
||||
int32_t persianYear = cal->get(UCAL_YEAR, status);
|
||||
int32_t persianMonth = cal->get(UCAL_MONTH, status)+1;
|
||||
int32_t persianDay = cal->get(UCAL_DAY_OF_MONTH, status);
|
||||
if (persianYear != testCase.pYear || persianMonth != 1 || persianDay != 1) {
|
||||
errln(UnicodeString("Gregorian(") + testCase.year + "/" + testCase.month + "/" + testCase.day + ") "+
|
||||
" => expect Persian(" + testCase.pYear + "/1/1) actual " +
|
||||
"Persian(" + persianYear + "/" + persianMonth + "/" + persianDay + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntlCalendarTest::TestPersianFormat() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"), Locale(" en_US@calendar=persian"), status);
|
||||
|
|
|
@ -41,6 +41,10 @@ public:
|
|||
void TestForceGannenNumbering();
|
||||
|
||||
void TestPersian();
|
||||
void TestPersianJulianDayToYMD();
|
||||
void TestPersianYMDToJulianDay();
|
||||
void TestPersianJan1ToGregorian();
|
||||
void TestGregorianToPersian();
|
||||
void TestPersianFormat();
|
||||
|
||||
void TestConsistencyGregorian();
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
package com.ibm.icu.util;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.icu.util.ULocale.Category;
|
||||
|
||||
|
@ -93,6 +95,22 @@ public class PersianCalendar extends Calendar {
|
|||
|
||||
private static final int PERSIAN_EPOCH = 1948320;
|
||||
|
||||
private static final int NON_LEAP_YEARS[] = {
|
||||
1502, 1601, 1634, 1667, 1700, 1733, 1766, 1799, 1832, 1865, 1898, 1931, 1964, 1997, 2030, 2059,
|
||||
2063, 2096, 2129, 2158, 2162, 2191, 2195, 2224, 2228, 2257, 2261, 2290, 2294, 2323, 2327, 2356,
|
||||
2360, 2389, 2393, 2422, 2426, 2455, 2459, 2488, 2492, 2521, 2525, 2554, 2558, 2587, 2591, 2620,
|
||||
2624, 2653, 2657, 2686, 2690, 2719, 2723, 2748, 2752, 2756, 2781, 2785, 2789, 2818, 2822, 2847,
|
||||
2851, 2855, 2880, 2884, 2888, 2913, 2917, 2921, 2946, 2950, 2954, 2979, 2983, 2987,
|
||||
};
|
||||
|
||||
private static Set<Integer> LEAP_CORRECTION = null;
|
||||
{
|
||||
Set<Integer> prefab = new HashSet<Integer>(NON_LEAP_YEARS.length);
|
||||
for (int nonLeap : NON_LEAP_YEARS) {
|
||||
prefab.add(nonLeap);
|
||||
}
|
||||
LEAP_CORRECTION = prefab;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// Constructors...
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -312,10 +330,15 @@ public class PersianCalendar extends Calendar {
|
|||
*/
|
||||
private final static boolean isLeapYear(int year)
|
||||
{
|
||||
if (year >= NON_LEAP_YEARS[0] && LEAP_CORRECTION.contains(year)) {
|
||||
return false;
|
||||
}
|
||||
if (year > NON_LEAP_YEARS[0] && LEAP_CORRECTION.contains(year-1)) {
|
||||
return true;
|
||||
}
|
||||
int[] remainder = new int[1];
|
||||
floorDivide(25 * year + 11, 33, remainder);
|
||||
return remainder[0] < 8;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -375,12 +398,12 @@ public class PersianCalendar extends Calendar {
|
|||
month = rem[0];
|
||||
}
|
||||
|
||||
int julianDay = PERSIAN_EPOCH - 1 + 365 * (eyear - 1) + floorDivide(8 * eyear + 21, 33);
|
||||
long julianDay = PERSIAN_EPOCH - 1L + firstJulianOfYear(eyear);
|
||||
if (month != 0) {
|
||||
julianDay += MONTH_COUNT[month][2];
|
||||
}
|
||||
return julianDay;
|
||||
}
|
||||
return (int)julianDay;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Functions for converting from milliseconds to field values
|
||||
|
@ -401,6 +424,13 @@ public class PersianCalendar extends Calendar {
|
|||
return year;
|
||||
}
|
||||
|
||||
private static long firstJulianOfYear(int year) {
|
||||
long julianDay = 365L * (year - 1L) + floorDivide(8L * year + 21, 33L);
|
||||
if (year > NON_LEAP_YEARS[0] && LEAP_CORRECTION.contains(year-1)) {
|
||||
julianDay--;
|
||||
}
|
||||
return julianDay;
|
||||
}
|
||||
/**
|
||||
* Override Calendar to compute several fields specific to the Persian
|
||||
* calendar system. These are:
|
||||
|
@ -425,16 +455,22 @@ public class PersianCalendar extends Calendar {
|
|||
long daysSinceEpoch = julianDay - PERSIAN_EPOCH;
|
||||
year = 1 + (int) floorDivide(33 * daysSinceEpoch + 3, 12053);
|
||||
|
||||
long farvardin1 = 365L * (year - 1L) + floorDivide(8L * year + 21, 33L);
|
||||
long farvardin1 = firstJulianOfYear(year);
|
||||
|
||||
dayOfYear = (int)(daysSinceEpoch - farvardin1); // 0-based
|
||||
if (dayOfYear == 365 && year >= NON_LEAP_YEARS[0] && LEAP_CORRECTION.contains(year)) {
|
||||
year++;
|
||||
dayOfYear = 0;
|
||||
}
|
||||
if (dayOfYear < 216) { // Compute 0-based month
|
||||
month = dayOfYear / 31;
|
||||
} else {
|
||||
month = (dayOfYear - 6) / 30;
|
||||
}
|
||||
dayOfMonth = dayOfYear - MONTH_COUNT[month][2] + 1;
|
||||
|
||||
++dayOfYear; // Make it 1-based now
|
||||
|
||||
dayOfMonth = dayOfYear - MONTH_COUNT[month][2];
|
||||
|
||||
internalSet(ERA, 0);
|
||||
internalSet(YEAR, year);
|
||||
internalSet(EXTENDED_YEAR, year);
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.junit.runners.JUnit4;
|
|||
|
||||
import com.ibm.icu.util.Calendar;
|
||||
import com.ibm.icu.util.PersianCalendar;
|
||||
import com.ibm.icu.util.TimeZone;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
|
@ -143,4 +144,439 @@ public class PersianTest extends CalendarTestFmwk {
|
|||
|
||||
new StubCalendar();
|
||||
}
|
||||
|
||||
// Test data copy from
|
||||
// https://github.com/unicode-org/icu4x/blob/main/components/calendar/src/persian.rs#L299
|
||||
final int[] PERSIAN_TEST_CASE_1 = {
|
||||
// rd, year, month, day
|
||||
656786, 1178, 1, 1,
|
||||
664224, 1198, 5, 10,
|
||||
671401, 1218, 1, 7,
|
||||
694799, 1282, 1, 29,
|
||||
702806, 1304, 1, 1,
|
||||
704424, 1308, 6, 3,
|
||||
708842, 1320, 7, 7,
|
||||
709409, 1322, 1, 29,
|
||||
709580, 1322, 7, 14,
|
||||
727274, 1370, 12, 27,
|
||||
728714, 1374, 12, 6,
|
||||
739330, 1403, 12, 30,
|
||||
739331, 1404, 1, 1,
|
||||
744313, 1417, 8, 19,
|
||||
763436, 1469, 12, 30,
|
||||
763437, 1470, 1, 1,
|
||||
764652, 1473, 4, 28,
|
||||
775123, 1501, 12, 29,
|
||||
775488, 1502, 12, 29,
|
||||
775487, 1502, 12, 28,
|
||||
775488, 1502, 12, 29,
|
||||
775489, 1503, 1, 1,
|
||||
775490, 1503, 1, 2,
|
||||
1317873, 2987, 12, 29,
|
||||
1317874, 2988, 1, 1,
|
||||
1317875, 2988, 1, 2,
|
||||
};
|
||||
|
||||
@Test
|
||||
public void TestPersianJulianDayToYMD() {
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"),
|
||||
new ULocale("fa_IR@calendar=persian"));
|
||||
for (int i = 0; i < PERSIAN_TEST_CASE_1.length;) {
|
||||
int rd = PERSIAN_TEST_CASE_1[i++];
|
||||
int year = PERSIAN_TEST_CASE_1[i++];
|
||||
int month = PERSIAN_TEST_CASE_1[i++];
|
||||
int day = PERSIAN_TEST_CASE_1[i++];
|
||||
int jday = rd + 1721425;
|
||||
cal.clear();
|
||||
cal.set(Calendar.JULIAN_DAY, jday);
|
||||
int actualYear = cal.get(Calendar.YEAR);
|
||||
int actualMonth = cal.get(Calendar.MONTH)+1;
|
||||
int actualDay = cal.get(Calendar.DAY_OF_MONTH);
|
||||
if (actualYear != year || actualMonth != month || actualDay != day) {
|
||||
errln("Fail: rd " + rd + " = jday " + jday + " -> expect Persian(" +
|
||||
year + "/" + month + "/" + day + ") " +
|
||||
"actual Persian(" + actualYear + "/" + actualMonth + "/" + actualDay + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestPersianYMDToJulianDay() {
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"),
|
||||
new ULocale("fa_IR@calendar=persian"));
|
||||
for (int i = 0; i < PERSIAN_TEST_CASE_1.length;) {
|
||||
int rd = PERSIAN_TEST_CASE_1[i++];
|
||||
int year = PERSIAN_TEST_CASE_1[i++];
|
||||
int month = PERSIAN_TEST_CASE_1[i++];
|
||||
int day = PERSIAN_TEST_CASE_1[i++];
|
||||
int jday = rd + 1721425;
|
||||
cal.clear();
|
||||
cal.set(Calendar.YEAR, year);
|
||||
cal.set(Calendar.MONTH, month-1);
|
||||
cal.set(Calendar.DAY_OF_MONTH, day);
|
||||
int actualJday = cal.get(Calendar.JULIAN_DAY);
|
||||
int actualRD = actualJday - 1721425;
|
||||
if (actualRD != rd) {
|
||||
errln("Fail: Persian(" + year + "/" + month + "/" + day + ") => "+
|
||||
"expect rd " + rd + " but actual jd: " + actualJday + " = rd " + actualRD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test data copy from
|
||||
// https://github.com/unicode-org/icu4x/blob/main/components/calendar/src/persian.rs#L534
|
||||
// From https://calendar.ut.ac.ir/Fa/News/Data/Doc/KabiseShamsi1206-1498-new.pdf
|
||||
// Plain text version at https://github.com/roozbehp/persiancalendar/blob/main/kabise.txt
|
||||
final int[] PERSIAN_TEST_CASE_2 = {
|
||||
// pYear, pLeap, year, month, day
|
||||
1206, 0, 1827, 3, 22,
|
||||
1207, 0, 1828, 3, 21,
|
||||
1208, 0, 1829, 3, 21,
|
||||
1209, 0, 1830, 3, 21,
|
||||
1210, 1, 1831, 3, 21,
|
||||
1211, 0, 1832, 3, 21,
|
||||
1212, 0, 1833, 3, 21,
|
||||
1213, 0, 1834, 3, 21,
|
||||
1214, 1, 1835, 3, 21,
|
||||
1215, 0, 1836, 3, 21,
|
||||
1216, 0, 1837, 3, 21,
|
||||
1217, 0, 1838, 3, 21,
|
||||
1218, 1, 1839, 3, 21,
|
||||
1219, 0, 1840, 3, 21,
|
||||
1220, 0, 1841, 3, 21,
|
||||
1221, 0, 1842, 3, 21,
|
||||
1222, 1, 1843, 3, 21,
|
||||
1223, 0, 1844, 3, 21,
|
||||
1224, 0, 1845, 3, 21,
|
||||
1225, 0, 1846, 3, 21,
|
||||
1226, 1, 1847, 3, 21,
|
||||
1227, 0, 1848, 3, 21,
|
||||
1228, 0, 1849, 3, 21,
|
||||
1229, 0, 1850, 3, 21,
|
||||
1230, 1, 1851, 3, 21,
|
||||
1231, 0, 1852, 3, 21,
|
||||
1232, 0, 1853, 3, 21,
|
||||
1233, 0, 1854, 3, 21,
|
||||
1234, 1, 1855, 3, 21,
|
||||
1235, 0, 1856, 3, 21,
|
||||
1236, 0, 1857, 3, 21,
|
||||
1237, 0, 1858, 3, 21,
|
||||
1238, 1, 1859, 3, 21,
|
||||
1239, 0, 1860, 3, 21,
|
||||
1240, 0, 1861, 3, 21,
|
||||
1241, 0, 1862, 3, 21,
|
||||
1242, 0, 1863, 3, 21,
|
||||
1243, 1, 1864, 3, 20,
|
||||
1244, 0, 1865, 3, 21,
|
||||
1245, 0, 1866, 3, 21,
|
||||
1246, 0, 1867, 3, 21,
|
||||
1247, 1, 1868, 3, 20,
|
||||
1248, 0, 1869, 3, 21,
|
||||
1249, 0, 1870, 3, 21,
|
||||
1250, 0, 1871, 3, 21,
|
||||
1251, 1, 1872, 3, 20,
|
||||
1252, 0, 1873, 3, 21,
|
||||
1253, 0, 1874, 3, 21,
|
||||
1254, 0, 1875, 3, 21,
|
||||
1255, 1, 1876, 3, 20,
|
||||
1256, 0, 1877, 3, 21,
|
||||
1257, 0, 1878, 3, 21,
|
||||
1258, 0, 1879, 3, 21,
|
||||
1259, 1, 1880, 3, 20,
|
||||
1260, 0, 1881, 3, 21,
|
||||
1261, 0, 1882, 3, 21,
|
||||
1262, 0, 1883, 3, 21,
|
||||
1263, 1, 1884, 3, 20,
|
||||
1264, 0, 1885, 3, 21,
|
||||
1265, 0, 1886, 3, 21,
|
||||
1266, 0, 1887, 3, 21,
|
||||
1267, 1, 1888, 3, 20,
|
||||
1268, 0, 1889, 3, 21,
|
||||
1269, 0, 1890, 3, 21,
|
||||
1270, 0, 1891, 3, 21,
|
||||
1271, 1, 1892, 3, 20,
|
||||
1272, 0, 1893, 3, 21,
|
||||
1273, 0, 1894, 3, 21,
|
||||
1274, 0, 1895, 3, 21,
|
||||
1275, 0, 1896, 3, 20,
|
||||
1276, 1, 1897, 3, 20,
|
||||
1277, 0, 1898, 3, 21,
|
||||
1278, 0, 1899, 3, 21,
|
||||
1279, 0, 1900, 3, 21,
|
||||
1280, 1, 1901, 3, 21,
|
||||
1281, 0, 1902, 3, 22,
|
||||
1282, 0, 1903, 3, 22,
|
||||
1283, 0, 1904, 3, 21,
|
||||
1284, 1, 1905, 3, 21,
|
||||
1285, 0, 1906, 3, 22,
|
||||
1286, 0, 1907, 3, 22,
|
||||
1287, 0, 1908, 3, 21,
|
||||
1288, 1, 1909, 3, 21,
|
||||
1289, 0, 1910, 3, 22,
|
||||
1290, 0, 1911, 3, 22,
|
||||
1291, 0, 1912, 3, 21,
|
||||
1292, 1, 1913, 3, 21,
|
||||
1293, 0, 1914, 3, 22,
|
||||
1294, 0, 1915, 3, 22,
|
||||
1295, 0, 1916, 3, 21,
|
||||
1296, 1, 1917, 3, 21,
|
||||
1297, 0, 1918, 3, 22,
|
||||
1298, 0, 1919, 3, 22,
|
||||
1299, 0, 1920, 3, 21,
|
||||
1300, 1, 1921, 3, 21,
|
||||
1301, 0, 1922, 3, 22,
|
||||
1302, 0, 1923, 3, 22,
|
||||
1303, 0, 1924, 3, 21,
|
||||
1304, 1, 1925, 3, 21,
|
||||
1305, 0, 1926, 3, 22,
|
||||
1306, 0, 1927, 3, 22,
|
||||
1307, 0, 1928, 3, 21,
|
||||
1308, 0, 1929, 3, 21,
|
||||
1309, 1, 1930, 3, 21,
|
||||
1310, 0, 1931, 3, 22,
|
||||
1311, 0, 1932, 3, 21,
|
||||
1312, 0, 1933, 3, 21,
|
||||
1313, 1, 1934, 3, 21,
|
||||
1314, 0, 1935, 3, 22,
|
||||
1315, 0, 1936, 3, 21,
|
||||
1316, 0, 1937, 3, 21,
|
||||
1317, 1, 1938, 3, 21,
|
||||
1318, 0, 1939, 3, 22,
|
||||
1319, 0, 1940, 3, 21,
|
||||
1320, 0, 1941, 3, 21,
|
||||
1321, 1, 1942, 3, 21,
|
||||
1322, 0, 1943, 3, 22,
|
||||
1323, 0, 1944, 3, 21,
|
||||
1324, 0, 1945, 3, 21,
|
||||
1325, 1, 1946, 3, 21,
|
||||
1326, 0, 1947, 3, 22,
|
||||
1327, 0, 1948, 3, 21,
|
||||
1328, 0, 1949, 3, 21,
|
||||
1329, 1, 1950, 3, 21,
|
||||
1330, 0, 1951, 3, 22,
|
||||
1331, 0, 1952, 3, 21,
|
||||
1332, 0, 1953, 3, 21,
|
||||
1333, 1, 1954, 3, 21,
|
||||
1334, 0, 1955, 3, 22,
|
||||
1335, 0, 1956, 3, 21,
|
||||
1336, 0, 1957, 3, 21,
|
||||
1337, 1, 1958, 3, 21,
|
||||
1338, 0, 1959, 3, 22,
|
||||
1339, 0, 1960, 3, 21,
|
||||
1340, 0, 1961, 3, 21,
|
||||
1341, 0, 1962, 3, 21,
|
||||
1342, 1, 1963, 3, 21,
|
||||
1343, 0, 1964, 3, 21,
|
||||
1344, 0, 1965, 3, 21,
|
||||
1345, 0, 1966, 3, 21,
|
||||
1346, 1, 1967, 3, 21,
|
||||
1347, 0, 1968, 3, 21,
|
||||
1348, 0, 1969, 3, 21,
|
||||
1349, 0, 1970, 3, 21,
|
||||
1350, 1, 1971, 3, 21,
|
||||
1351, 0, 1972, 3, 21,
|
||||
1352, 0, 1973, 3, 21,
|
||||
1353, 0, 1974, 3, 21,
|
||||
1354, 1, 1975, 3, 21,
|
||||
1355, 0, 1976, 3, 21,
|
||||
1356, 0, 1977, 3, 21,
|
||||
1357, 0, 1978, 3, 21,
|
||||
1358, 1, 1979, 3, 21,
|
||||
1359, 0, 1980, 3, 21,
|
||||
1360, 0, 1981, 3, 21,
|
||||
1361, 0, 1982, 3, 21,
|
||||
1362, 1, 1983, 3, 21,
|
||||
1363, 0, 1984, 3, 21,
|
||||
1364, 0, 1985, 3, 21,
|
||||
1365, 0, 1986, 3, 21,
|
||||
1366, 1, 1987, 3, 21,
|
||||
1367, 0, 1988, 3, 21,
|
||||
1368, 0, 1989, 3, 21,
|
||||
1369, 0, 1990, 3, 21,
|
||||
1370, 1, 1991, 3, 21,
|
||||
1371, 0, 1992, 3, 21,
|
||||
1372, 0, 1993, 3, 21,
|
||||
1373, 0, 1994, 3, 21,
|
||||
1374, 0, 1995, 3, 21,
|
||||
1375, 1, 1996, 3, 20,
|
||||
1376, 0, 1997, 3, 21,
|
||||
1377, 0, 1998, 3, 21,
|
||||
1378, 0, 1999, 3, 21,
|
||||
1379, 1, 2000, 3, 20,
|
||||
1380, 0, 2001, 3, 21,
|
||||
1381, 0, 2002, 3, 21,
|
||||
1382, 0, 2003, 3, 21,
|
||||
1383, 1, 2004, 3, 20,
|
||||
1384, 0, 2005, 3, 21,
|
||||
1385, 0, 2006, 3, 21,
|
||||
1386, 0, 2007, 3, 21,
|
||||
1387, 1, 2008, 3, 20,
|
||||
1388, 0, 2009, 3, 21,
|
||||
1389, 0, 2010, 3, 21,
|
||||
1390, 0, 2011, 3, 21,
|
||||
1391, 1, 2012, 3, 20,
|
||||
1392, 0, 2013, 3, 21,
|
||||
1393, 0, 2014, 3, 21,
|
||||
1394, 0, 2015, 3, 21,
|
||||
1395, 1, 2016, 3, 20,
|
||||
1396, 0, 2017, 3, 21,
|
||||
1397, 0, 2018, 3, 21,
|
||||
1398, 0, 2019, 3, 21,
|
||||
1399, 1, 2020, 3, 20,
|
||||
1400, 0, 2021, 3, 21,
|
||||
1401, 0, 2022, 3, 21,
|
||||
1402, 0, 2023, 3, 21,
|
||||
1403, 1, 2024, 3, 20,
|
||||
1404, 0, 2025, 3, 21,
|
||||
1405, 0, 2026, 3, 21,
|
||||
1406, 0, 2027, 3, 21,
|
||||
1407, 0, 2028, 3, 20,
|
||||
1408, 1, 2029, 3, 20,
|
||||
1409, 0, 2030, 3, 21,
|
||||
1410, 0, 2031, 3, 21,
|
||||
1411, 0, 2032, 3, 20,
|
||||
1412, 1, 2033, 3, 20,
|
||||
1413, 0, 2034, 3, 21,
|
||||
1414, 0, 2035, 3, 21,
|
||||
1415, 0, 2036, 3, 20,
|
||||
1416, 1, 2037, 3, 20,
|
||||
1417, 0, 2038, 3, 21,
|
||||
1418, 0, 2039, 3, 21,
|
||||
1419, 0, 2040, 3, 20,
|
||||
1420, 1, 2041, 3, 20,
|
||||
1421, 0, 2042, 3, 21,
|
||||
1422, 0, 2043, 3, 21,
|
||||
1423, 0, 2044, 3, 20,
|
||||
1424, 1, 2045, 3, 20,
|
||||
1425, 0, 2046, 3, 21,
|
||||
1426, 0, 2047, 3, 21,
|
||||
1427, 0, 2048, 3, 20,
|
||||
1428, 1, 2049, 3, 20,
|
||||
1429, 0, 2050, 3, 21,
|
||||
1430, 0, 2051, 3, 21,
|
||||
1431, 0, 2052, 3, 20,
|
||||
1432, 1, 2053, 3, 20,
|
||||
1433, 0, 2054, 3, 21,
|
||||
1434, 0, 2055, 3, 21,
|
||||
1435, 0, 2056, 3, 20,
|
||||
1436, 1, 2057, 3, 20,
|
||||
1437, 0, 2058, 3, 21,
|
||||
1438, 0, 2059, 3, 21,
|
||||
1439, 0, 2060, 3, 20,
|
||||
1440, 0, 2061, 3, 20,
|
||||
1441, 1, 2062, 3, 20,
|
||||
1442, 0, 2063, 3, 21,
|
||||
1443, 0, 2064, 3, 20,
|
||||
1444, 0, 2065, 3, 20,
|
||||
1445, 1, 2066, 3, 20,
|
||||
1446, 0, 2067, 3, 21,
|
||||
1447, 0, 2068, 3, 20,
|
||||
1448, 0, 2069, 3, 20,
|
||||
1449, 1, 2070, 3, 20,
|
||||
1450, 0, 2071, 3, 21,
|
||||
1451, 0, 2072, 3, 20,
|
||||
1452, 0, 2073, 3, 20,
|
||||
1453, 1, 2074, 3, 20,
|
||||
1454, 0, 2075, 3, 21,
|
||||
1455, 0, 2076, 3, 20,
|
||||
1456, 0, 2077, 3, 20,
|
||||
1457, 1, 2078, 3, 20,
|
||||
1458, 0, 2079, 3, 21,
|
||||
1459, 0, 2080, 3, 20,
|
||||
1460, 0, 2081, 3, 20,
|
||||
1461, 1, 2082, 3, 20,
|
||||
1462, 0, 2083, 3, 21,
|
||||
1463, 0, 2084, 3, 20,
|
||||
1464, 0, 2085, 3, 20,
|
||||
1465, 1, 2086, 3, 20,
|
||||
1466, 0, 2087, 3, 21,
|
||||
1467, 0, 2088, 3, 20,
|
||||
1468, 0, 2089, 3, 20,
|
||||
1469, 1, 2090, 3, 20,
|
||||
1470, 0, 2091, 3, 21,
|
||||
1471, 0, 2092, 3, 20,
|
||||
1472, 0, 2093, 3, 20,
|
||||
1473, 0, 2094, 3, 20,
|
||||
1474, 1, 2095, 3, 20,
|
||||
1475, 0, 2096, 3, 20,
|
||||
1476, 0, 2097, 3, 20,
|
||||
1477, 0, 2098, 3, 20,
|
||||
1478, 1, 2099, 3, 20,
|
||||
1479, 0, 2100, 3, 21,
|
||||
1480, 0, 2101, 3, 21,
|
||||
1481, 0, 2102, 3, 21,
|
||||
1482, 1, 2103, 3, 21,
|
||||
1483, 0, 2104, 3, 21,
|
||||
1484, 0, 2105, 3, 21,
|
||||
1485, 0, 2106, 3, 21,
|
||||
1486, 1, 2107, 3, 21,
|
||||
1487, 0, 2108, 3, 21,
|
||||
1488, 0, 2109, 3, 21,
|
||||
1489, 0, 2110, 3, 21,
|
||||
1490, 1, 2111, 3, 21,
|
||||
1491, 0, 2112, 3, 21,
|
||||
1492, 0, 2113, 3, 21,
|
||||
1493, 0, 2114, 3, 21,
|
||||
1494, 1, 2115, 3, 21,
|
||||
1495, 0, 2116, 3, 21,
|
||||
1496, 0, 2117, 3, 21,
|
||||
1497, 0, 2118, 3, 21,
|
||||
1498, 1, 2119, 3, 21,
|
||||
};
|
||||
|
||||
@Test
|
||||
public void TestPersianJan1ToGregorian() {
|
||||
Calendar gcal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"),
|
||||
new ULocale("en"));
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"),
|
||||
new ULocale("fa_IR@calendar=persian"));
|
||||
for (int i = 0; i < PERSIAN_TEST_CASE_2.length;) {
|
||||
int pYear = PERSIAN_TEST_CASE_2[i++];
|
||||
boolean pLeap = PERSIAN_TEST_CASE_2[i++] != 0;
|
||||
int year = PERSIAN_TEST_CASE_2[i++];
|
||||
int month = PERSIAN_TEST_CASE_2[i++];
|
||||
int day = PERSIAN_TEST_CASE_2[i++];
|
||||
cal.clear();
|
||||
cal.set(Calendar.YEAR, pYear);
|
||||
cal.set(Calendar.MONTH, 0);
|
||||
cal.set(Calendar.DAY_OF_MONTH, 1);
|
||||
gcal.setTime(cal.getTime());
|
||||
int actualYear = gcal.get(Calendar.YEAR);
|
||||
int actualMonth = gcal.get(Calendar.MONTH)+1;
|
||||
int actualDay = gcal.get(Calendar.DAY_OF_MONTH);
|
||||
if (actualYear != year || actualMonth != month || actualDay != day) {
|
||||
errln("Fail: Persian(" + pYear + ", 1, 1) => " +
|
||||
"expect Gregorian(" + year + "/" + month + "/" + day + ") " +
|
||||
"actual Gregorian(" + actualYear + "/" + actualMonth + "/" + actualDay + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestGregorianToPersian() {
|
||||
Calendar gcal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"),
|
||||
new ULocale("en"));
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"),
|
||||
new ULocale("fa_IR@calendar=persian"));
|
||||
for (int i = 0; i < PERSIAN_TEST_CASE_2.length;) {
|
||||
int pYear = PERSIAN_TEST_CASE_2[i++];
|
||||
boolean pLeap = PERSIAN_TEST_CASE_2[i++] != 0;
|
||||
int year = PERSIAN_TEST_CASE_2[i++];
|
||||
int month = PERSIAN_TEST_CASE_2[i++];
|
||||
int day = PERSIAN_TEST_CASE_2[i++];
|
||||
gcal.clear();
|
||||
gcal.set(Calendar.YEAR, year);
|
||||
gcal.set(Calendar.MONTH, month-1);
|
||||
gcal.set(Calendar.DAY_OF_MONTH, day);
|
||||
cal.setTime(gcal.getTime());
|
||||
int persianYear = cal.get(Calendar.YEAR);
|
||||
int persianMonth = cal.get(Calendar.MONTH)+1;
|
||||
int persianDay = cal.get(Calendar.DAY_OF_MONTH);
|
||||
if (persianYear != pYear || persianMonth != 1 || persianDay != 1) {
|
||||
errln("Fail: Gregorian(" + year + "/" + month + "/" + day + ") "+
|
||||
" => expect Persian(" + pYear + "/1/1) actual " +
|
||||
"Persian(" + persianYear + "/" + persianMonth + "/" + persianDay + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue