Skip to content

Commit ca9d724

Browse files
authored
CLDR-8260 Add range patterns for intervals (unicode-org#5608)
1 parent ea081c8 commit ca9d724

8 files changed

Lines changed: 105 additions & 31 deletions

File tree

‎common/dtd/ldml.dtd‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,7 +1646,7 @@ CLDR data files are interpreted according to the LDML specification (http://unic
16461646
<!ATTLIST appendItem references CDATA #IMPLIED >
16471647
<!--@METADATA-->
16481648

1649-
<!ELEMENT intervalFormats ( alias | ( intervalFormatFallback*, intervalFormatItem*, special* ) ) >
1649+
<!ELEMENT intervalFormats ( alias | ( intervalFormatRanges*, intervalFormatFallback*, intervalFormatItem*, special* ) ) >
16501650
<!ATTLIST intervalFormats alt NMTOKENS #IMPLIED >
16511651
<!--@MATCH:literal/variant-->
16521652
<!ATTLIST intervalFormats draft (approved | contributed | provisional | unconfirmed) #IMPLIED >
@@ -1658,6 +1658,18 @@ CLDR data files are interpreted according to the LDML specification (http://unic
16581658
<!--@VALUE-->
16591659
<!--@DEPRECATED-->
16601660

1661+
<!ELEMENT intervalFormatRanges ( alias | ( intervalFormatRange*, special* ) ) >
1662+
1663+
<!ELEMENT intervalFormatRange ( #PCDATA ) >
1664+
<!ATTLIST intervalFormatRange type NMTOKEN #REQUIRED >
1665+
<!--@MATCH:literal/numeric, non-numeric, mixed -->
1666+
<!ATTLIST intervalFormatRange alt NMTOKENS #IMPLIED >
1667+
<!--@MATCH:literal/variant-->
1668+
<!ATTLIST intervalFormatRange draft (approved | contributed | provisional | unconfirmed) #IMPLIED >
1669+
<!--@METADATA-->
1670+
<!ATTLIST intervalFormatRange references CDATA #IMPLIED >
1671+
<!--@METADATA-->
1672+
16611673
<!ELEMENT intervalFormatFallback ( #PCDATA ) >
16621674
<!ATTLIST intervalFormatFallback alt NMTOKENS #IMPLIED >
16631675
<!--@MATCH:literal/variant-->
@@ -1668,7 +1680,7 @@ CLDR data files are interpreted according to the LDML specification (http://unic
16681680
<!ATTLIST intervalFormatFallback validSubLocales CDATA #IMPLIED >
16691681
<!--@VALUE-->
16701682
<!--@DEPRECATED-->
1671-
1683+
16721684
<!ELEMENT intervalFormatItem ( alias | ( greatestDifference*, special* ) ) >
16731685
<!ATTLIST intervalFormatItem id NMTOKEN #REQUIRED >
16741686
<!--@MATCH:regex/((H|h|Bh)m?(v|vvvv)?)|((G|GGGGG)?(y|yyyy)((M|MMM|MMMM)((E|EEEE)?d)?)?)|((M|MMM|MMMM)((E|EEEE)?d)?)|d-->

‎common/main/en.xml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2973,6 +2973,11 @@ annotations.
29732973
<appendItem request="Year">{0} {1}</appendItem>
29742974
</appendItems>
29752975
<intervalFormats>
2976+
<intervalFormatRanges>
2977+
<intervalFormatRange type="mixed">{0} – {1}</intervalFormatRange>
2978+
<intervalFormatRange type="numeric">{0}–{1}</intervalFormatRange>
2979+
<intervalFormatRange type="non-numeric">{0}–{1}</intervalFormatRange>
2980+
</intervalFormatRanges>
29762981
<intervalFormatFallback>{0} – {1}</intervalFormatFallback>
29772982
<intervalFormatItem id="Bh">
29782983
<greatestDifference id="B">h B – h B</greatestDifference>

‎common/main/root.xml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,9 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/
502502
<appendItem request="Year">{1} {0}</appendItem>
503503
</appendItems>
504504
<intervalFormats>
505+
<intervalFormatRanges>
506+
<alias source="locale" path="../../calendar[@type='gregorian']/dateTimeFormats/intervalFormats/intervalFormatRanges"/>
507+
</intervalFormatRanges>
505508
<intervalFormatFallback>{0} – {1}</intervalFormatFallback>
506509
<intervalFormatItem id="Bh">
507510
<greatestDifference id="B">h B – h B</greatestDifference>
@@ -1038,6 +1041,9 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/
10381041
<appendItem request="Year">{1} {0}</appendItem>
10391042
</appendItems>
10401043
<intervalFormats>
1044+
<intervalFormatRanges>
1045+
<alias source="locale" path="../../calendar[@type='gregorian']/dateTimeFormats/intervalFormats/intervalFormatRanges"/>
1046+
</intervalFormatRanges>
10411047
<intervalFormatFallback>{0} – {1}</intervalFormatFallback>
10421048
<intervalFormatItem id="Bh">
10431049
<greatestDifference id="B">h B – h B</greatestDifference>
@@ -1522,6 +1528,11 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/
15221528
<appendItem request="Year">{1} {0}</appendItem>
15231529
</appendItems>
15241530
<intervalFormats>
1531+
<intervalFormatRanges>
1532+
<intervalFormatRange type="mixed">{0} – {1}</intervalFormatRange>
1533+
<intervalFormatRange type="numeric">{0}–{1}</intervalFormatRange>
1534+
<intervalFormatRange type="non-numeric">{0}–{1}</intervalFormatRange>
1535+
</intervalFormatRanges>
15251536
<intervalFormatFallback>{0} – {1}</intervalFormatFallback>
15261537
<intervalFormatItem id="Bh">
15271538
<greatestDifference id="B">h B – h B</greatestDifference>
@@ -2184,6 +2195,9 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/
21842195
<appendItem request="Year">{1} {0}</appendItem>
21852196
</appendItems>
21862197
<intervalFormats>
2198+
<intervalFormatRanges>
2199+
<alias source="locale" path="../../calendar[@type='gregorian']/dateTimeFormats/intervalFormats/intervalFormatRanges"/>
2200+
</intervalFormatRanges>
21872201
<intervalFormatFallback>{0} – {1}</intervalFormatFallback>
21882202
<intervalFormatItem id="Bh">
21892203
<greatestDifference id="B">h B – h B</greatestDifference>

‎common/supplemental/coverageLevels.xml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,9 @@ For terms of use, see http://www.unicode.org/copyright.html
423423
<coverageLevel value="basic" match="dates/calendars/calendar[@type='gregorian']/dateTimeFormats/intervalFormats/intervalFormatFallback"/>
424424
<coverageLevel value="moderate" match="dates/calendars/calendar[@type='generic']/dateTimeFormats/intervalFormats/intervalFormatFallback"/>
425425

426+
<coverageLevel value="moderate" match="dates/calendars/calendar[@type='gregorian']/dateTimeFormats/intervalFormats/intervalFormatRanges/intervalFormatRange[@type='%A']"/>
427+
<coverageLevel value="moderate" match="dates/calendars/calendar[@type='generic']/dateTimeFormats/intervalFormats/intervalFormatRanges/intervalFormatRange[@type='%A']"/>
428+
426429
<coverageLevel value="basic" match="dates/calendars/calendar[@type='gregorian']/dateTimeFormats/availableFormats/dateFormatItem[@id='%basicDateSkeletons']"/>
427430
<coverageLevel value="moderate" match="dates/calendars/calendar[@type='gregorian']/dateTimeFormats/availableFormats/dateFormatItem[@id='%anyAttribute']"/>
428431

‎tools/cldr-code/src/main/java/org/unicode/cldr/test/ExampleGenerator.java‎

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,35 +1777,65 @@ private void handleMiscPatterns(XPathParts parts, String value, List<String> exa
17771777
}
17781778

17791779
private void handleIntervalFormats(XPathParts parts, String value, List<String> examples) {
1780-
if (parts.getElement(6).equals("intervalFormatFallback")) {
1781-
SimpleDateFormat dateFormat = new SimpleDateFormat();
1782-
String fallbackFormat = invertBackground(setBackground(value));
1783-
examples.add(
1784-
format(
1785-
fallbackFormat,
1786-
dateFormat.format(FIRST_INTERVAL),
1787-
dateFormat.format(SECOND_INTERVAL.get("y"))));
1788-
return;
1780+
switch (parts.getElement(6)) {
1781+
case "intervalFormatFallback":
1782+
{
1783+
SimpleDateFormat dateFormat = new SimpleDateFormat();
1784+
String formatted =
1785+
getFormattedInterval(
1786+
value,
1787+
dateFormat.format(FIRST_INTERVAL),
1788+
dateFormat.format(SECOND_INTERVAL.get("y")));
1789+
examples.add(formatted);
1790+
break;
1791+
}
1792+
case "intervalFormatRanges":
1793+
String formatted = "";
1794+
switch (parts.getAttributeValue(-1, "type")) {
1795+
case "mixed":
1796+
formatted = getFormattedInterval(value, "1 March", "13 April");
1797+
break;
1798+
case "numeric":
1799+
formatted = getFormattedInterval(value, "1", "23");
1800+
break;
1801+
case "non-numeric":
1802+
formatted = getFormattedInterval(value, "March", "April");
1803+
break;
1804+
}
1805+
examples.add(formatted);
1806+
break;
1807+
default:
1808+
{
1809+
addIntervalExample(FIRST_INTERVAL, SECOND_INTERVAL, parts, value, examples);
1810+
addIntervalExample(FIRST_INTERVAL2, SECOND_INTERVAL2, parts, value, examples);
1811+
Set<String> relatedPatterns =
1812+
RelatedDatePathValues.getRelatedPathValues(cldrFile, parts);
1813+
if (!relatedPatterns.isEmpty()) {
1814+
examples.add("Related Flexible Dates:");
1815+
for (String pattern : relatedPatterns) {
1816+
SimpleDateFormat sdf =
1817+
icuServiceBuilder.getDateFormat(
1818+
parts.getAttributeValue(
1819+
RelatedDatePathValues.calendarElement, "type"),
1820+
pattern);
1821+
examples.add(sdf.format(FIRST_INTERVAL));
1822+
examples.add(sdf.format(FIRST_INTERVAL2));
1823+
}
1824+
}
1825+
// de-dup, just in case
1826+
LinkedHashSet<String> dedup = new LinkedHashSet<>(examples);
1827+
examples.clear();
1828+
examples.addAll(dedup);
1829+
break;
1830+
}
17891831
}
1790-
addIntervalExample(FIRST_INTERVAL, SECOND_INTERVAL, parts, value, examples);
1791-
addIntervalExample(FIRST_INTERVAL2, SECOND_INTERVAL2, parts, value, examples);
1792-
Set<String> relatedPatterns = RelatedDatePathValues.getRelatedPathValues(cldrFile, parts);
1793-
if (!relatedPatterns.isEmpty()) {
1794-
examples.add("Related Flexible Dates:");
1795-
for (String pattern : relatedPatterns) {
1796-
SimpleDateFormat sdf =
1797-
icuServiceBuilder.getDateFormat(
1798-
parts.getAttributeValue(
1799-
RelatedDatePathValues.calendarElement, "type"),
1800-
pattern);
1801-
examples.add(sdf.format(FIRST_INTERVAL));
1802-
examples.add(sdf.format(FIRST_INTERVAL2));
1803-
}
1804-
}
1805-
// de-dup, just in case
1806-
LinkedHashSet<String> dedup = new LinkedHashSet<>(examples);
1807-
examples.clear();
1808-
examples.addAll(dedup);
1832+
}
1833+
1834+
private String getFormattedInterval(
1835+
String value, String firstOfInterval, String secondOfInterval) {
1836+
String fallbackFormat = invertBackground(setBackground(value));
1837+
String formatted = format(fallbackFormat, firstOfInterval, secondOfInterval);
1838+
return formatted;
18091839
}
18101840

18111841
private void addIntervalExample(

‎tools/cldr-code/src/main/java/org/unicode/cldr/test/RelatedDatePathValues.java‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ public static Set<String> getRelatedPathValues(CLDRFile cldrFile, XPathParts xpa
4747
case "availableFormats":
4848
return forAvailable(cldrFile, xparts);
4949
case "intervalFormats":
50-
return forInterval(cldrFile, xparts);
50+
if ("intervalFormatItem".equals(xparts.getElement(6))) {
51+
return forInterval(cldrFile, xparts);
52+
}
53+
break;
5154
default:
5255
break;
5356
}

‎tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@
144144
//ldml/dates/calendars/calendar[@type="(gregorian|iso8601)"]/dateTimeFormats/appendItems/appendItem[@request="(Timezone)"] ; DateTime ; &calendar($1) ; &calField(Formats:Flexible:Append) ; $2 ; LTR_ALWAYS
145145
//ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/appendItems/appendItem[@request="(Timezone)"] ; Special ; Suppress ; &calendar($1) ; &calField(Formats:Flexible:Append)-$2 ; HIDE
146146

147+
//ldml/dates/calendars/calendar[@type="%N"]/dateTimeFormats/intervalFormats/intervalFormatRanges/intervalFormatRange[@type="%A"] ; DateTime ; &calendar($1) ; &calField(Formats:Intervals:Range) ; $2 ; LTR_ALWAYS
148+
//ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/intervalFormats/intervalFormatRanges/intervalFormatRange[@type="%A"] ; Special ; Suppress ; &calendar($1) ; &calField(Formats:Intervals:Range)-$2 ; HIDE
149+
147150
//ldml/dates/calendars/calendar[@type="%N"]/dateTimeFormats/intervalFormats/intervalFormatFallback ; DateTime ; &calendar($1) ; &calField(Formats:Intervals:Fallback) ; Fallback ; LTR_ALWAYS
148151
//ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/intervalFormats/intervalFormatFallback ; Special ; Suppress ; &calendar($1) ; &calField(Formats:Intervals:Fallback)-Fallback ; HIDE
149152

‎tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/Placeholders.txt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@
154154
^//ldml/dates/calendars/calendar\[@type="%A"]/dateTimeFormats/appendItems/appendItem\[@request="(Month)"] ; {0}=BASE_FORMAT Monday, January 23; {1}=APPEND_FIELD_FORMAT February; {2}=APPEND_FIELD_NAME $1
155155
^//ldml/dates/calendars/calendar\[@type="%A"]/dateTimeFormats/appendItems/appendItem\[@request="(Minute|Second)"] ; {0}=BASE_FORMAT Monday, January 23; {1}=APPEND_FIELD_FORMAT 53; {2}=APPEND_FIELD_NAME $1
156156

157+
^//ldml/dates/calendars/calendar\[@type="%A"]/dateTimeFormats/intervalFormats/intervalFormatRanges/intervalFormatRange\[@type="numeric"] ; {0}=START_DATE_OR_TIME 9; {1}=END_DATE_OR_TIME 12
158+
^//ldml/dates/calendars/calendar\[@type="%A"]/dateTimeFormats/intervalFormats/intervalFormatRanges/intervalFormatRange\[@type="non-numeric"] ; {0}=START_DATE_OR_TIME January; {1}=END_DATE_OR_TIME March
159+
^//ldml/dates/calendars/calendar\[@type="%A"]/dateTimeFormats/intervalFormats/intervalFormatRanges/intervalFormatRange\[@type="mixed"] ; {0}=START_DATE_OR_TIME January 9; {1}=END_DATE_OR_TIME March 12
160+
157161
^//ldml/dates/calendars/calendar\[@type="%A"]/dateTimeFormats/intervalFormats/intervalFormatFallback ; {0}=START_DATE_OR_TIME Nov 10; {1}=END_DATE_OR_TIME Dec 10
158162
^//ldml/dates/calendars/calendar\[@type="%A"]/monthPatterns/monthPatternContext\[@type="%A"]/monthPatternWidth\[@type="%A"]/monthPattern\[@type="%A"] ; {0}=CHINESE_CALENDAR_MONTH_NAME Month4
159163

0 commit comments

Comments
 (0)