ICU-2436 Japanese Calendar implementation, other fixes (multi calendar)

X-SVN-Rev: 12105
This commit is contained in:
Steven R. Loomis 2003-05-25 07:12:19 +00:00
parent 1b1cf58c46
commit f2e4031b0c
16 changed files with 1265 additions and 217 deletions

View file

@ -2543,4 +2543,257 @@ ja {
ZAR { "ZAR", "\u30E9\u30F3\u30C9" } // Rand
ZWD { "ZWD", "\u30B8\u30F3\u30D0\u30D6\u30A8 \u30C9\u30EB" } // Zimbabwe Dollar
}
// (ICU 2.6) International Calendar Data. Note, THE FORMAT OF THIS DATA WILL CHANGE IN FUTURE RELEASES.
Eras_japanese {
"\u5927\u5316", // 645 Taika
"\u767D\u96C9", // 650 Hakuchi
"\u767D\u9CEF", // 672 Hakuho
"\u6731\u9CE5", // 686 Shucho
"\u5927\u5B9D", // 701 Taiho
"\u6176\u96F2", // 704 Keiun
"\u548C\u9285", // 708 Wado
"\u970A\u4E80", // 715 Reiki
"\u990A\u8001", // 717 Yoro
"\u795E\u4E80", // 724 Jinki
"\u5929\u5E73", // 729 Tempyo
"\u5929\u5E73\u611F\u5B9D", // 749 Tempyo-kampo
"\u5929\u5E73\u52DD\u5B9D", // 749 Tempyo-shoho
"\u5929\u5E73\u5B9D\u5B57", // 757 Tempyo-hoji
"\u5929\u5E73\u795E\u8B77", // 765 Tempho-jingo
"\u795E\u8B77\u666F\u96F2", // 767 Jingo-keiun
"\u5B9D\u4E80", // 770 Hoki
"\u5929\u5FDC", // 781 Ten-o
"\u5EF6\u66A6", // 782 Enryaku
"\u5927\u540C", // 806 Daido
"\u5F18\u4EC1", // 810 Konin
"\u5929\u9577", // 824 Tencho
"\u627F\u548C", // 834 Showa
"\u5609\u7965", // 848 Kajo
"\u4EC1\u5BFF", // 851 Ninju
"\u6589\u8861", // 854 Saiko
"\u5929\u5B89", // 857 Tennan
"\u8C9E\u89B3", // 859 Jogan
"\u5143\u6176", // 877 Genkei
"\u4EC1\u548C", // 885 Ninna
"\u5BDB\u5E73", // 889 Kampyo
"\u660C\u6CF0", // 898 Shotai
"\u5EF6\u559C", // 901 Engi
"\u5EF6\u9577", // 923 Encho
"\u627F\u5E73", // 931 Shohei
"\u5929\u6176", // 938 Tengyo
"\u5929\u66A6", // 947 Tenryaku
"\u5929\u5FB3", // 957 Tentoku
"\u5FDC\u548C", // 961 Owa
"\u5EB7\u4FDD", // 964 Koho
"\u5B89\u548C", // 968 Anna
"\u5929\u7984", // 970 Tenroku
"\u5929\u5EF6", // 973 Ten-en
"\u8C9E\u5143", // 976 Jogen
"\u5929\u5143", // 978 Tengen
"\u6C38\u89B3", // 983 Eikan
"\u5BDB\u548C", // 985 Kanna
"\u6C38\u5EF6", // 987 Ei-en
"\u6C38\u795A", // 989 Eiso
"\u6B63\u66A6", // 990 Shoryaku
"\u9577\u5FB3", // 995 Chotoku
"\u9577\u4FDD", // 999 Choho
"\u5BDB\u5F18", // 1004 Kanko
"\u9577\u548C", // 1012 Chowa
"\u5BDB\u4EC1", // 1017 Kannin
"\u6CBB\u5B89", // 1021 Jian
"\u4E07\u5BFF", // 1024 Manju
"\u9577\u5143", // 1028 Chogen
"\u9577\u66A6", // 1037 Choryaku
"\u9577\u4E45", // 1040 Chokyu
"\u5BDB\u5FB3", // 1044 Kantoku
"\u6C38\u627F", // 1046 Eisho
"\u5929\u559C", // 1053 Tengi
"\u5EB7\u5E73", // 1058 Kohei
"\u6CBB\u66A6", // 1065 Jiryaku
"\u5EF6\u4E45", // 1069 Enkyu
"\u627F\u4FDD", // 1074 Shoho
"\u627F\u66A6", // 1077 Shoryaku
"\u6C38\u4FDD", // 1081 Eiho
"\u5FDC\u5FB3", // 1084 Otoku
"\u5BDB\u6CBB", // 1087 Kanji
"\u5609\u4FDD", // 1094 Kaho
"\u6C38\u9577", // 1096 Eicho
"\u627F\u5FB3", // 1097 Shotoku
"\u5EB7\u548C", // 1099 Kowa
"\u9577\u6CBB", // 1104 Choji
"\u5609\u627F", // 1106 Kasho
"\u5929\u4EC1", // 1108 Tennin
"\u5929\u6C38", // 1110 Ten-ei
"\u6C38\u4E45", // 1113 Eikyu
"\u5143\u6C38", // 1118 Gen-ei
"\u4FDD\u5B89", // 1120 Hoan
"\u5929\u6CBB", // 1124 Tenji
"\u5927\u6CBB", // 1126 Daiji
"\u5929\u627F", // 1131 Tensho
"\u9577\u627F", // 1132 Chosho
"\u4FDD\u5EF6", // 1135 Hoen
"\u6C38\u6CBB", // 1141 Eiji
"\u5EB7\u6CBB", // 1142 Koji
"\u5929\u990A", // 1144 Tenyo
"\u4E45\u5B89", // 1145 Kyuan
"\u4EC1\u5E73", // 1151 Ninpei
"\u4E45\u5BFF", // 1154 Kyuju
"\u4FDD\u5143", // 1156 Hogen
"\u5E73\u6CBB", // 1159 Heiji
"\u6C38\u66A6", // 1160 Eiryaku
"\u5FDC\u4FDD", // 1161 Oho
"\u9577\u5BDB", // 1163 Chokan
"\u6C38\u4E07", // 1165 Eiman
"\u4EC1\u5B89", // 1166 Nin-an
"\u5609\u5FDC", // 1169 Kao
"\u627F\u5B89", // 1171 Shoan
"\u5B89\u5143", // 1175 Angen
"\u6CBB\u627F", // 1177 Jisho
"\u990A\u548C", // 1181 Yowa
"\u5BFF\u6C38", // 1182 Juei
"\u5143\u66A6", // 1184 Genryuku
"\u6587\u6CBB", // 1185 Bunji
"\u5EFA\u4E45", // 1190 Kenkyu
"\u6B63\u6CBB", // 1199 Shoji
"\u5EFA\u4EC1", // 1201 Kennin
"\u5143\u4E45", // 1204 Genkyu
"\u5EFA\u6C38", // 1206 Ken-ei
"\u627F\u5143", // 1207 Shogen
"\u5EFA\u66A6", // 1211 Kenryaku
"\u5EFA\u4FDD", // 1213 Kenpo
"\u627F\u4E45", // 1219 Shokyu
"\u8C9E\u5FDC", // 1222 Joo
"\u5143\u4EC1", // 1224 Gennin
"\u5609\u7984", // 1225 Karoku
"\u5B89\u8C9E", // 1227 Antei
"\u5BDB\u559C", // 1229 Kanki
"\u8C9E\u6C38", // 1232 Joei
"\u5929\u798F", // 1233 Tempuku
"\u6587\u66A6", // 1234 Bunryaku
"\u5609\u798E", // 1235 Katei
"\u66A6\u4EC1", // 1238 Ryakunin
"\u5EF6\u5FDC", // 1239 En-o
"\u4EC1\u6CBB", // 1240 Ninji
"\u5BDB\u5143", // 1243 Kangen
"\u5B9D\u6CBB", // 1247 Hoji
"\u5EFA\u9577", // 1249 Kencho
"\u5EB7\u5143", // 1256 Kogen
"\u6B63\u5609", // 1257 Shoka
"\u6B63\u5143", // 1259 Shogen
"\u6587\u5FDC", // 1260 Bun-o
"\u5F18\u9577", // 1261 Kocho
"\u6587\u6C38", // 1264 Bun-ei
"\u5EFA\u6CBB", // 1275 Kenji
"\u5F18\u5B89", // 1278 Koan
"\u6B63\u5FDC", // 1288 Shoo
"\u6C38\u4EC1", // 1293 Einin
"\u6B63\u5B89", // 1299 Shoan
"\u4E7E\u5143", // 1302 Kengen
"\u5609\u5143", // 1303 Kagen
"\u5FB3\u6CBB", // 1306 Tokuji
"\u5EF6\u6176", // 1308 Enkei
"\u5FDC\u9577", // 1311 Ocho
"\u6B63\u548C", // 1312 Showa
"\u6587\u4FDD", // 1317 Bunpo
"\u5143\u5FDC", // 1319 Geno
"\u5143\u4EA8", // 1321 Genkyo
"\u6B63\u4E2D", // 1324 Shochu
"\u5609\u66A6", // 1326 Kareki
"\u5143\u5FB3", // 1329 Gentoku
"\u5143\u5F18", // 1331 Genko
"\u5EFA\u6B66", // 1334 Kemmu
"\u5EF6\u5143", // 1336 Engen
"\u8208\u56FD", // 1340 Kokoku
"\u6B63\u5E73", // 1346 Shohei
"\u5EFA\u5FB3", // 1370 Kentoku
"\u6587\u4E2D", // 1372 Bunchu
"\u5929\u6388", // 1375 Tenju
"\u5F18\u548C", // 1381 Kowa
"\u5143\u4E2D", // 1384 Genchu
"\u81F3\u5FB3", // 1384 Meitoku
"\u5EB7\u66A6", // 1379 Koryaku
"\u5609\u6176", // 1387 Kakei
"\u5EB7\u5FDC", // 1389 Koo
"\u660E\u5FB3", // 1390 Meitoku
"\u5FDC\u6C38", // 1394 Oei
"\u6B63\u9577", // 1428 Shocho
"\u6C38\u4EAB", // 1429 Eikyo
"\u5609\u5409", // 1441 Kakitsu
"\u6587\u5B89", // 1444 Bun-an
"\u5B9D\u5FB3", // 1449 Hotoku
"\u4EAB\u5FB3", // 1452 Kyotoku
"\u5EB7\u6B63", // 1455 Kosho
"\u9577\u7984", // 1457 Choroku
"\u5BDB\u6B63", // 1460 Kansho
"\u6587\u6B63", // 1466 Bunsho
"\u5FDC\u4EC1", // 1467 Onin
"\u6587\u660E", // 1469 Bunmei
"\u9577\u4EAB", // 1487 Chokyo
"\u5EF6\u5FB3", // 1489 Entoku
"\u660E\u5FDC", // 1492 Meio
"\u6587\u4E80", // 1501 Bunki
"\u6C38\u6B63", // 1504 Eisho
"\u5927\u6C38", // 1521 Taiei
"\u4EAB\u7984", // 1528 Kyoroku
"\u5929\u6587", // 1532 Tenmon
"\u5F18\u6CBB", // 1555 Koji
"\u6C38\u7984", // 1558 Eiroku
"\u5143\u4E80", // 1570 Genki
"\u5929\u6B63", // 1573 Tensho
"\u6587\u7984", // 1592 Bunroku
"\u6176\u9577", // 1596 Keicho
"\u5143\u548C", // 1615 Genwa
"\u5BDB\u6C38", // 1624 Kan-ei
"\u6B63\u4FDD", // 1644 Shoho
"\u6176\u5B89", // 1648 Keian
"\u627F\u5FDC", // 1652 Shoo
"\u660E\u66A6", // 1655 Meiryaku
"\u4E07\u6CBB", // 1658 Manji
"\u5BDB\u6587", // 1661 Kanbun
"\u5EF6\u5B9D", // 1673 Enpo
"\u5929\u548C", // 1681 Tenwa
"\u8C9E\u4EAB", // 1684 Jokyo
"\u5143\u7984", // 1688 Genroku
"\u5B9D\u6C38", // 1704 Hoei
"\u6B63\u5FB3", // 1711 Shotoku
"\u4EAB\u4FDD", // 1716 Kyoho
"\u5143\u6587", // 1736 Genbun
"\u5BDB\u4FDD", // 1741 Kanpo
"\u5EF6\u4EAB", // 1744 Enkyo
"\u5BDB\u5EF6", // 1748 Kan-en
"\u5B9D\u66A6", // 1751 Horyaku
"\u660E\u548C", // 1764 Meiwa
"\u5B89\u6C38", // 1772 An-ei
"\u5929\u660E", // 1781 Tenmei
"\u5BDB\u653F", // 1789 Kansei
"\u4EAB\u548C", // 1801 Kyowa
"\u6587\u5316", // 1804 Bunka
"\u6587\u653F", // 1818 Bunsei
"\u5929\u4FDD", // 1830 Tenpo
"\u5F18\u5316", // 1844 Koka
"\u5609\u6C38", // 1848 Kaei
"\u5B89\u653F", // 1854 Ansei
"\u4E07\u5EF6", // 1860 Man-en
"\u6587\u4E45", // 1861 Bunkyu
"\u5143\u6CBB", // 1864 Genji
"\u6176\u5FDC", // 1865 Keio
"\u660E\u6CBB", // 1868 Meiji
"\u5927\u6B63", // 1912 Taisho
"\u662D\u548C", // 1926 Showa
"\u5E73\u6210" // 1989 Heisei
}
DateTimePatterns_japanese {
"H'\u6642'mm'\u5206'ss'\u79D2'z",
"H:mm:ss:z",
"H:mm:ss",
"H:mm",
"yyyy G'\u5E74'M'\u6708'd'\u65E5'",
"yyyy G/MM/dd",
"yyyy G/MM/dd",
"yyyy G/MM/dd",
"{1} {0}",
}
}

View file

@ -0,0 +1,14 @@
// ***************************************************************************
// *
// * Copyright (C) 1997-2003, International Business Machines
// * Corporation and others. All Rights Reserved.
// *
// ***************************************************************************
ja_JP_TRADITIONAL {
Version { "1.0" }
// International Calendars Data.
// NOTE (ICU 2.6) - the format of this data WILL CHANGE in future releases.
DefaultCalendar { "japanese" }
}

View file

@ -76,7 +76,7 @@ hy.txt hy_AM.txt hy_AM_REVISED.txt\
id.txt id_ID.txt\
is.txt is_IS.txt\
it.txt it_CH.txt it_IT.txt it_IT_PREEURO.txt\
ja.txt ja_JP.txt\
ja.txt ja_JP.txt ja_JP_TRADITIONAL.txt\
kl.txt kl_GL.txt\
ko.txt ko_KR.txt\
kok.txt kok_IN.txt\

View file

@ -8,6 +8,8 @@
// 11/17/99 aliu Added support for transliterators.
// 01/15/2002 grhoten Synchronized the language and contry codes with ISO standards
// *** Note: do NOT translate or modify (customize) this root locale.
// Instead, put translations in sub locales.
root {
Version { "3.2" }
@ -1606,9 +1608,34 @@ root {
"Heisei", // 1989
}
DateTimePatterns_japanese:array {
"h:mm:ss a z", // full time pattern
"h:mm:ss a z", // long time pattern
"h:mm:ss a", // medium time pattern
"h:mm a", // short time pattern
"EEEE, MMMM d, y G", // full date pattern
"MMMM d, y G", // long date pattern
"MMM d, y G", // medium date pattern
"M/d/yy", // short date pattern
"{1} {0}" // date-time pattern
}
// Buddhist calendar data
Eras_buddhist:array {
"BE" // Buddhist Era = 543 BC Gregorian
}
DateTimePatterns_buddhist { // shorten year, use Era
"h:mm:ss a z",
"h:mm:ss a z",
"h:mm:ss a",
"h:mm a",
"EEEE, MMMM d, y G",
"MMMM d, y G",
"MMM d, y G",
"M/d/y",
"{1} {0}",
}
}

View file

@ -27,6 +27,8 @@ static const int32_t kMaxEra = 0; // only 1 era
static const int32_t kBuddhistEraStart = -543; // 544 BC (Gregorian)
static const int32_t kGregorianEpoch = 1970;
BuddhistCalendar::BuddhistCalendar(const Locale& aLocale, UErrorCode& success)
: GregorianCalendar(aLocale, success)
{
@ -108,15 +110,15 @@ int32_t BuddhistCalendar::internalGetEra() const
}
int32_t
BuddhistCalendar::getGregorianYear(UErrorCode &status)
BuddhistCalendar::getGregorianYear(UErrorCode &status) const
{
int32_t year = (fStamp[UCAL_YEAR] != kUnset) ? internalGet(UCAL_YEAR) : 1970+kBuddhistEraStart;
int32_t year = (fStamp[UCAL_YEAR] != kUnset) ? internalGet(UCAL_YEAR) : kGregorianEpoch+kBuddhistEraStart;
int32_t era = BE;
if (fStamp[UCAL_ERA] != kUnset) {
era = internalGet(UCAL_ERA);
if (era != BE) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 1970 + kBuddhistEraStart;
return kGregorianEpoch + kBuddhistEraStart;
}
}
return year + kBuddhistEraStart;
@ -144,6 +146,10 @@ void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& stat
internalSet(UCAL_YEAR, year);
}
UBool BuddhistCalendar::haveDefaultCentury() const
{
return FALSE;
}
U_NAMESPACE_END

View file

@ -137,11 +137,12 @@ private:
protected:
virtual int32_t monthLength(int32_t month) const;
virtual int32_t monthLength(int32_t month, int32_t year) const;
int32_t getGregorianYear(UErrorCode& status);
int32_t getGregorianYear(UErrorCode& status) const;
int32_t getMaximum(UCalendarDateFields field) const;
int32_t getLeastMaximum(UCalendarDateFields field) const;
virtual int32_t internalGetEra() const;
virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
virtual UBool haveDefaultCentury() const;
};
inline UClassID

View file

