ICU4C/ICU4J API proposal: Day of Month names

2 views
Skip to first unread message

Rich Gillam

unread,
Jun 3, 2026, 10:47:28 PM (7 days ago) Jun 3
to icu-design

Hi everybody--


I would like to propose the following API for: ICU 79

Please provide feedback by: next Wednesday, 2026-jun-10

Designated API reviewer: Markus

Ticket: https://unicode-org.atlassian.net/browse/ICU-23364

Pull request: https://github.com/unicode-org/icu/pull/4010


https://unicode-org.atlassian.net/browse/CLDR-7408 added new dayOfMonths resources to CLDR, along with a spec change (that may not have landed yet) to treat “ddd” in a date formatting pattern as asking to use the dayOfMonths resource for the date’s day field instead of using a number.


The formatting API doesn’t change, other than the change in meaning of “ddd” in a pattern or skeleton, but we also need to add new API to DateFormatSymbols to access the new day-of-month names.  In C++, we would add the following to the DateFormatSymbols definition in i18n/unicode/dtfmtsym.h::


    /**

     * Gets day-of-month ordinal name format patterns by width and context.

     * The returned array is indexed by StandardPlural::Form (see standardplural.h);

     * its length is always StandardPlural::COUNT.  An empty entry means no data for that

     * plural category.  Currently only FORMAT context and ABBREVIATED width are

     * supported; other combinations return nullptr.

     * @param context  The formatting context.  Currently only FORMAT is supported.

     * @param width    The width.  Currently only ABBREVIATED is supported.

     * @return the day-of-month ordinal name strings, or nullptr if not available.

     *         (DateFormatSymbols retains ownership.)

     * @draft ICU 79

     */

    U_I18N_API const UnicodeString* getDayOfMonthOrdinalNames(DtContextType context,

                                                              DtWidthType width) const;

    /**

     * Sets day-of-month ordinal name format patterns by width and context.

     * Currently only FORMAT context and ABBREVIATED width are supported;

     * other combinations are silently ignored.

     * @param names    The new strings, indexed by StandardPlural::Form.

     *                 (not adopted; caller retains ownership)

     * @param count    The length of the array.

     * @param context  The formatting context.  Currently only FORMAT is supported.

     * @param width    The width.  Currently only ABBREVIATED is supported.

     * @draft ICU 79

     */

    U_I18N_API void setDayOfMonthOrdinalNames(const UnicodeString* names,

                                              int32_t count,

                                              DtContextType context,

                                              DtWidthType width);

    /**

     * Gets day-of-month type-specific name strings by width and context.

     * The returned array has length 33 and is indexed by day-of-month (1-32);

     * index 0 is unused.  An empty entry means no type-specific override for

     * that day number.  Currently only FORMAT context and ABBREVIATED width are

     * supported; other combinations return nullptr.

     * @param count    Filled in with the length of the array (33).

     * @param context  The formatting context.  Currently only FORMAT is supported.

     * @param width    The width.  Currently only ABBREVIATED is supported.

     * @return the day-of-month type-specific strings, or nullptr if not available.

     *         (DateFormatSymbols retains ownership.)

     * @draft ICU 79

     */

    U_I18N_API const UnicodeString* getDayOfMonthTypeNames(int32_t& count,

                                                           DtContextType context,

                                                           DtWidthType width) const;

    /**

     * Sets day-of-month type-specific name strings by width and context.

     * Currently only FORMAT context and ABBREVIATED width are supported;

     * other combinations are silently ignored.

     * @param names    The new strings (length 33, indexed by day-of-month 1-32;

     *                 use an empty UnicodeString for days without a specific override).

     *                 (not adopted; caller retains ownership)

     * @param count    The length of the array.

     * @param context  The formatting context.  Currently only FORMAT is supported.

     * @param width    The width.  Currently only ABBREVIATED is supported.

     * @draft ICU 79

     */

    U_I18N_API void setDayOfMonthTypeNames(const UnicodeString* names,

                                           int32_t count,

                                           DtContextType context,

                                           DtWidthType width);


In C, we add two new enum constants to UDateFormatSymbolType:


    /**

     * Day-of-month ordinal name patterns (e.g. "{0}st", "{0}nd"),

     * indexed by StandardPlural::Form (0 = ZERO ... 7 = EQ_1).

     * @draft ICU 79

     */

    UDAT_DAY_OF_MONTH_ORDINAL_NAMES,

    /**

     * Day-of-month type name strings, indexed by day number

     * (entries 1-32; entry 0 is unused/empty).

     * @draft ICU 79

     */

    UDAT_DAY_OF_MONTH_TYPE_NAMES,


In Java, we add the same new methods to DateFormatSymbols:


/**

* Gets day-of-month ordinal name format patterns by width and context.

* The returned array is indexed by {@link com.ibm.icu.impl.StandardPlural} ordinal;

* its length is {@link com.ibm.icu.impl.StandardPlural#COUNT}. An empty entry means

* no data for that plural category. Currently only FORMAT context and ABBREVIATED

* width are supported; other combinations return null.

*

* @param context The formatting context. Currently only FORMAT is supported.

* @param width   The width. Currently only ABBREVIATED is supported.

* @return the day-of-month ordinal name strings, or null if not available.

* @draft ICU 79

*/

public String[] getDayOfMonthOrdinalNames(int context, int width) {

}


/**

* Sets day-of-month ordinal name format patterns by width and context.

* Currently only FORMAT context and ABBREVIATED width are supported;

* other combinations are silently ignored.

*

* @param names   The new strings, indexed by {@link com.ibm.icu.impl.StandardPlural} ordinal.

* @param context The formatting context. Currently only FORMAT is supported.

* @param width   The width. Currently only ABBREVIATED is supported.

* @draft ICU 79

*/

public void setDayOfMonthOrdinalNames(String[] names, int context, int width) {

}


/**

* Gets day-of-month type-specific name strings by width and context.

* The returned array has length 33 and is indexed by day-of-month (1-32);

* index 0 is unused. An empty entry means no type-specific override for that

* day number. Currently only FORMAT context and ABBREVIATED width are

* supported; other combinations return null.

*

* @param context The formatting context. Currently only FORMAT is supported.

* @param width   The width. Currently only ABBREVIATED is supported.

* @return the day-of-month type-specific strings, or null if not available.

* @draft ICU 79

*/

public String[] getDayOfMonthTypeNames(int context, int width) {

}


/**

* Sets day-of-month type-specific name strings by width and context.

* Currently only FORMAT context and ABBREVIATED width are supported;

* other combinations are silently ignored.

*

* @param names   The new strings (length 33, indexed by day-of-month 1-32;

*                use null or empty for days without a specific override).

* @param context The formatting context. Currently only FORMAT is supported.

* @param width   The width. Currently only ABBREVIATED is supported.

* @draft ICU 79

*/

public void setDayOfMonthTypeNames(String[] names, int context, int width) {

}


Mark Davis Ⓤ

unread,
Jun 3, 2026, 11:48:33 PM (7 days ago) Jun 3
to Rich Gillam, icu-design
Looks reasonable, if it is more convenient to use arrays. 

Is the array  always of length 6*, and indexed by plural category: zero -> 0, one -> 1, two -> 2, few -> 3, many -> 4, other -> 5?

* until such time as we add another plural category (hopefully never)

--
You received this message because you are subscribed to the Google Groups "icu-design" group.
To unsubscribe from this group and stop receiving emails from it, send an email to icu-design+...@unicode.org.
To view this discussion visit https://groups.google.com/a/unicode.org/d/msgid/icu-design/94CFE6C4-6CBF-4437-980B-DF6D6C25C362%40apple.com.
For more options, visit https://groups.google.com/a/unicode.org/d/optout.

Rich Gillam

unread,
Jun 4, 2026, 11:35:09 AM (6 days ago) Jun 4
to Mark Davis Ⓤ, icu-design
Mark--

Looks reasonable, if it is more convenient to use arrays. 

I _think_ it’s more convenient.  Mostly I was trying to stick with precedent as much as I could, and splitting the day names out into two arrays seemed the simplest way to do that.

Is the array  always of length 6*, and indexed by plural category: zero -> 0, one -> 1, two -> 2, few -> 3, many -> 4, other -> 5?

* until such time as we add another plural category (hopefully never)

Yes, exactly.

—Rich

Mark Davis Ⓤ

unread,
Jun 4, 2026, 12:44:51 PM (6 days ago) Jun 4
to Rich Gillam, icu-design
If that's the precedent, I have no objections.

Rich Gillam

unread,
Jun 4, 2026, 1:23:16 PM (6 days ago) Jun 4
to Mark Davis Ⓤ, icu-design
This got a lot of discussion in today’s ICU TC meeting, and the consensus, for a bunch of reasons, was to take the new functions out of the public API.  There’s a lot of agreement that DateFormatSymbols sucks in general and that we should find a way to redesign it (maybe by redesigning DateFormat too, and creating a new DateFormatter, sort of like we did with NumberFormatter years ago).  If you don’t need the setters, you can get the ordinal names by just formatting stuff, and we can improve the API design and performance and memory usage of DateFormatSymbols later without it holding up this PR.

—Rich

Mark Davis Ⓤ

unread,
Jun 4, 2026, 1:40:19 PM (6 days ago) Jun 4
to Rich Gillam, icu-design
Sounds good to me. 
Reply all
Reply to author
Forward
0 new messages