Skip to content

ICU-11533 limited Myanmar calendar support #3482

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions icu4c/source/i18n/calendar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "coptccal.h"
#include "dangical.h"
#include "ethpccal.h"
#include "myancal.h"
#include "unicode/calendar.h"
#include "cpputils.h"
#include "servloc.h"
Expand Down Expand Up @@ -162,6 +163,7 @@ static const char * const gCalTypes[] = {
"gregorian",
"japanese",
"buddhist",
"myanmar",
"roc",
"persian",
"islamic-civil",
Expand All @@ -186,6 +188,7 @@ typedef enum ECalType {
CALTYPE_GREGORIAN = 0,
CALTYPE_JAPANESE,
CALTYPE_BUDDHIST,
CALTYPE_MYANMAR,
CALTYPE_ROC,
CALTYPE_PERSIAN,
CALTYPE_ISLAMIC_CIVIL,
Expand Down Expand Up @@ -323,6 +326,9 @@ static Calendar *createStandardCalendar(ECalType calType, const Locale &loc, UEr
case CALTYPE_BUDDHIST:
cal.adoptInsteadAndCheckErrorCode(new BuddhistCalendar(loc, status), status);
break;
case CALTYPE_MYANMAR:
cal.adoptInsteadAndCheckErrorCode(new MyanmarCalendar(loc, status), status);
break;
case CALTYPE_ROC:
cal.adoptInsteadAndCheckErrorCode(new TaiwanCalendar(loc, status), status);
break;
Expand Down
2 changes: 2 additions & 0 deletions icu4c/source/i18n/i18n.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
<ClCompile Include="messageformat2_parser.cpp" />
<ClCompile Include="messageformat2_serializer.cpp" />
<ClCompile Include="msgfmt.cpp" />
<ClCompile Include="myancal.cpp" />
<ClCompile Include="nfrs.cpp" />
<ClCompile Include="nfrule.cpp" />
<ClCompile Include="nfsubs.cpp" />
Expand Down Expand Up @@ -400,6 +401,7 @@
<ClInclude Include="japancal.h" />
<ClInclude Include="measunit_impl.h" />
<ClInclude Include="msgfmt_impl.h" />
<ClInclude Include="myancal.h" />
<ClInclude Include="nfrlist.h" />
<ClInclude Include="nfrs.h" />
<ClInclude Include="nfrule.h" />
Expand Down
6 changes: 6 additions & 0 deletions icu4c/source/i18n/i18n.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@
<ClCompile Include="msgfmt.cpp">
<Filter>formatting</Filter>
</ClCompile>
<ClCompile Include="myancal.cpp">
<Filter>formatting</Filter>
</ClCompile>
<ClCompile Include="nfrs.cpp">
<Filter>formatting</Filter>
</ClCompile>
Expand Down Expand Up @@ -908,6 +911,9 @@
<ClInclude Include="msgfmt_impl.h">
<Filter>formatting</Filter>
</ClInclude>
<ClInclude Include="myancal.h">
<Filter>formatting</Filter>
</ClInclude>
<ClInclude Include="nfrlist.h">
<Filter>formatting</Filter>
</ClInclude>
Expand Down
2 changes: 2 additions & 0 deletions icu4c/source/i18n/i18n_uwp.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@
<ClCompile Include="messageformat2_parser.cpp" />
<ClCompile Include="messageformat2_serializer.cpp" />
<ClCompile Include="msgfmt.cpp" />
<ClCompile Include="myancal.cpp" />
<ClCompile Include="nfrs.cpp" />
<ClCompile Include="nfrule.cpp" />
<ClCompile Include="nfsubs.cpp" />
Expand Down Expand Up @@ -631,6 +632,7 @@
<ClInclude Include="japancal.h" />
<ClInclude Include="measunit_impl.h" />
<ClInclude Include="msgfmt_impl.h" />
<ClInclude Include="myancal.h" />
<ClInclude Include="nfrlist.h" />
<ClInclude Include="nfrs.h" />
<ClInclude Include="nfrule.h" />
Expand Down
107 changes: 107 additions & 0 deletions icu4c/source/i18n/myancal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// © 2025 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*
* File MYANCAL.CPP
*
* Modification History:
* 04/18/2025 mapmeld copied from buddhcal.h
*
*/

#include "unicode/ucal.h"
#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "myancal.h"
#include "gregoimp.h"
#include "unicode/gregocal.h"
#include "umutex.h"
#include <float.h>

U_NAMESPACE_BEGIN

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MyanmarCalendar)

//static const int32_t kMaxEra = 0; // only 1 era

static const int32_t kMEEraStart = 639; // 639 AD (Gregorian)

static const int32_t kGregorianEpoch = 1970; // used as the default value of EXTENDED_YEAR

MyanmarCalendar::MyanmarCalendar(const Locale& aLocale, UErrorCode& success)
: GregorianCalendar(aLocale, success)
{
}

MyanmarCalendar::~MyanmarCalendar()
{
}

MyanmarCalendar::MyanmarCalendar(const MyanmarCalendar& source)
: GregorianCalendar(source)
{
}

MyanmarCalendar* MyanmarCalendar::clone() const
{
return new MyanmarCalendar(*this);
}

const char *MyanmarCalendar::getType() const
{
return "myanmar";
}

int32_t MyanmarCalendar::yearStart(int32_t year, UErrorCode& status) {
return GregorianCalendar::handleComputeMonthStart(year + 638, 3, true, status) + 16;
}

int32_t MyanmarCalendar::handleGetExtendedYear(UErrorCode& status)
{
if (U_FAILURE(status)) {
return 0;
}

// extended year is a gregorian year, where 1 = 1AD, 0 = 1BC, -1 = 2BC, etc
int32_t y = internalGet(UCAL_YEAR, kGregorianEpoch - kMEEraStart);
int32_t m = internalGet(UCAL_MONTH);
int32_t d = internalGet(UCAL_DAY_OF_MONTH);
if ((m == 3 && d >= 17) || m >= 4) {
y--;
internalSet(UCAL_YEAR, y);
}
if (uprv_add32_overflow(y, kMEEraStart, &y)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
return y;
}

void MyanmarCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
{
GregorianCalendar::handleComputeFields(julianDay, status);
int32_t y = internalGet(UCAL_EXTENDED_YEAR) - kMEEraStart;
int32_t m = internalGet(UCAL_MONTH);
int32_t d = internalGet(UCAL_DAY_OF_MONTH);
if ((m == 3 && d >= 17) || m >= 4) {
y++;
}
internalSet(UCAL_ERA, 0);
internalSet(UCAL_YEAR, y);
}

int32_t MyanmarCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const
{
if(field == UCAL_ERA) {
return ME;
}
return GregorianCalendar::handleGetLimit(field,limitType);
}

IMPL_SYSTEM_DEFAULT_CENTURY(MyanmarCalendar, "@calendar=myanmar")

U_NAMESPACE_END

#endif
163 changes: 163 additions & 0 deletions icu4c/source/i18n/myancal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// © 2025 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*
* File MYANCAL.H
*
* Modification History:
*
* Date Name Description
* 04/18/2025 srl copied from buddhcal.h
********************************************************************************
*/

#ifndef MYANCAL_H
#define MYANCAL_H

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/calendar.h"
#include "unicode/gregocal.h"

U_NAMESPACE_BEGIN

/**
* Concrete class which provides the Myanmar calendar.
* <P>
* <code>MyanmarCalendar</code> is a subclass of <code>GregorianCalendar</code>
* that numbers years since the birth of the Buddha. This imementatin ]is ]based ]n the civil calendar
* used in Myanmar.
* <p>
* The Myanmar calendar increments in mid April; represented as April 17 as it
* has been between April 2001 - 2034 (inclusive).
* <p>
* The Myanmar Calendar has only one allowable era: <code>ME</code>. If the
* calendar is not in lenient mode (see <code>setLenient</code>), dates before
* 1/1/1 ME are rejected as an illegal argument.
* <p>
* @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 <code>MINIMUM</code>, <code>GREATEST_MINIMUM</code>,
* <code>LEAST_MAXIMUM</code>, or <code>MAXIMUM</code>
* @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
1 change: 1 addition & 0 deletions icu4c/source/i18n/sources.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions icu4c/source/i18n/ucal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,7 @@ static const char * const CAL_TYPES[] = {
"islamic-umalqura",
"islamic-tbla",
"islamic-rgsa",
"myanmar",
nullptr
};

Expand Down
2 changes: 1 addition & 1 deletion icu4c/source/test/depstest/dependencies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions icu4c/source/test/intltest/callimts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading