+ * MyanmarCalendar
is a subclass of GregorianCalendar
+ * that numbers years since the birth of the Buddha. This imementatin ]is ]based ]n the civil calendar
+ * used in Myanmar.
+ *
+ * The Myanmar calendar increments in mid April; represented as April 17 as it + * has been between April 2001 - 2034 (inclusive). + *
+ * The Myanmar Calendar has only one allowable era: ME
. If the
+ * calendar is not in lenient mode (see setLenient
), dates before
+ * 1/1/1 ME are rejected as an illegal argument.
+ *
+ * @internal
+ */
+class MyanmarCalendar : public GregorianCalendar {
+public:
+
+ /**
+ * Useful constants for MyanmarCalendar. Only one Era.
+ * @internal
+ */
+ enum EEras {
+ ME
+ };
+
+ /**
+ * Constructs a MyanmarCalendar based on the current time in the default time zone
+ * with the given locale.
+ *
+ * @param aLocale The given locale.
+ * @param success Indicates the status of MyanmarCalendar object construction.
+ * Returns U_ZERO_ERROR if constructed successfully.
+ * @internal
+ */
+ MyanmarCalendar(const Locale& aLocale, UErrorCode& success);
+
+
+ /**
+ * Destructor
+ * @internal
+ */
+ virtual ~MyanmarCalendar();
+
+ /**
+ * Copy constructor
+ * @param source the object to be copied.
+ * @internal
+ */
+ MyanmarCalendar(const MyanmarCalendar& source);
+
+ /**
+ * Create and return a polymorphic copy of this calendar.
+ * @return return a polymorphic copy of this calendar.
+ * @internal
+ */
+ virtual MyanmarCalendar* clone() const override;
+
+public:
+ /**
+ * Override Calendar Returns a unique class ID POLYMORPHICALLY. Pure virtual
+ * override. This method is to implement a simple version of RTTI, since not all C++
+ * compilers support genuine RTTI. Polymorphic operator==() and clone() methods call
+ * this method.
+ *
+ * @return The class ID for this object. All objects of a given class have the
+ * same class ID. Objects of other classes have different class IDs.
+ * @internal
+ */
+ virtual UClassID getDynamicClassID() const override;
+
+ /**
+ * Return the class ID for this class. This is useful only for comparing to a return
+ * value from getDynamicClassID(). For example:
+ *
+ * Base* polymorphic_pointer = createPolymorphicObject();
+ * if (polymorphic_pointer->getDynamicClassID() ==
+ * Derived::getStaticClassID()) ...
+ *
+ * @return The class ID for all objects of this class.
+ * @internal
+ */
+ U_I18N_API static UClassID U_EXPORT2 getStaticClassID();
+
+ /**
+ * return the calendar type, "myanmar".
+ *
+ * @return calendar type
+ * @internal
+ */
+ virtual const char * getType() const override;
+
+private:
+ MyanmarCalendar(); // default constructor not implemented
+
+ /**
+ * Return the day # on which the given Myanmar era year starts (April 17th).
+ */
+ int32_t yearStart(int32_t year, UErrorCode& status);
+
+ protected:
+ /**
+ * Return the extended year defined by the current fields. This will
+ * use the UCAL_EXTENDED_YEAR field or the UCAL_YEAR and supra-year fields (such
+ * as UCAL_ERA) specific to the calendar system, depending on which set of
+ * fields is newer.
+ * @param status
+ * @return the extended year
+ * @internal
+ */
+ virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
+ /**
+ * Subclasses may override this method to compute several fields
+ * specific to each calendar system.
+ * @internal
+ */
+ virtual void handleComputeFields(int32_t julianDay, UErrorCode& status) override;
+ /**
+ * Subclass API for defining limits of different types.
+ * @param field one of the field numbers
+ * @param limitType one of MINIMUM
, GREATEST_MINIMUM
,
+ * LEAST_MAXIMUM
, or MAXIMUM
+ * @internal
+ */
+ virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const override;
+
+ virtual bool isEra0CountingBackward() const override { return false; }
+
+ DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY
+};
+
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif // _GREGOCAL
+//eof
diff --git a/icu4c/source/i18n/sources.txt b/icu4c/source/i18n/sources.txt
index 77532f556467..c7f48cd90506 100644
--- a/icu4c/source/i18n/sources.txt
+++ b/icu4c/source/i18n/sources.txt
@@ -105,6 +105,7 @@ messageformat2_formattable.cpp
messageformat2_function_registry.cpp
messageformat2_parser.cpp
messageformat2_serializer.cpp
+myancal.cpp
name2uni.cpp
nfrs.cpp
nfrule.cpp
diff --git a/icu4c/source/i18n/ucal.cpp b/icu4c/source/i18n/ucal.cpp
index b8905fe9a3d1..c503b6c0447b 100644
--- a/icu4c/source/i18n/ucal.cpp
+++ b/icu4c/source/i18n/ucal.cpp
@@ -710,6 +710,7 @@ static const char * const CAL_TYPES[] = {
"islamic-umalqura",
"islamic-tbla",
"islamic-rgsa",
+ "myanmar",
nullptr
};
diff --git a/icu4c/source/test/depstest/dependencies.txt b/icu4c/source/test/depstest/dependencies.txt
index caf3c57cdbe8..f789f9f7b418 100644
--- a/icu4c/source/test/depstest/dependencies.txt
+++ b/icu4c/source/test/depstest/dependencies.txt
@@ -1083,7 +1083,7 @@ group: formatting
measfmt.o quantityformatter.o
# dateformat
astro.o buddhcal.o calendar.o cecal.o chnsecal.o coptccal.o dangical.o ethpccal.o
- gregocal.o gregoimp.o hebrwcal.o indiancal.o islamcal.o iso8601cal.o japancal.o persncal.o taiwncal.o
+ gregocal.o gregoimp.o hebrwcal.o indiancal.o islamcal.o iso8601cal.o japancal.o persncal.o taiwncal.o myancal.o
erarules.o # mostly for Japanese eras
ucal.o
basictz.o olsontz.o rbtz.o simpletz.o timezone.o tzrule.o tztrans.o
diff --git a/icu4c/source/test/intltest/callimts.cpp b/icu4c/source/test/intltest/callimts.cpp
index bbac90cea1f7..6296c0caa65c 100644
--- a/icu4c/source/test/intltest/callimts.cpp
+++ b/icu4c/source/test/intltest/callimts.cpp
@@ -170,9 +170,10 @@ TestCase TestCases[] = {
{"indian", false, DEFAULT_START, DEFAULT_END},
{"coptic", false, DEFAULT_START, DEFAULT_END},
{"ethiopic", false, DEFAULT_START, DEFAULT_END},
- {"ethiopic-amete-alem", false, DEFAULT_START, DEFAULT_END}
+ {"ethiopic-amete-alem", false, DEFAULT_START, DEFAULT_END},
+ {"myanmar", false, DEFAULT_START, DEFAULT_END}
};
-
+
struct {
int32_t fIndex;
UBool next (int32_t &rIndex) {
diff --git a/icu4c/source/test/intltest/incaltst.cpp b/icu4c/source/test/intltest/incaltst.cpp
index 4b825fda06c1..17384a553cb5 100644
--- a/icu4c/source/test/intltest/incaltst.cpp
+++ b/icu4c/source/test/intltest/incaltst.cpp
@@ -92,6 +92,8 @@ void IntlCalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &n
TESTCASE_AUTO(TestGregorianToPersian);
TESTCASE_AUTO(TestPersianFormat);
TESTCASE_AUTO(TestTaiwan);
+ TESTCASE_AUTO(TestMyanmar);
+ TESTCASE_AUTO(TestMyanmarFormat);
TESTCASE_AUTO(TestConsistencyGregorian);
TESTCASE_AUTO(TestConsistencyCoptic);
TESTCASE_AUTO(TestConsistencyEthiopic);
@@ -779,6 +781,118 @@ void IntlCalendarTest::TestForceGannenNumbering()
}
}
+/**
+ * Verify the Myanmar Calendar.
+ */
+void IntlCalendarTest::TestMyanmar() {
+ UDate timeA = Calendar::getNow();
+
+ Calendar *cal;
+ UErrorCode status = U_ZERO_ERROR;
+ cal = Calendar::createInstance("en_US@calendar=myanmar", status);
+ CHECK(status, UnicodeString("Creating en_US@calendar=myanmar calendar"));
+ // Sanity check the calendar
+ UDate timeB = Calendar::getNow();
+ UDate timeCal = cal->getTime(status);
+
+ if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
+ errln((UnicodeString)"Error: Calendar time " + timeCal +
+ " is not within sampled times [" + timeA + " to " + timeB + "]!");
+ }
+
+ // Test thingyan in recent years
+ int32_t data[] = {
+ 2024, 6, 12, 1386, 6, 12, // 2024
+ 2019, 4, 17, 1381, 4, 17, // start of 1381
+ 2019, 1, 1, 1380, 1, 1,
+ 2018,12, 31, 1380,12, 31,
+
+ 2018, 4, 17, 1380, 4, 17, // start year in kason
+ 2018, 4, 16, 1379, 4, 16, // late kason
+ 2017, 4, 17, 1379, 4, 17, // start year in tagu
+ 2017, 4, 16, 1378, 4, 16, // late tagu
+
+ 2016, 4, 17, 1378, 4, 17, // first day of 1378, tagu
+ 2016, 4, 16, 1377, 4, 16, // last day of 1377, late tagu
+
+ 2015, 4, 17, 1377, 4, 17, // first day of year is single-day tagu
+ 2015, 4, 3, 1376, 4, 3, // late dagu
+
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ };
+
+ Calendar *grego = Calendar::createInstance("en_US@calendar=gregorian", status);
+ for (int32_t i=0; data[i]!=-1; ) {
+ int32_t gregYear = data[i++];
+ int32_t gregMonth = data[i++]-1;
+ int32_t gregDay = data[i++];
+ int32_t myanYear = data[i++];
+ int32_t myanMonth = data[i++]-1;
+ int32_t myanDay = data[i++];
+
+ // Test conversion from Myanmar dates
+ grego->clear();
+ grego->set(gregYear, gregMonth, gregDay);
+
+ cal->clear();
+ cal->set(myanYear, myanMonth, myanDay);
+
+ UDate myanTime = cal->getTime(status);
+ UDate gregTime = grego->getTime(status);
+
+ if (myanTime != gregTime) {
+ errln(UnicodeString("Expected ") + gregTime + " but got " + myanTime);
+ }
+
+ // Test conversion to Myanmar dates
+ cal->clear();
+ cal->setTime(gregTime, status);
+
+ int32_t computedYear = cal->get(UCAL_YEAR, status);
+ int32_t computedMonth = cal->get(UCAL_MONTH, status);
+ int32_t computedDay = cal->get(UCAL_DATE, status);
+
+ if ((myanYear != computedYear) ||
+ (myanMonth != computedMonth) ||
+ (myanDay != computedDay)) {
+ errln(UnicodeString("Expected ") + myanYear + "/" + (myanMonth+1) + "/" + myanDay +
+ " but got " + computedYear + "/" + (computedMonth+1) + "/" + computedDay);
+ }
+
+ }
+
+ delete cal;
+ delete grego;
+}
+
+void IntlCalendarTest::TestMyanmarFormat() {
+ UErrorCode status = U_ZERO_ERROR;
+ SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=myanmar"), status);
+ CHECK(status, "creating date format instance");
+ SimpleDateFormat fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
+ CHECK(status, "creating gregorian date format instance");
+ UnicodeString gregorianDate("April 15, 1989 AD");
+ UDate aDate = fmt2.parse(gregorianDate, status);
+ UnicodeString str;
+ fmt.format(aDate, str);
+ logln(UnicodeString() + "as Myanmar Calendar: " + escape(str));
+ UnicodeString expected("April 15, 1350 BC"); // TODO : correct to ME
+ if(str != expected) {
+ errln("Expected " + escape(expected) + " but got " + escape(str));
+ }
+ UDate otherDate = fmt.parse(expected, status);
+ if(otherDate != aDate) {
+ UnicodeString str3;
+ fmt.format(otherDate, str3);
+ errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate + ", " + escape(str3));
+ } else {
+ logln("Parsed OK: " + expected);
+ }
+
+ CHECK(status, "Error occurred testing Myanmar Calendar in English ");
+}
+
+
/**
* Verify the Persian Calendar.
*/
diff --git a/icu4c/source/test/intltest/incaltst.h b/icu4c/source/test/intltest/incaltst.h
index a1f7d11bfc40..d56ab24001b4 100644
--- a/icu4c/source/test/intltest/incaltst.h
+++ b/icu4c/source/test/intltest/incaltst.h
@@ -47,6 +47,9 @@ class IntlCalendarTest: public CalendarTimeZoneTest {
void TestGregorianToPersian();
void TestPersianFormat();
+ void TestMyanmar();
+ void TestMyanmarFormat();
+
void TestConsistencyGregorian();
void TestConsistencyCoptic();
void TestConsistencyEthiopic();
diff --git a/icu4c/source/test/intltest/uobjtest.cpp b/icu4c/source/test/intltest/uobjtest.cpp
index a10a71b32759..d7f7872f87dd 100644
--- a/icu4c/source/test/intltest/uobjtest.cpp
+++ b/icu4c/source/test/intltest/uobjtest.cpp
@@ -243,6 +243,7 @@ UObject *UObjectTest::testClassNoClassID(UObject *obj, const char *className, co
#include "taiwncal.h"
#include "indiancal.h"
#include "chnsecal.h"
+#include "myancal.h"
#include "windtfmt.h"
#include "winnmfmt.h"
#include "ustrenum.h"
@@ -389,6 +390,7 @@ void UObjectTest::testIDs()
TESTCLASSID_FACTORY(IndianCalendar, Calendar::createInstance(Locale("@calendar=indian"), status));
TESTCLASSID_FACTORY(ChineseCalendar, Calendar::createInstance(Locale("@calendar=chinese"), status));
TESTCLASSID_FACTORY(TaiwanCalendar, Calendar::createInstance(Locale("@calendar=roc"), status));
+ TESTCLASSID_FACTORY(MyanmarCalendar, Calendar::createInstance(Locale("@calendar=myanmar"), status));
#if U_PLATFORM_USES_ONLY_WIN32_API
TESTCLASSID_FACTORY(Win32DateFormat, DateFormat::createDateInstance(DateFormat::kFull, Locale("@compat=host")));
TESTCLASSID_FACTORY(Win32NumberFormat, NumberFormat::createInstance(Locale("@compat=host"), status));
diff --git a/icu4c/source/test/testdata/structLocale.txt b/icu4c/source/test/testdata/structLocale.txt
index 99f3cdc0d3a3..11bff13d9376 100644
--- a/icu4c/source/test/testdata/structLocale.txt
+++ b/icu4c/source/test/testdata/structLocale.txt
@@ -34535,6 +34535,7 @@ structLocale:table(nofallback){
islamic-umalqura{""}
iso8601{""}
japanese{""}
+ myanmar{""}
persian{""}
roc{""}
}