@ -36,6 +36,7 @@
#include "cpputils.h"
#include "iculserv.h"
#include "ucln_in.h"
#include "cstring.h"
U_NAMESPACE_BEGIN
@ -51,10 +52,6 @@ U_NAMESPACE_BEGIN
#include <stdio.h>
#endif
// do NOT force a 'getService' (and thus, registration).
// Define this if you do NOT want automatic registration.
//#define U_DEBUG_CALSVC_NO_GETSVC 1
static ICULocaleService* gService = NULL;
// -------------------------------------
@ -113,11 +110,11 @@ protected:
fflush(stderr);
#endif
if(!fType || !*fType || !strcmp(fType,"gregorian")) { // Gregorian (default)
if(!fType || !*fType || !uprv_strcmp(fType,"gregorian")) { // Gregorian (default)
return new GregorianCalendar(canLoc, status);
} else if(!strcmp(fType, "japanese")) {
} else if(!uprv_strcmp(fType, "japanese")) {
return new JapaneseCalendar(canLoc, status);
} else if(!strcmp(fType, "buddhist")) {
} else if(!uprv_strcmp(fType, "buddhist")) {
return new BuddhistCalendar(canLoc, status);
} else {
status = U_UNSUPPORTED_ERROR;
@ -169,9 +166,12 @@ protected:
int32_t len = 0;
const UChar *defCal = ures_getStringByKey(rb, Calendar::kDefaultCalendar, &len, &status);
UnicodeString myString = ures_getUnicodeStringByKey(rb, Calendar::kDefaultCalendar, &status);
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "... get string(%d) -> %s\n", len, u_errorName(status));
UErrorCode debugStatus = U_ZERO_ERROR;
const UChar *defCal = ures_getStringByKey(rb, Calendar::kDefaultCalendar, &len, &debugStatus);
fprintf(stderr, "... get string(%d) -> %s\n", len, u_errorName(debugStatus));
#endif
ures_close(rb);
@ -180,18 +180,20 @@ protected:
return NULL;
}
char defCalStr[200];
if(len > 199) {
len = 199;
}
u_UCharsToChars(defCal, defCalStr, len);
defCalStr[len]=0;
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "DefaultCalendarFactory: looked up %s, got DefaultCalendar= %s\n", (const char*)loc.getName(), defCalStr);
{
char defCalStr[200];
if(len > 199) {
len = 199;
}
u_UCharsToChars(defCal, defCalStr, len);
defCalStr[len]=0;
fprintf(stderr, "DefaultCalendarFactory: looked up %s, got DefaultCalendar= %s\n", (const char*)loc.getName(), defCalStr);
}
#endif
return new UnicodeString(defCalStr,""); // Return indirection string
return myString.clone();
}
};
@ -483,12 +485,14 @@ Calendar::createInstance(const Locale& aLocale, UErrorCode& success)
Calendar*
Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& success)
{
// to do - put back non-service code.
UObject* u = getService()->get(aLocale, LocaleKey::KIND_ANY, success);
Calendar* c = NULL;
if(U_FAILURE(success) || !u) {
delete zone;
if(U_SUCCESS(success)) { // Propagate some kind of err
success = U_INTERNAL_PROGRAM_ERROR;
}
return NULL;
}
@ -496,11 +500,10 @@ Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
// It's a unicode string telling us what type of calendar to load ("gregorian", etc)
char tmp[200];
const UnicodeString& str = *(UnicodeString*)u;
// Extract a char* out of it..
int32_t len = str.length();
if(len > 198) {
len = 198;
if(len > sizeof(tmp)-1) {
len = sizeof(tmp)-1;
}
str.extract(0,len,tmp);
tmp[len]=0;
@ -509,24 +512,27 @@ Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
// fprintf(stderr, "createInstance(%s) told to look at %s..\n", (const char*)aLocale.getName(), tmp);
#endif
// Create a Locale
Locale l(tmp,"");
// Create a Locale over this string
Locale l(tmp);
delete u;
u = NULL;
c = (Calendar*)getService()->get(l, LocaleKey::KIND_ANY, success);
if(U_FAILURE(success) || !c) {
delete zone;
//delete u;
if(U_SUCCESS(success)) {
success = U_INTERNAL_PROGRAM_ERROR; // Propagate some err
}
return NULL;
}
if(c->getDynamicClassID() == UnicodeString::getStaticClassID()) {
// recursed!
// recursed! Second lookup returned a UnicodeString.
// Perhaps DefaultCalendar{} was set to another locale.
success = U_MISSING_RESOURCE_ERROR; // requested a calendar type which could NOT be found.
delete c;
//delete u;
delete zone;
return NULL;
}
@ -535,7 +541,7 @@ Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
#endif
c->setWeekCountData(aLocale, success); // set the correct locale (this was an indirected calendar)
} else {
// calendar was returned
// a calendar was returned - we assume the factory did the right thing.
c = (Calendar*)u;
}
c->adoptTimeZone(zone); // Set the correct time zone
@ -547,26 +553,11 @@ Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
Calendar*
Calendar::createInstance(const TimeZone& zone, const Locale& aLocale, UErrorCode& success)
{
#ifndef U_DEBUG_CALSVC_NO_GETSVC
getService();
#endif
if(gService != NULL) {
Calendar* c = createInstance(aLocale, success);
if(U_SUCCESS(success) && c) {
c->setTimeZone(zone);
}
return c;
} else {
// non service code
Calendar* c = new GregorianCalendar(zone, aLocale, success);
/* test for NULL */
if (c == 0) {
success = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
if (U_FAILURE(success)) { delete c; c = 0; }
return c;
Calendar* c = createInstance(aLocale, success);
if(U_SUCCESS(success) && c) {
c->setTimeZone(zone);
}
return c;
}
// -------------------------------------

View file

@ -38,10 +38,12 @@
*/
#include "unicode/utypes.h"
#include <float.h>
#if !UCONFIG_NO_FORMATTING
#include "unicode/gregocal.h"
#include "unicode/smpdtfmt.h" /* for the public field (!) SimpleDateFormat::fgSystemDefaultCentury */
// *****************************************************************************
// class GregorianCalendar
@ -780,7 +782,7 @@ GregorianCalendar::getEpochDay(UErrorCode& status)
// -------------------------------------
int32_t
GregorianCalendar::getGregorianYear(UErrorCode &status)
GregorianCalendar::getGregorianYear(UErrorCode &status) const
{
int32_t year = (fStamp[UCAL_YEAR] != kUnset) ? internalGet(UCAL_YEAR) : kEpochYear;
int32_t era = AD;
@ -1171,7 +1173,7 @@ GregorianCalendar::computeJulianDay(UBool isGregorian, int32_t year)
// predominates. This set of computations must be done BEFORE
// using the year, since the year value may be adjusted here.
UBool useMonth = FALSE;
int32_t month = 0;
int32_t month = 0; // SRL getDefaultMonth ?
if (bestStamp != kUnset &&
(bestStamp == monthStamp ||
bestStamp == domStamp ||
@ -1180,7 +1182,7 @@ GregorianCalendar::computeJulianDay(UBool isGregorian, int32_t year)
useMonth = TRUE;
// We have the month specified. Make it 0-based for the algorithm.
month = (monthStamp != kUnset) ? internalGet(UCAL_MONTH) - UCAL_JANUARY : 0;
month = (monthStamp != kUnset) ? internalGet(UCAL_MONTH) - UCAL_JANUARY : getDefaultMonthInYear();
// If the month is out of range, adjust it into range
if (month < 0 || month > 11) {
@ -1205,7 +1207,7 @@ GregorianCalendar::computeJulianDay(UBool isGregorian, int32_t year)
if (bestStamp == domStamp ||
bestStamp == monthStamp) {
date = (domStamp != kUnset) ? internalGet(UCAL_DATE) : 1;
date = (domStamp != kUnset) ? internalGet(UCAL_DATE) : getDefaultDayInMonth(month);
}
else { // assert(bestStamp == womStamp || bestStamp == dowimStamp)
// Compute from day of week plus week number or from the day of
@ -1267,8 +1269,13 @@ GregorianCalendar::computeJulianDay(UBool isGregorian, int32_t year)
UBool doCutoverAdjustment = TRUE;
if (bestStamp == kUnset) {
doy = 1; // Advance to January 1
doCutoverAdjustment = FALSE;
//doy = 1;
// For Gregorian the following will always be 1: kNumDays[UCAL_JANUARY] + 1
int32_t defMonth = getDefaultMonthInYear(); // 0 for gregorian
int32_t defDay = getDefaultDayInMonth(month); // 1 for gregorian
doy = defDay + (isLeap ? kLeapNumDays[defMonth] : kNumDays[defMonth]);
doCutoverAdjustment = FALSE;
}
else if (bestStamp == doyStamp) {
doy = internalGet(UCAL_DAY_OF_YEAR);
@ -2075,6 +2082,82 @@ GregorianCalendar::getType() const {
return "gregorian";
}
// ------ Default Century functions moved here from SimpleDateFormat
// uncomment in 2.8
//const UDate GregorianCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t GregorianCalendar::fgSystemDefaultCenturyYear = -1;
UDate GregorianCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t GregorianCalendar::fgSystemDefaultCenturyStartYear = -1;
UBool GregorianCalendar::haveDefaultCentury() const
{
return TRUE;
}
UDate GregorianCalendar::defaultCenturyStart() const
{
return internalGetDefaultCenturyStart();
}
int32_t GregorianCalendar::defaultCenturyStartYear() const
{
return internalGetDefaultCenturyStartYear();
}
UDate
GregorianCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
if (fgSystemDefaultCenturyStart == SimpleDateFormat::fgSystemDefaultCentury)
initializeSystemDefaultCentury();
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
}
int32_t
GregorianCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
if (fgSystemDefaultCenturyStart == SimpleDateFormat::fgSystemDefaultCentury)
initializeSystemDefaultCentury();
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
return fgSystemDefaultCenturyStartYear;
}
void
GregorianCalendar::initializeSystemDefaultCentury()
{
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
// the current time.
// No point in locking as it should be idempotent.
if (fgSystemDefaultCenturyStart == SimpleDateFormat::fgSystemDefaultCentury)
{
UErrorCode status = U_ZERO_ERROR;
Calendar *calendar = new GregorianCalendar(status);
if (calendar != NULL && U_SUCCESS(status))
{
calendar->setTime(Calendar::getNow(), status);
calendar->add(UCAL_YEAR, -80, status);
fgSystemDefaultCenturyStart = calendar->getTime(status);
fgSystemDefaultCenturyStartYear = calendar->get(UCAL_YEAR, status);
delete calendar;
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
}
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2003, International Business Machines Corporation and *
* Copyright (C) 2003, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -18,17 +18,269 @@
#include "japancal.h"
#include "unicode/gregocal.h"
//#define U_DEBUG_JCAL
#ifdef U_DEBUG_JCAL
#include <stdio.h>
#endif
U_NAMESPACE_BEGIN
const char JapaneseCalendar::fgClassID = 0; // Value is irrelevant
// Gregorian date of each emperor's ascension
// Years are AD, months are 1-based.
static const struct {
int16_t year;
int8_t month;
int8_t day;
} kEraInfo[] = {
// Year Month Day
{ 645, 6, 19 }, // Taika 0
{ 650, 2, 15 }, // Hakuchi 1
{ 672, 1, 1 }, // Hakuho 2
{ 686, 7, 20 }, // Shucho 3
{ 701, 3, 21 }, // Taiho 4
{ 704, 5, 10 }, // Keiun 5
{ 708, 1, 11 }, // Wado 6
{ 715, 9, 2 }, // Reiki 7
{ 717, 11, 17 }, // Yoro 8
{ 724, 2, 4 }, // Jinki 9
{ 729, 8, 5 }, // Tempyo 10
{ 749, 4, 14 }, // Tempyo-kampo 11
{ 749, 7, 2 }, // Tempyo-shoho 12
{ 757, 8, 18 }, // Tempyo-hoji 13
{ 765, 1, 7 }, // Tempho-jingo 14
{ 767, 8, 16 }, // Jingo-keiun 15
{ 770, 10, 1 }, // Hoki 16
{ 781, 1, 1 }, // Ten-o 17
{ 782, 8, 19 }, // Enryaku 18
{ 806, 5, 18 }, // Daido 19
{ 810, 9, 19 }, // Konin 20
{ 824, 1, 5 }, // Tencho
{ 834, 1, 3 }, // Showa
{ 848, 6, 13 }, // Kajo
{ 851, 4, 28 }, // Ninju
{ 854, 11, 30 }, // Saiko
{ 857, 2, 21 }, // Tennan
{ 859, 4, 15 }, // Jogan
{ 877, 4, 16 }, // Genkei
{ 885, 2, 21 }, // Ninna
{ 889, 4, 27 }, // Kampyo 30
{ 898, 4, 26 }, // Shotai
{ 901, 7, 15 }, // Engi
{ 923, 4, 11 }, // Encho
{ 931, 4, 26 }, // Shohei
{ 938, 5, 22 }, // Tengyo
{ 947, 4, 22 }, // Tenryaku
{ 957, 10, 27 }, // Tentoku
{ 961, 2, 16 }, // Owa
{ 964, 7, 10 }, // Koho
{ 968, 8, 13 }, // Anna 40
{ 970, 3, 25 }, // Tenroku
{ 973, 12, 20 }, // Ten-en
{ 976, 7, 13 }, // Jogen
{ 978, 11, 29 }, // Tengen
{ 983, 4, 15 }, // Eikan
{ 985, 4, 27 }, // Kanna
{ 987, 4, 5 }, // Ei-en
{ 989, 8, 8 }, // Eiso
{ 990, 11, 7 }, // Shoryaku
{ 995, 2, 22 }, // Chotoku 50
{ 999, 1, 13 }, // Choho
{ 1004, 7, 20 }, // Kanko
{ 1012, 12, 25 }, // Chowa
{ 1017, 4, 23 }, // Kannin
{ 1021, 2, 2 }, // Jian
{ 1024, 7, 13 }, // Manju
{ 1028, 7, 25 }, // Chogen
{ 1037, 4, 21 }, // Choryaku
{ 1040, 11, 10 }, // Chokyu
{ 1044, 11, 24 }, // Kantoku 60
{ 1046, 4, 14 }, // Eisho
{ 1053, 1, 11 }, // Tengi
{ 1058, 8, 29 }, // Kohei
{ 1065, 8, 2 }, // Jiryaku
{ 1069, 4, 13 }, // Enkyu
{ 1074, 8, 23 }, // Shoho
{ 1077, 11, 17 }, // Shoryaku
{ 1081, 2, 10 }, // Eiho
{ 1084, 2, 7 }, // Otoku
{ 1087, 4, 7 }, // Kanji 70
{ 1094, 12, 15 }, // Kaho
{ 1096, 12, 17 }, // Eicho
{ 1097, 11, 21 }, // Shotoku
{ 1099, 8, 28 }, // Kowa
{ 1104, 2, 10 }, // Choji
{ 1106, 4, 9 }, // Kasho
{ 1108, 8, 3 }, // Tennin
{ 1110, 7, 13 }, // Ten-ei
{ 1113, 7, 13 }, // Eikyu
{ 1118, 4, 3 }, // Gen-ei 80
{ 1120, 4, 10 }, // Hoan
{ 1124, 4, 3 }, // Tenji
{ 1126, 1, 22 }, // Daiji
{ 1131, 1, 29 }, // Tensho
{ 1132, 8, 11 }, // Chosho
{ 1135, 4, 27 }, // Hoen
{ 1141, 7, 10 }, // Eiji
{ 1142, 4, 28 }, // Koji
{ 1144, 2, 23 }, // Tenyo
{ 1145, 7, 22 }, // Kyuan 90
{ 1151, 1, 26 }, // Ninpei
{ 1154, 10, 28 }, // Kyuju
{ 1156, 4, 27 }, // Hogen
{ 1159, 4, 20 }, // Heiji
{ 1160, 1, 10 }, // Eiryaku
{ 1161, 9, 4 }, // Oho
{ 1163, 3, 29 }, // Chokan
{ 1165, 6, 5 }, // Eiman
{ 1166, 8, 27 }, // Nin-an
{ 1169, 4, 8 }, // Kao 100
{ 1171, 4, 21 }, // Shoan
{ 1175, 7, 28 }, // Angen
{ 1177, 8, 4 }, // Jisho
{ 1181, 7, 14 }, // Yowa
{ 1182, 5, 27 }, // Juei
{ 1184, 4, 16 }, // Genryuku
{ 1185, 8, 14 }, // Bunji
{ 1190, 4, 11 }, // Kenkyu
{ 1199, 4, 27 }, // Shoji
{ 1201, 2, 13 }, // Kennin 110
{ 1204, 2, 20 }, // Genkyu
{ 1206, 4, 27 }, // Ken-ei
{ 1207, 10, 25 }, // Shogen
{ 1211, 3, 9 }, // Kenryaku
{ 1213, 12, 6 }, // Kenpo
{ 1219, 4, 12 }, // Shokyu
{ 1222, 4, 13 }, // Joo
{ 1224, 11, 20 }, // Gennin
{ 1225, 4, 20 }, // Karoku
{ 1227, 12, 10 }, // Antei 120
{ 1229, 3, 5 }, // Kanki
{ 1232, 4, 2 }, // Joei
{ 1233, 4, 15 }, // Tempuku
{ 1234, 11, 5 }, // Bunryaku
{ 1235, 9, 19 }, // Katei
{ 1238, 11, 23 }, // Ryakunin
{ 1239, 2, 7 }, // En-o
{ 1240, 7, 16 }, // Ninji
{ 1243, 2, 26 }, // Kangen
{ 1247, 2, 28 }, // Hoji 130
{ 1249, 3, 18 }, // Kencho
{ 1256, 10, 5 }, // Kogen
{ 1257, 3, 14 }, // Shoka
{ 1259, 3, 26 }, // Shogen
{ 1260, 4, 13 }, // Bun-o
{ 1261, 2, 20 }, // Kocho
{ 1264, 2, 28 }, // Bun-ei
{ 1275, 4, 25 }, // Kenji
{ 1278, 2, 29 }, // Koan
{ 1288, 4, 28 }, // Shoo 140
{ 1293, 8, 55 }, // Einin
{ 1299, 4, 25 }, // Shoan
{ 1302, 11, 21 }, // Kengen
{ 1303, 8, 5 }, // Kagen
{ 1306, 12, 14 }, // Tokuji
{ 1308, 10, 9 }, // Enkei
{ 1311, 4, 28 }, // Ocho
{ 1312, 3, 20 }, // Showa
{ 1317, 2, 3 }, // Bunpo
{ 1319, 4, 28 }, // Geno 150
{ 1321, 2, 23 }, // Genkyo
{ 1324, 12, 9 }, // Shochu
{ 1326, 4, 26 }, // Kareki
{ 1329, 8, 29 }, // Gentoku
{ 1331, 8, 9 }, // Genko
{ 1334, 1, 29 }, // Kemmu
{ 1336, 2, 29 }, // Engen
{ 1340, 4, 28 }, // Kokoku
{ 1346, 12, 8 }, // Shohei
{ 1370, 7, 24 }, // Kentoku 160
{ 1372, 4, 1 }, // Bunch\u0169
{ 1375, 5, 27 }, // Tenju
{ 1381, 2, 10 }, // Kowa
{ 1384, 4, 28 }, // Gench\u0169
{ 1384, 2, 27 }, // Meitoku
{ 1379, 3, 22 }, // Koryaku
{ 1387, 8, 23 }, // Kakei
{ 1389, 2, 9 }, // Koo
{ 1390, 3, 26 }, // Meitoku
{ 1394, 7, 5 }, // Oei 170
{ 1428, 4, 27 }, // Shocho
{ 1429, 9, 5 }, // Eikyo
{ 1441, 2, 17 }, // Kakitsu
{ 1444, 2, 5 }, // Bun-an
{ 1449, 7, 28 }, // Hotoku
{ 1452, 7, 25 }, // Kyotoku
{ 1455, 7, 25 }, // Kosho
{ 1457, 9, 28 }, // Choroku
{ 1460, 12, 21 }, // Kansho
{ 1466, 2, 28 }, // Bunsho 180
{ 1467, 3, 3 }, // Onin
{ 1469, 4, 28 }, // Bunmei
{ 1487, 7, 29 }, // Chokyo
{ 1489, 8, 21 }, // Entoku
{ 1492, 7, 19 }, // Meio
{ 1501, 2, 29 }, // Bunki
{ 1504, 2, 30 }, // Eisho
{ 1521, 8, 23 }, // Taiei
{ 1528, 8, 20 }, // Kyoroku
{ 1532, 7, 29 }, // Tenmon 190
{ 1555, 10, 23 }, // Koji
{ 1558, 2, 28 }, // Eiroku
{ 1570, 4, 23 }, // Genki
{ 1573, 7, 28 }, // Tensho
{ 1592, 12, 8 }, // Bunroku
{ 1596, 10, 27 }, // Keicho
{ 1615, 7, 13 }, // Genwa
{ 1624, 2, 30 }, // Kan-ei
{ 1644, 12, 16 }, // Shoho
{ 1648, 2, 15 }, // Keian 200
{ 1652, 9, 18 }, // Shoo
{ 1655, 4, 13 }, // Meiryaku
{ 1658, 7, 23 }, // Manji
{ 1661, 4, 25 }, // Kanbun
{ 1673, 9, 21 }, // Enpo
{ 1681, 9, 29 }, // Tenwa
{ 1684, 2, 21 }, // Jokyo
{ 1688, 9, 30 }, // Genroku
{ 1704, 3, 13 }, // Hoei
{ 1711, 4, 25 }, // Shotoku 210
{ 1716, 6, 22 }, // Kyoho
{ 1736, 4, 28 }, // Genbun
{ 1741, 2, 27 }, // Kanpo
{ 1744, 2, 21 }, // Enkyo
{ 1748, 7, 12 }, // Kan-en
{ 1751, 10, 27 }, // Horyaku
{ 1764, 6, 2 }, // Meiwa
{ 1772, 11, 16 }, // An-ei
{ 1781, 4, 2 }, // Tenmei
{ 1789, 1, 25 }, // Kansei 220
{ 1801, 2, 5 }, // Kyowa
{ 1804, 2, 11 }, // Bunka
{ 1818, 4, 22 }, // Bunsei
{ 1830, 12, 10 }, // Tenpo
{ 1844, 12, 2 }, // Koka
{ 1848, 2, 28 }, // Kaei
{ 1854, 11, 27 }, // Ansei
{ 1860, 3, 18 }, // Man-en
{ 1861, 2, 19 }, // Bunkyu
{ 1864, 2, 20 }, // Genji 230
{ 1865, 4, 7 }, // Keio 231
{ 1868, 9, 8 }, // Meiji 232
{ 1912, 7, 30 }, // Taisho 233
{ 1926, 12, 25 }, // Showa 234
{ 1989, 1, 8 } // Heisei 235
};
#define kEraCount (sizeof(kEraInfo)/sizeof(kEraInfo[0]))
const uint32_t JapaneseCalendar::kCurrentEra = (kEraCount-1);
JapaneseCalendar::JapaneseCalendar(const Locale& aLocale, UErrorCode& success)
: GregorianCalendar(aLocale, success)
{
success = U_UNSUPPORTED_ERROR; // Just a stub for now.
}
JapaneseCalendar::~JapaneseCalendar()
@ -57,6 +309,203 @@ const char *JapaneseCalendar::getType() const
}
int32_t
JapaneseCalendar::getMaximum(UCalendarDateFields field) const
{
if(field == UCAL_ERA) {
return kCurrentEra;
} else {
return GregorianCalendar::getMaximum(field);
}
}
int32_t
JapaneseCalendar::getLeastMaximum(UCalendarDateFields field) const
{
if(field == UCAL_ERA) {
return kCurrentEra;
} else {
return GregorianCalendar::getLeastMaximum(field);
}
}
int32_t
JapaneseCalendar::monthLength(int32_t month, int32_t year) const
{
return GregorianCalendar::monthLength(month,year);
}
int32_t
JapaneseCalendar::monthLength(int32_t month) const
{
int32_t year = internalGet(UCAL_YEAR);
// ignore era
return monthLength(month, year);
}
int32_t JapaneseCalendar::getDefaultMonthInYear() const
{
UErrorCode status = U_ZERO_ERROR;
int32_t era = internalGetEra();
int32_t year = getGregorianYear(status);
// TODO do we assume we can trust 'era'? What if it is denormalized?
int32_t month = GregorianCalendar::getDefaultMonthInYear();
// Find out if we are at the edge of an era
if(year == kEraInfo[era].year) {
// Yes, we're in the first year of this era.
return kEraInfo[era].month;
}
if(era < kCurrentEra) {
// if we're not in the current era,
// fail_here;
}
return month;
}
int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t month) const
{
UErrorCode status = U_ZERO_ERROR;
int32_t era = internalGetEra();
int32_t year = getGregorianYear(status);
int32_t day = GregorianCalendar::getDefaultDayInMonth(month);
if(year == kEraInfo[era].year) {
if(month == kEraInfo[era].month) {
return kEraInfo[era].day;
}
}
return day;
}
int32_t JapaneseCalendar::internalGetEra() const
{
return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : kCurrentEra;
}
int32_t
JapaneseCalendar::getGregorianYear(UErrorCode &status) const
{
int32_t year = (fStamp[UCAL_YEAR] != kUnset) ? internalGet(UCAL_YEAR) : 0;
int32_t era = kCurrentEra;
if (fStamp[UCAL_ERA] != kUnset) {
era = internalGet(UCAL_ERA);
}
if ((era<0)||(era>kCurrentEra)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0 ;
}
return year + kEraInfo[era].year - 1;
}
void JapaneseCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status)
{
GregorianCalendar::timeToFields(theTime, quick, status);
// these are the gregorian era and year
int32_t era = internalGet(UCAL_ERA);
int32_t year = internalGet(UCAL_YEAR);
if(era == GregorianCalendar::BC) {
year = 1 - year;
}
// grego [e+y] -> e+y
int32_t low = 0;
// Short circuit for recent years. Most modern computations will
// occur in the current era and won't require the binary search.
// Note that if the year is == the current era year, then we use
// the binary search to handle the month/dom comparison.
#ifdef U_DEBUG_JCAL
fprintf(stderr, "== %d:%d \n", era, year);
#endif
if (year > kEraInfo[kCurrentEra].year) {
low = kCurrentEra;
#ifdef U_DEBUG_JCAL
fprintf(stderr, " low=%d (special)\n", low);
#endif
} else {
// Binary search
int32_t high = kEraCount;
#ifdef U_DEBUG_JCAL
fprintf(stderr, " high=%d\n", high);
#endif
while (low < high - 1) {
int32_t i = (low + high) / 2;
int32_t diff = year - kEraInfo[i].year;
#ifdef U_DEBUG_JCAL
fprintf(stderr, " d=%d low=%d, high=%d. Considering %d:M%d D%d Y%d. { we are ?:M%d D%d Y%d }\n",
diff,low, high, i, kEraInfo[i].month-1, kEraInfo[i].day, kEraInfo[i].year, internalGet(UCAL_MONTH), internalGet(UCAL_DATE),year);
#endif
// If years are the same, then compare the months, and if those
// are the same, compare days of month. In the ERAS array
// months are 1-based for easier maintenance.
if (diff == 0) {
diff = internalGet(UCAL_MONTH) - (kEraInfo[i].month - 1);
#ifdef U_DEBUG_JCAL
fprintf(stderr, "diff now %d (M) = %d - %d - 1\n", diff, internalGet(UCAL_MONTH), kEraInfo[i].month);
#endif
if (diff == 0) {
diff = internalGet(UCAL_DATE) - kEraInfo[i].day;
#ifdef U_DEBUG_JCAL
fprintf(stderr, "diff now %d (D)\n", diff);
#endif
}
}
if (diff >= 0) {
low = i;
} else {
high = i;
}
#ifdef U_DEBUG_JCAL
fprintf(stderr, ". low=%d, high=%d, i=%d, diff=%d.. %d\n", low, high, i, diff, year);
#endif
}
}
#ifdef U_DEBUG_JCAL
fprintf(stderr, " low=%d,.. %d\n", low, year);
#endif
// Now we've found the last era that starts before this date, so
// adjust the year to count from the start of that era. Note that
// all dates before the first era will fall into the first era by
// the algorithm.
internalSet(UCAL_ERA, low);
internalSet(UCAL_YEAR, year - kEraInfo[low].year + 1);
}
/*
Disable pivoting
*/
UBool JapaneseCalendar::haveDefaultCentury() const
{
return FALSE;
}
UDate JapaneseCalendar::defaultCenturyStart() const
{
return 0;// WRONG
}
int32_t JapaneseCalendar::defaultCenturyStartYear() const
{
return 0;
}
U_NAMESPACE_END

View file

@ -7,7 +7,7 @@
* Modification History:
*
* Date Name Description
* 05/13/2003 srl copied from gregocal.h
* 05/13/2003 srl copied from gregocal.h
********************************************************************************
*/
@ -26,7 +26,28 @@ U_NAMESPACE_BEGIN
/**
* Concrete class which provides the Japanese calendar.
* <P>
* <i>(stuff pasted here from java)
* <code>JapaneseCalendar</code> is a subclass of <code>GregorianCalendar</code>
* that numbers years and eras based on the reigns of the Japanese emperors.
* The Japanese calendar is identical to the Gregorian calendar in all respects
* except for the year and era. The ascension of each emperor to the throne
* begins a new era, and the years of that era are numbered starting with the
* year of ascension as year 1.
* <p>
* Note that in the year of an imperial ascension, there are two possible sets
* of year and era values: that for the old era and for the new. For example, a
* new era began on January 7, 1989 AD. Strictly speaking, the first six days
* of that year were in the Showa era, e.g. "January 6, 64 Showa", while the rest
* of the year was in the Heisei era, e.g. "January 7, 1 Heisei". This class
* handles this distinction correctly when computing dates. However, in lenient
* mode either form of date is acceptable as input.
* <p>
* In modern times, eras have started on January 8, 1868 AD, Gregorian (Meiji),
* July 30, 1912 (Taisho), December 25, 1926 (Showa), and January 7, 1989 (Heisei). Constants
* for these eras, suitable for use in the <code>UCAL_ERA</code> field, are provided
* in this class. Note that the <em>number</em> used for each era is more or
* less arbitrary. Currently, the era starting in 1053 AD is era #0; however this
* may change in the future as we add more historical data. Use the predefined
* constants rather than using actual, absolute numbers.
* <p>
* @internal
*/
@ -34,12 +55,10 @@ class U_I18N_API JapaneseCalendar : public GregorianCalendar {
public:
/**
* Useful constants for JapaneseCalendar. Only one Era.
* Useful constants for JapaneseCalendar.
* @internal
*/
// enum EEras {
// BE
// };
static const uint32_t kCurrentEra; // the current era
/**
* Constructs a JapaneseCalendar based on the current time in the default time zone
@ -110,26 +129,60 @@ public:
static inline UClassID getStaticClassID(void);
/**
* return the calendar type, "gregorian".
* return the calendar type, "japanese".
*
* @return calendar type
* @internal
* @draft ICU 2.6
*/
virtual const char * getType() const;
/**
* @internal
* @return TRUE if this calendar has the notion of a default century
*/
virtual UBool haveDefaultCentury() const;
virtual UDate defaultCenturyStart() const;
virtual int32_t defaultCenturyStartYear() const;
private:
JapaneseCalendar(); // default constructor not implemented
static const char fgClassID;
protected:
// virtual int32_t monthLength(int32_t month) const;
// virtual int32_t monthLength(int32_t month, int32_t year) const;
// int32_t getGregorianYear(UErrorCode& status);
// int32_t getMaximum(UCalendarDateFields field) const;
// int32_t getLeastMaximum(UCalendarDateFields field) const;
// virtual int32_t internalGetEra() const;
// virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
protected:
virtual int32_t monthLength(int32_t month) const;
virtual int32_t monthLength(int32_t month, int32_t year) const;
int32_t getGregorianYear(UErrorCode& status) const;
int32_t getMaximum(UCalendarDateFields field) const;
int32_t getLeastMaximum(UCalendarDateFields field) const;
virtual int32_t internalGetEra() const;
virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
/**
* (Overrides Calendar) Converts Calendar's time field values to GMT as
* milliseconds. In this case, we have to be concerned with filling in inconsistent
* information. For example, if the year and era only are set, need to make sure
* month & date are set correctly. Ex, 'Heisei 1' starts Jan 8th, not Jan 1st.
* Default month and date values will end up giving the wrong Era.
*
* @param status Output param set to success/failure code on exit. If any value
* previously set in the time field is invalid, this will be set to
* an error status.
* @stable ICU 2.0
*/
/***
* Called by computeJulianDay. Returns the default month (0-based) for the year,
* taking year and era into account. Defaults to 0 for Gregorian, which doesn't care.
*/
virtual int32_t getDefaultMonthInYear() const;
/***
* Called by computeJulianDay. Returns the default day (1-based) for the month,
* taking currently-set year and era into account. Defaults to 1 for Gregorian, which doesn't care.
*/
virtual int32_t getDefaultDayInMonth(int32_t month) const;
};
inline UClassID

View file

@ -77,13 +77,9 @@ const char SimpleDateFormat::fgClassID = 0; // Value is irrelevant
/**
* This value of defaultCenturyStart indicates that the system default is to be
* used.
* used. To be removed in 2.8
*/
const UDate SimpleDateFormat::fgSystemDefaultCentury = DBL_MIN;
const int32_t SimpleDateFormat::fgSystemDefaultCenturyYear = -1;
UDate SimpleDateFormat::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t SimpleDateFormat::fgSystemDefaultCenturyStartYear = -1;
static const UChar QUOTE = 0x27; // Single quote
@ -97,11 +93,10 @@ SimpleDateFormat::~SimpleDateFormat()
//----------------------------------------------------------------------
SimpleDateFormat::SimpleDateFormat(UErrorCode& status)
: fSymbols(NULL),fLocale(Locale::getDefault()),
fDefaultCenturyStart(fgSystemDefaultCentury),
fDefaultCenturyStartYear(fgSystemDefaultCenturyYear)
: fSymbols(NULL),fLocale(Locale::getDefault())
{
construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
initializeDefaultCentury();
}
//----------------------------------------------------------------------
@ -110,12 +105,11 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
UErrorCode &status)
: fPattern(pattern),
fSymbols(NULL),
fLocale(Locale::getDefault()),
fDefaultCenturyStart(fgSystemDefaultCentury),
fDefaultCenturyStartYear(fgSystemDefaultCenturyYear)
fLocale(Locale::getDefault())
{
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initialize(fLocale, status);
initializeDefaultCentury();
}
//----------------------------------------------------------------------
@ -124,12 +118,11 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
const Locale& locale,
UErrorCode& status)
: fPattern(pattern),
fLocale(locale),
fDefaultCenturyStart(fgSystemDefaultCentury),
fDefaultCenturyStartYear(fgSystemDefaultCenturyYear)
fLocale(locale)
{
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initialize(fLocale, status);
initializeDefaultCentury();
}
//----------------------------------------------------------------------
@ -139,12 +132,11 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
UErrorCode& status)
: fPattern(pattern),
fSymbols(symbolsToAdopt),
fLocale(Locale::getDefault()),
fDefaultCenturyStart(fgSystemDefaultCentury),
fDefaultCenturyStartYear(fgSystemDefaultCenturyYear)
fLocale(Locale::getDefault())
{
initializeCalendar(NULL,fLocale,status);
initialize(fLocale, status);
initializeDefaultCentury();
}
//----------------------------------------------------------------------
@ -154,12 +146,11 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
UErrorCode& status)
: fPattern(pattern),
fSymbols(new DateFormatSymbols(symbols)),
fDefaultCenturyStart(fgSystemDefaultCentury),
fDefaultCenturyStartYear(fgSystemDefaultCenturyYear),
fLocale(Locale::getDefault())
{
initializeCalendar(NULL, fLocale, status);
initialize(fLocale, status);
initializeDefaultCentury();
}
//----------------------------------------------------------------------
@ -170,11 +161,10 @@ SimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
const Locale& locale,
UErrorCode& status)
: fSymbols(NULL),
fDefaultCenturyStart(fgSystemDefaultCentury),
fDefaultCenturyStartYear(fgSystemDefaultCenturyYear),
fLocale(locale)
{
construct(timeStyle, dateStyle, fLocale, status);
initializeDefaultCentury();
}
//----------------------------------------------------------------------
@ -188,9 +178,7 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
UErrorCode& status)
: fPattern(fgDefaultPattern),
fSymbols(NULL),
fLocale(locale),
fDefaultCenturyStart(fgSystemDefaultCentury),
fDefaultCenturyStartYear(fgSystemDefaultCenturyYear)
fLocale(locale)
{
if (U_FAILURE(status)) return;
initializeSymbols(fLocale, initializeCalendar(NULL, fLocale, status),status);
@ -208,15 +196,14 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
}
initialize(fLocale, status);
initializeDefaultCentury();
}
//----------------------------------------------------------------------
SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
: DateFormat(other),
fSymbols(NULL),
fDefaultCenturyStart(fgSystemDefaultCentury),
fDefaultCenturyStartYear(fgSystemDefaultCenturyYear)
fSymbols(NULL)
{
*this = other;
}
@ -235,6 +222,7 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
fDefaultCenturyStart = other.fDefaultCenturyStart;
fDefaultCenturyStartYear = other.fDefaultCenturyStartYear;
fHaveDefaultCentury = other.fHaveDefaultCentury;
fPattern = other.fPattern;
@ -262,6 +250,7 @@ SimpleDateFormat::operator==(const Format& other) const
fSymbols != NULL && // Check for pathological object
that->fSymbols != NULL && // Check for pathological object
*fSymbols == *that->fSymbols &&
fHaveDefaultCentury == that->fHaveDefaultCentury &&
fDefaultCenturyStart == that->fDefaultCenturyStart);
}
return FALSE;
@ -278,12 +267,16 @@ void SimpleDateFormat::construct(EStyle timeStyle,
if (U_FAILURE(status)) return;
// load up the DateTimePatters resource from the appropriate locale (throw
// load up the DateTimePatterns resource from the appropriate locale (throw
// an error if for some weird reason the resource is malformed)
ResourceBundle resources((char *)0, locale, status);
ResourceBundle dateTimePatterns = resources.get(fgDateTimePatternsTag, status);
// We will need the calendar to know what type of symbols to load.
initializeCalendar(NULL, locale, status);
// use Date Format Symbols' helper function to do the actual load.
ResourceBundle dateTimePatterns = DateFormatSymbols::getData(resources, fgDateTimePatternsTag, fCalendar?fCalendar->getType():NULL, status);
if (U_FAILURE(status)) return;
if (dateTimePatterns.getSize() <= kDateTime)
@ -292,8 +285,8 @@ void SimpleDateFormat::construct(EStyle timeStyle,
return;
}
initializeSymbols(locale, initializeCalendar(NULL, locale, status), status);
// create a symbols object from the locale
initializeSymbols(locale,fCalendar, status);
if (U_FAILURE(status)) return;
/* test for NULL */
if (fSymbols == 0) {
@ -401,8 +394,6 @@ SimpleDateFormat::initialize(const Locale& locale,
((DecimalFormat*)fNumberFormat)->setDecimalSeparatorAlwaysShown(FALSE);
fNumberFormat->setParseIntegerOnly(TRUE);
fNumberFormat->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
initializeDefaultCentury();
}
else if (U_SUCCESS(status))
{
@ -415,12 +406,14 @@ SimpleDateFormat::initialize(const Locale& locale,
*/
void SimpleDateFormat::initializeDefaultCentury()
{
fDefaultCenturyStart = internalGetDefaultCenturyStart();
fDefaultCenturyStartYear = internalGetDefaultCenturyStartYear();
UErrorCode status = U_ZERO_ERROR;
fCalendar->setTime(fDefaultCenturyStart, status);
// {sfb} throw away error
fHaveDefaultCentury = fCalendar->haveDefaultCentury();
if(fHaveDefaultCentury) {
fDefaultCenturyStart = fCalendar->defaultCenturyStart();
fDefaultCenturyStartYear = fCalendar->defaultCenturyStartYear();
} else {
fDefaultCenturyStart = DBL_MIN;
fDefaultCenturyStartYear = -1;
}
}
/* Define one-century window into which to disambiguate dates using
@ -433,6 +426,7 @@ void SimpleDateFormat::parseAmbiguousDatesAsAfter(UDate startDate, UErrorCode& s
fCalendar->setTime(startDate, status);
if(U_SUCCESS(status)) {
fHaveDefaultCentury = TRUE;
fDefaultCenturyStart = startDate;
fDefaultCenturyStartYear = fCalendar->get(UCAL_YEAR, status);
}
@ -589,6 +583,8 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
zeroPaddingNumber(appendTo, value, 4, maxIntCount);
else
zeroPaddingNumber(appendTo, value, 2, 2);
// SRL TODO: add 'y', unpadded value
break;
// for "MMMM", write out the whole month name, for "MMM", write out the month
@ -952,10 +948,10 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
Calendar *copy = cal.clone();
UDate parsedDate = copy->getTime(status);
// {sfb} check internalGetDefaultCenturyStart
if (parsedDate < internalGetDefaultCenturyStart())
if (fHaveDefaultCentury && (parsedDate < fDefaultCenturyStart))
{
// We can't use add here because that does a complete() first.
cal.set(UCAL_YEAR, internalGetDefaultCenturyStartYear() + 100);
cal.set(UCAL_YEAR, fDefaultCenturyStartYear + 100);
}
delete copy;
}
@ -1137,18 +1133,21 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
// other fields specify a date before 6/18, or 1903 if they specify a
// date afterwards. As a result, 03 is an ambiguous year. All other
// two-digit years are unambiguous.
int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
ambiguousYear[0] = (value == ambiguousTwoDigitYear);
value += (fDefaultCenturyStartYear/100)*100 +
if(fHaveDefaultCentury) { // check if this formatter even has a pivot year
int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
ambiguousYear[0] = (value == ambiguousTwoDigitYear);
value += (fDefaultCenturyStartYear/100)*100 +
(value < ambiguousTwoDigitYear ? 100 : 0);
}
}
cal.set(UCAL_YEAR, value);
return pos.getIndex();
case kYearWOYField:
// Comment is the same as for kYearFiels - look above
// Comment is the same as for kYearFields - look above
if (count <= 2 && (pos.getIndex() - start) == 2
&& u_isdigit(text.charAt(start))
&& u_isdigit(text.charAt(start+1)))
&& u_isdigit(text.charAt(start+1))
&& fHaveDefaultCentury )
{
int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
ambiguousYear[0] = (value == ambiguousTwoDigitYear);
@ -1527,56 +1526,6 @@ SimpleDateFormat::setDateFormatSymbols(const DateFormatSymbols& newFormatSymbols
//----------------------------------------------------------------------
UDate
SimpleDateFormat::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
initializeSystemDefaultCentury();
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return (fDefaultCenturyStart == fgSystemDefaultCentury) ?
fgSystemDefaultCenturyStart : fDefaultCenturyStart;
}
int32_t
SimpleDateFormat::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
initializeSystemDefaultCentury();
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
//return (fDefaultCenturyStart == fgSystemDefaultCentury) ?
return (fDefaultCenturyStartYear == fgSystemDefaultCenturyYear) ?
fgSystemDefaultCenturyStartYear : fDefaultCenturyStartYear;
}
void
SimpleDateFormat::initializeSystemDefaultCentury()
{
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
// the current time.
// No point in locking as it should be idempotent.
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
{
UErrorCode status = U_ZERO_ERROR;
Calendar *calendar = Calendar::createInstance(status);
if (calendar != NULL && U_SUCCESS(status))
{
calendar->setTime(Calendar::getNow(), status);
calendar->add(UCAL_YEAR, -80, status);
fgSystemDefaultCenturyStart = calendar->getTime(status);
fgSystemDefaultCenturyStartYear = calendar->get(UCAL_YEAR, status);
delete calendar;
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
}
void SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
{
@ -1584,7 +1533,8 @@ void SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
DateFormat::adoptCalendar(calendarToAdopt);
delete fSymbols;
fSymbols=NULL;
initializeSymbols(fLocale, fCalendar, status);
initializeSymbols(fLocale, fCalendar, status); // we need new symbols
initializeDefaultCentury(); // we need a new century (possibly)
}

View file

@ -38,7 +38,7 @@ U_NAMESPACE_BEGIN
class ICUServiceFactory;
/**
* @draft ICU 2.6
* @internal
*/
typedef const void* URegistryKey;
@ -1139,7 +1139,7 @@ public:
* or "Eras_gregorian".
*
* @returns static string, for example, "gregorian" or "japanese"
* @draft ICU 2.6
* @internal
*/
virtual const char * getType() const = 0;
@ -1465,6 +1465,23 @@ private:
friend class CalendarFactory;
friend class CalendarService;
friend class DefaultCalendarFactory;
/**
* @internal
* @return TRUE if this calendar has the notion of a default century
*/
virtual UBool haveDefaultCentury() const = 0;
/**
* @internal
* @return the start of the default century
*/
virtual UDate defaultCenturyStart() const = 0;
/**
* @internal
* @return the beginning year of the default century
*/
virtual int32_t defaultCenturyStartYear() const = 0;
};
// -------------------------------------

View file

@ -58,8 +58,15 @@ class SimpleDateFormat;
* they feel easy to remember. Or they can change the representative cities
* originally picked by default to using their favorite ones.
* <P>
* New DateFormatSymbols sub-classes may be added to support SimpleDateFormat
* for date-time formatting for additional locales.
* DateFormatSymbols are not expected to be subclassed. Data for a calendar is
* loaded out of resource bundles. The 'type' parameter indicates the type of
* calendar, for example, "gregorian" or "japanese". If the type is not gregorian
* (or NULL, or an empty string) then the type is appended to the resource name,
* for example, 'Eras_japanese' instead of 'Eras'. If the resource 'Eras_japanese' did
* not exist (even in root), then this class will fall back to just 'Eras', that is,
* Gregorian data. Therefore, the calendar implementor MUST ensure that the root
* locale at least contains any resources that are to be particularized for the
* calendar type.
*/
class U_I18N_API DateFormatSymbols : public UObject {
public:
@ -71,7 +78,7 @@ public:
* data for the default locale, it will return a last-resort object
* based on hard-coded strings.
*
* @param status Output param set to success of failure. Failure
* @param status Status code. Failure
* results if the resources for the default cannot be
* found or cannot be loaded
* @stable ICU 2.0
@ -83,7 +90,7 @@ public:
* resources for the given locale, in the default calendar (Gregorian).
*
* @param locale Locale to load format data from.
* @param status Output param set to success of failure. Failure
* @param status Status code. Failure
* results if the resources for the locale cannot be
* found or cannot be loaded
* @stable ICU 2.0
@ -102,10 +109,10 @@ public:
* @param type Type of calendar (as returned by Calendar::getType).
* Will be used to access the correct set of strings.
* (NULL or empty string defaults to "gregorian".)
* @param status Output param set to success of failure. Failure
* @param status Status code. Failure
* results if the resources for the default cannot be
* found or cannot be loaded
* @draft ICU 2.6
* @internal
*/
DateFormatSymbols(const char *type, UErrorCode& status);
@ -117,10 +124,10 @@ public:
* @param type Type of calendar (as returned by Calendar::getType).
* Will be used to access the correct set of strings.
* (NULL or empty string defaults to "gregorian".)
* @param status Output param set to success of failure. Failure
* @param status Status code. Failure
* results if the resources for the locale cannot be
* found or cannot be loaded
* @draft ICU 2.6
* @internal
*/
DateFormatSymbols(const Locale& locale,
const char *type,
@ -422,7 +429,7 @@ private:
* @param status Error Status
* @internal
*/
ResourceBundle
static ResourceBundle
getData(ResourceBundle &rb, const char *tag, const char *type, UErrorCode& status);

View file

@ -550,7 +550,7 @@ public:
* Get the calendar type, "gregorian", for use in DateFormatSymbols.
*
* @return calendar type
* @draft ICU 2.6
* @internal
*/
virtual const char * getType() const;
@ -560,7 +560,22 @@ protected:
* Called by computeFields. Converts calendar's year into Gregorian Extended Year (where negative = BC)
* @internal
*/
virtual int32_t getGregorianYear(UErrorCode &status);
virtual int32_t getGregorianYear(UErrorCode &status) const;
/***
* Called by computeJulianDay. Returns the default month (0-based) for the year,
* taking year and era into account. Defaults to 0 for Gregorian, which doesn't care.
*/
virtual int32_t getDefaultMonthInYear() const { return 0; }
/***
* Called by computeJulianDay. Returns the default day (1-based) for the month,
* taking currently-set year and era into account. Defaults to 1 for Gregorian, which doesn't care.
*/
virtual int32_t getDefaultDayInMonth(int32_t month) const { return 1; }
/**
* (Overrides Calendar) Converts GMT as milliseconds to time field values.
@ -850,6 +865,72 @@ protected:
*/
static int32_t floorDivide(double numerator, int32_t denominator, int32_t remainder[]);
public: // internal implementation
/**
* @internal
* @return TRUE if this calendar has the notion of a default century
*/
virtual UBool haveDefaultCentury() const;
/**
* @internal
* @return the start of the default century
*/
virtual UDate defaultCenturyStart() const;
/**
* @internal
* @return the beginning year of the default century
*/
virtual int32_t defaultCenturyStartYear() const;
private:
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* TODO: (ICU 2.8) use this value instead of SimpleDateFormat::fgSystemDefaultCentury
*/
//static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates with 2-digit years
* are considered to fall within.
* @return the beginning date of the 100-year window that dates with 2-digit years
* are considered to fall within.
*/
UDate internalGetDefaultCenturyStart(void) const;
/**
* Returns the first year of the 100-year window that dates with 2-digit years
* are considered to fall within.
* @return the first year of the 100-year window that dates with 2-digit years
* are considered to fall within.
*/
int32_t internalGetDefaultCenturyStartYear(void) const;
/**
* Initializes the 100-year window that dates with 2-digit years are considered
* to fall within so that its start date is 80 years before the current time.
*/
static void initializeSystemDefaultCentury(void);
};
inline UClassID

View file

@ -14,7 +14,7 @@
#define CHECK(status, msg) \
if (U_FAILURE(status)) { \
errln((UnicodeString(u_errorName(status)) + UnicodeString("err " ) )+ msg); \
errln((UnicodeString(u_errorName(status)) + UnicodeString(" : " ) )+ msg); \
return; \
}
@ -30,6 +30,9 @@
static UnicodeString fieldName(UCalendarDateFields f);
// Turn this on to dump the calendar fields
#define U_DEBUG_DUMPCALS
static UnicodeString calToStr(const Calendar & cal)
{
@ -41,7 +44,7 @@ static UnicodeString calToStr(const Calendar & cal)
}
out += UnicodeString(cal.getType());
out += cal.inDaylightTime(status)?UnicodeString("DAYLIGHT"):UnicodeString("NORMAL");
out += cal.inDaylightTime(status)?UnicodeString("- DAYLIGHT"):UnicodeString("- NORMAL");
UnicodeString str2;
out += cal.getTimeZone().getDisplayName(str2);
@ -49,28 +52,25 @@ static UnicodeString calToStr(const Calendar & cal)
return out;
}
#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
void IntlCalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
{
if (exec) logln("TestSuite IntlCalendarTest");
switch (index) {
case 0:
name = "TestTypes";
if (exec) {
logln("TestTypes---"); logln("");
TestTypes();
}
break;
case 1:
name = "TestBuddhist";
if (exec) {
logln("TestBuddhist---"); logln("");
TestBuddhist();
}
break;
CASE(0,TestTypes);
CASE(1,TestGregorian);
CASE(2,TestBuddhist);
CASE(3,TestJapanese);
CASE(4,TestBuddhistFormat);
CASE(5,TestJapaneseFormat);
default: name = ""; break;
}
}
#undef CASE
// ---------------------------------------------------------------------------------
static UnicodeString fieldName(UCalendarDateFields f) {
@ -110,15 +110,11 @@ IntlCalendarTest::TestTypes()
UErrorCode status = U_ZERO_ERROR;
int j;
const char *locs [40] = { "en_US_VALLEYGIRL",
#if 0
"ja_JP_TRADITIONAL",
#endif
"th_TH_TRADITIONAL",
"en_US", NULL };
const char *types[40] = { "gregorian",
#if 0
"japanese",
#endif
"buddhist",
"gregorian", NULL };
@ -175,13 +171,15 @@ void IntlCalendarTest::quasiGregorianTest(Calendar& cal, const Locale& gcl, cons
cal.set(UCAL_ERA, era);
cal.set(year, month, dayOfMonth);
UDate d = cal.getTime(status);
// logln((UnicodeString)"cal : " + calToStr(cal));
// logln((UnicodeString)"grego: " + calToStr(*grego));
#ifdef U_DEBUG_DUMPCALS
logln((UnicodeString)"cal : " + calToStr(cal));
logln((UnicodeString)"grego: " + calToStr(*grego));
#endif
if (d == D) {
logln(UnicodeString("OK: ") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
" => " + d + " (" + UnicodeString(cal.getType()));
" => " + d + " (" + UnicodeString(cal.getType()) + ")");
} else {
errln(UnicodeString("Fail: ") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
errln(UnicodeString("Fail: (fields to millis)") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
" => " + d + ", expected " + D + " (" + UnicodeString(cal.getType()) + "Off by: " + (d-D));
}
@ -190,14 +188,16 @@ void IntlCalendarTest::quasiGregorianTest(Calendar& cal, const Locale& gcl, cons
cal.setTime(D, status);
int e = cal.get(UCAL_ERA, status);
int y = cal.get(UCAL_YEAR, status);
//logln((UnicodeString)"cal : " + calToStr(cal));
//logln((UnicodeString)"grego: " + calToStr(*grego));
#ifdef U_DEBUG_DUMPCALS
logln((UnicodeString)"cal : " + calToStr(cal));
logln((UnicodeString)"grego: " + calToStr(*grego));
#endif
if (y == year && e == era) {
logln((UnicodeString)"OK: " + D + " => " + cal.get(UCAL_ERA, status) + ":" +
cal.get(UCAL_YEAR, status) + "/" +
(cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) + " (" + UnicodeString(cal.getType()));
(cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) + " (" + UnicodeString(cal.getType()) + ")");
} else {
errln((UnicodeString)"Fail: " + D + " => " + cal.get(UCAL_ERA, status) + ":" +
errln((UnicodeString)"Fail: (millis to fields)" + D + " => " + cal.get(UCAL_ERA, status) + ":" +
cal.get(UCAL_YEAR, status) + "/" +
(cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) +
", expected " + era + ":" + year + "/" + (month+1) + "/" +
@ -208,6 +208,26 @@ void IntlCalendarTest::quasiGregorianTest(Calendar& cal, const Locale& gcl, cons
CHECK(status, "err during quasiGregorianTest()");
}
// Verify that Gregorian works like Gregorian
void IntlCalendarTest::TestGregorian() {
int32_t data[] = {
GregorianCalendar::AD, 1868, 1868, UCAL_SEPTEMBER, 8,
GregorianCalendar::AD, 1868, 1868, UCAL_SEPTEMBER, 9,
GregorianCalendar::AD, 1869, 1869, UCAL_JUNE, 4,
GregorianCalendar::AD, 1912, 1912, UCAL_JULY, 29,
GregorianCalendar::AD, 1912, 1912, UCAL_JULY, 30,
GregorianCalendar::AD, 1912, 1912, UCAL_AUGUST, 1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};
Calendar *cal;
UErrorCode status = U_ZERO_ERROR;
cal = Calendar::createInstance("de_DE", status);
CHECK(status, UnicodeString("Creating de_CH calendar"));
quasiGregorianTest(*cal,Locale("fr_FR"),data);
delete cal;
}
/**
* Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise
* behaves like GregorianCalendar.
@ -231,6 +251,50 @@ void IntlCalendarTest::TestBuddhist() {
cal = Calendar::createInstance("th_TH_TRADITIONAL", status);
CHECK(status, UnicodeString("Creating th_TH_TRADITIONAL calendar"));
quasiGregorianTest(*cal,Locale("th_TH"),data);
}
/**
* Verify that JapaneseCalendar shifts years to Japanese Eras but otherwise
* behaves like GregorianCalendar.
*/
void IntlCalendarTest::TestJapanese() {
/* Sorry.. japancal.h is private! */
#define JapaneseCalendar_MEIJI 232
#define JapaneseCalendar_TAISHO 233
#define JapaneseCalendar_SHOWA 234
#define JapaneseCalendar_HEISEI 235
// BE 2542 == 1999 CE
int32_t data[] = {
// Jera Jyr Gyear m d
JapaneseCalendar_MEIJI, 1, 1868, UCAL_SEPTEMBER, 8,
JapaneseCalendar_MEIJI, 1, 1868, UCAL_SEPTEMBER, 9,
JapaneseCalendar_MEIJI, 2, 1869, UCAL_JUNE, 4,
JapaneseCalendar_MEIJI, 45, 1912, UCAL_JULY, 29,
JapaneseCalendar_TAISHO, 1, 1912, UCAL_JULY, 30,
JapaneseCalendar_TAISHO, 1, 1912, UCAL_AUGUST, 1,
// new tests (not in java)
JapaneseCalendar_SHOWA, 64, 1989, UCAL_JANUARY, 7,
JapaneseCalendar_HEISEI, 1, 1989, UCAL_JANUARY, 8,
JapaneseCalendar_HEISEI, 1, 1989, UCAL_JANUARY, 9,
JapaneseCalendar_HEISEI, 1, 1989, UCAL_DECEMBER, 20,
JapaneseCalendar_HEISEI, 15, 2003, UCAL_MAY, 22,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 };
Calendar *cal;
UErrorCode status = U_ZERO_ERROR;
cal = Calendar::createInstance("ja_JP_TRADITIONAL", status);
CHECK(status, UnicodeString("Creating ja_JP_TRADITIONAL calendar"));
quasiGregorianTest(*cal,Locale("ja_JP"),data);
}
void IntlCalendarTest::TestBuddhistFormat() {
Calendar *cal;
UErrorCode status = U_ZERO_ERROR;
cal = Calendar::createInstance("th_TH_TRADITIONAL", status);
CHECK(status, UnicodeString("Creating th_TH_TRADITIONAL calendar"));
// Test simple parse/format with adopt
@ -262,6 +326,54 @@ void IntlCalendarTest::TestBuddhist() {
}
delete fmt;
}
delete cal;
CHECK(status, "Error occured");
}
void IntlCalendarTest::TestJapaneseFormat() {
Calendar *cal;
UErrorCode status = U_ZERO_ERROR;
cal = Calendar::createInstance("ja_JP_TRADITIONAL", status);
CHECK(status, UnicodeString("Creating ja_JP_TRADITIONAL calendar"));
Calendar *cal2 = cal->clone();
// Test simple parse/format with adopt
UDate aDate = 999932400000.0;
SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yy G"), Locale("en_US"), status);
CHECK(status, "creating date format instance");
if(!fmt) {
errln("Coudln't create en_US instance");
} else {
UnicodeString str;
fmt->format(aDate, str);
logln(UnicodeString() + "Test Date: " + str);
str.remove();
fmt->adoptCalendar(cal);
cal = NULL;
fmt->format(aDate, str);
logln(UnicodeString() + "as Japanese Calendar: " + str);
UnicodeString expected("September 8, 13 Heisei");
if(str != expected) {
errln("Expected " + expected + " but got " + str);
}
UDate otherDate = fmt->parse(expected, status);
if(otherDate != aDate) {
UnicodeString str3;
ParsePosition pp;
fmt->parse(expected, *cal2, pp);
fmt->format(otherDate, str3);
errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + calToStr(*cal2) );
} else {
logln("Parsed OK: " + expected);
}
delete fmt;
}
delete cal;
delete cal2;
CHECK(status, "Error occured");
}

View file

@ -20,14 +20,18 @@ public:
// IntlTest override
void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par );
public:
/**
* Confirm that the registered calendars have the correct type.
*/
void TestTypes(void);
void TestGregorian(void);
void TestBuddhist(void);
void TestBuddhistFormat(void);
void TestJapanese(void);
void TestJapaneseFormat(void);
protected:
// Test a Gregorian-Like calendar
void quasiGregorianTest(Calendar& cal, const Locale& gregoLocale, const int32_t *data);
public: // package