Skip to content
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

CLDR-16933 Allow names for noon, midnight to match adjacent non-fixed dayPeriods; add tests & spec note #3857

Merged
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
4 changes: 3 additions & 1 deletion docs/ldml/tr35-dates.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,9 @@ The former `am`/`pm` elements have been deprecated, and replaced by the more fle

These behave like months, days, and so on in terms of having context and width. Each locale has an associated dayPeriodRuleSet in the supplemental data, rules that specify when the day periods start and end for that locale. Each type in the rules needs to have a translation in a dayPeriod (but if translation data is missing for a particular variable dayPeriod in the locale’s language and script, formatting should fall back to using the am/pm values). For more information, see _[Day Period Rules](#Day_Period_Rules)_.

The dayPeriod names should be distinct within each of the context/width combinations, including narrow; as with era names, there is less disambiguating information for them, and they are more likely to be used in a format that requires parsing. In some unambiguous cases, it is acceptable for certain overlapping dayPeriods to be the same, such as the names for "am" and "morning", or the names for "pm" and "afternoon".
The dayPeriod names should be distinct within each of the context/width combinations, including narrow; as with era names, there is less disambiguating information for them, and they are more likely to be used in a format that requires parsing. In some unambiguous cases, it is acceptable for certain overlapping dayPeriods to be the same, such as the names for `am` and `morning`, or the names for `pm` and `afternoon`.

If dayPeriods are specified for `noon` and `midnight`, they can often be formatted without also specifying the numeric time, e.g. "May 6, noon" instead of "May 6, 12:00 noon" or "May 6, 12:00 PM". To prevent parse issues, this should only be done if the names for `noon` and `midnight` are not also used for any other day periods, such as for `morning2` or `night1`.

Example:

Expand Down
6 changes: 4 additions & 2 deletions docs/ldml/tr35.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
|Version|46 (draft)|
|-------|----------|
|Editors|Mark Davis (<a href="mailto:[email protected]">[email protected]</a>) and <a href="tr35.md#Acknowledgments">other CLDR committee members</a>|
|Date|2024-04-22|
|Date|2024-07-08|
|This Version|<a href="https://www.unicode.org/reports/tr35/tr35-73/tr35.html">https://www.unicode.org/reports/tr35/tr35-73/tr35.html</a>|
|Previous Version|<a href="https://www.unicode.org/reports/tr35/tr35-72/tr35.html">https://www.unicode.org/reports/tr35/tr35-72/tr35.html</a>|
|Latest Version|<a href="https://www.unicode.org/reports/tr35/">https://www.unicode.org/reports/tr35/</a>|
Expand Down Expand Up @@ -4095,7 +4095,9 @@ Other contributors to CLDR are listed on the [CLDR Project Page](https://www.uni

**Differences from LDML Version 45**

(in progress)
* Part 4: [Dates](tr35-dates.md#Contents)
* In [Element dayPeriods](tr35-dates.md#dayPeriods), added a note on special formatting usable with
dayPeriods `noon` and `midnight`.

**Differences from LDML Version 44.1**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,9 @@ && isTooMuchWiderThan(value, abbrValue)
final boolean isDayPeriod = path.contains("dayPeriod");
if (isDayPeriod) {
XPathParts parts = XPathParts.getFrozenInstance(fullPath);
type = Type.fromString(parts.getAttributeValue(5, "type"));
type =
Type.fromString(
parts.getAttributeValue(5, "type")); // format, stand-alone
dayPeriod = DayPeriod.valueOf(parts.getAttributeValue(-1, "type"));
}

Expand Down Expand Up @@ -577,7 +579,10 @@ && isTooMuchWiderThan(value, abbrValue)
}
if (isDayPeriod) {
// ldml/dates/calendars/calendar[@type="gregorian"]/dayPeriods/dayPeriodContext[@type="format"]/dayPeriodWidth[@type="wide"]/dayPeriod[@type="am"]
Type itemType = Type.fromString(itemParts.getAttributeValue(5, "type"));
Type itemType =
Type.fromString(
itemParts.getAttributeValue(
5, "type")); // format, stand-alone
DayPeriod itemDayPeriod =
DayPeriod.valueOf(itemParts.getAttributeValue(-1, "type"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,42 @@ public boolean collisionIsError(
}
}

// Fix for CLDR-16933, for format types only
// Let midnight match a non-fixed period that starts at, ends at, or contains midnight (both
// versions);
// Let noon match a non-fixed period that starts at, ends at, or contains noon (or just
// before noon);
if (type1 == Type.format && type2 == Type.format) {
if (dayPeriod1 == DayPeriod.midnight && !dayPeriod2.isFixed()) {
for (Span s : dayPeriodsToSpans.get(dayPeriod2)) {
if (s.contains(MIDNIGHT) || s.contains(DAY_LIMIT)) {
return false;
}
}
}
if (dayPeriod2 == DayPeriod.midnight && !dayPeriod1.isFixed()) {
for (Span s : dayPeriodsToSpans.get(dayPeriod1)) {
if (s.contains(MIDNIGHT) || s.contains(DAY_LIMIT)) {
return false;
}
}
}
if (dayPeriod1 == DayPeriod.noon && !dayPeriod2.isFixed()) {
for (Span s : dayPeriodsToSpans.get(dayPeriod2)) {
if (s.contains(NOON) || s.contains(NOON - 1)) {
return false;
}
}
}
if (dayPeriod2 == DayPeriod.noon && !dayPeriod1.isFixed()) {
for (Span s : dayPeriodsToSpans.get(dayPeriod1)) {
if (s.contains(NOON) || s.contains(NOON - 1)) {
return false;
}
}
}
}

// we use the more lenient if they are mixed types
if (type2 == Type.format) {
type1 = Type.format;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,48 @@ public void TestDotPixel14031() {
checkDisplayCollisions("de", pathValuePairs, factory);
}

public void checkDayPeriodCollisions() {
// CLDR-16933 (uk, ...)
// Let midnight match a non-fixed period that starts at, ends at, or contains midnight (both
// versions);
// Let noon match a non-fixed period that starts at, ends at, or contains noon (or just
// before noon);
Map<String, String> ukPathValuePairs =
ImmutableMap.of(
"ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\"format\"]/dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"midnight\"]",
"ночі",
"ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\"format\"]/dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"night1\"]",
"ночі",
"ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\"format\"]/dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"noon\"]",
"дня",
"ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\"format\"]/dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"afternoon1\"]",
"дня");
TestFactory ukFactory = makeFakeCldrFile("uk", ukPathValuePairs);
checkDisplayCollisions("uk", ukPathValuePairs, ukFactory);

// CLDR-17132 (fr, ...)
// Let night1 have the same name as morning1/am if night1 starts at 00:00
Map<String, String> frPathValuePairs =
ImmutableMap.of(
"ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\"format\"]/dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"morning1\"]",
"matin",
"ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\"format\"]/dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"night1\"]",
"matin");
TestFactory frFactory = makeFakeCldrFile("fr", frPathValuePairs);
checkDisplayCollisions("fr", frPathValuePairs, frFactory);

// CLDR-17139 (fil, ...)
// Let night1 have the same name as evening1 if night1 ends at 24:00
Map<String, String> filPathValuePairs =
ImmutableMap.of(
"ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\"format\"]/dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"evening1\"]",
"ng gabi",
"ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\"format\"]/dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"night1\"]",
"ng gabi");
TestFactory filFactory = makeFakeCldrFile("fil", filPathValuePairs);
checkDisplayCollisions("fil", filPathValuePairs, filFactory);
}

public void checkDisplayCollisions(
String locale, Map<String, String> pathValuePairs, TestFactory factory) {
CheckDisplayCollisions cdc = new CheckDisplayCollisions(factory);
Expand Down
Loading