From 928ed1a63c5177425db60c2cfb09ec38d79f59ac Mon Sep 17 00:00:00 2001 From: macchiati Date: Tue, 10 Sep 2024 14:53:06 -0700 Subject: [PATCH 1/8] CLDR-17892 ISO 8601 calendar --- common/main/root.xml | 307 ++++++++++++++++++ .../unicode/cldr/unittest/TestDateOrder.java | 179 +++++++++- 2 files changed, 485 insertions(+), 1 deletion(-) diff --git a/common/main/root.xml b/common/main/root.xml index d398b8c2dc2..8c484d4bab7 100644 --- a/common/main/root.xml +++ b/common/main/root.xml @@ -1936,6 +1936,313 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ + + + + + + + + + + + + + + + + + + + + y MMMM d + yMMMMd, EEEE + + + + + y MMMM d + yMMMMd + + + + + y MMM d + yMMMd + + + + + y-MM-dd + yMMdd + + + + + + + HH:mm:ss zzzz + HHmmsszzzz + + + + + HH:mm:ss z + HHmmssz + + + + + HH:mm:ss + HHmmss + + + + + HH:mm + HHmm + + + + + + + {1} {0} + + + + + + + + {1} {0} + + + + + + + + {1} {0} + + + + + + + + {1} {0} + + + + + + + h B + h:mm B + h:mm:ss B + d + ccc + E h:mm B + E h:mm:ss B + d, E + E HH:mm + E HH:mm + E HH:mm:ss + E HH:mm:ss + y + y-MM-dd + y MMM + y MMM d + y MMM d, E + HH + HH + HH:mm + HH:mm + HH:mm:ss + HH:mm:ss + HH:mm:ss v + HH:mm:ss v + HH:mm v + HH:mm v + L + MM-dd + MM-dd, E + LLL + MMM d + MMM d + MMMM d + MMMM 'week' W + mm:ss + y + y-MM + y-MM-dd + y-MM-dd, E + y MMM + y MMM d + y MMM d + y MMMM + y QQQ + y QQQQ + Y 'week' w + + + {0} ({2}: {1}) + {0} {1} + {1} {0} + {0} ({2}: {1}) + {0} ({2}: {1}) + {0} ({2}: {1}) + {0} ({2}: {1}) + {0} ({2}: {1}) + {0} {1} + {0} ({2}: {1}) + {1} {0} + + + {0} – {1} + + h B – h B + h–h B + + + h:mm B – h:mm B + h:mm–h:mm B + h:mm–h:mm B + + + d–d + + + y – y + y–y + + + y-MM – y-MM + y-MM – y-MM + y-MM – y-MM + + + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + + + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – GGGGG y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + + + y MMM – G y MMM + y MMM–MMM + y MMM – y MMM + + + y MMM d–d + y MMM d – y MMM d + y MMM d – MMM d + y MMM d – y MMM d + + + y MMM d, E – MMM d, E + y MMM d, E – y MMM d, E + y MMM d, E – MMM d, E + y MMM d, E – y MMM d, E + + + HH–HH + HH–HH + + + HH–HH + + + HH:mm–HH:mm + HH:mm–HH:mm + HH:mm–HH:mm + + + HH:mm–HH:mm + HH:mm–HH:mm + + + HH:mm–HH:mm v + HH:mm–HH:mm v + HH:mm–HH:mm v + + + HH:mm–HH:mm v + HH:mm–HH:mm v + + + HH–HH v + HH–HH v + + + HH–HH v + + + MM–MM + + + MM-dd – MM-dd + MM-dd – MM-dd + + + MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E + + + LLL–LLL + + + MMM d–d + MMM d – MMM d + + + MMM d, E – MMM d, E + MMM d, E – MMM d, E + + + y–y + + + y-MM – y-MM + y-MM – y-MM + + + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + + + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + + + y MMM–MMM + y MMM – y MMM + + + y MMM d–d + y MMM d – MMM d + y MMM d – y MMM d + + + y MMM d, E – MMM d, E + y MMM d, E – MMM d, E + y MMM d, E – y MMM d, E + + + y MMMM–MMMM + y MMMM – y MMMM + + + + diff --git a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java index e6650b0b38e..9b1aaaba9ae 100644 --- a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java +++ b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java @@ -1,16 +1,33 @@ package org.unicode.cldr.unittest; +import com.google.common.base.Joiner; import com.ibm.icu.dev.test.TestFmwk; import com.ibm.icu.text.DateTimePatternGenerator; +import com.ibm.icu.text.DateTimePatternGenerator.VariableField; +import com.ibm.icu.text.SimpleDateFormat; +import com.ibm.icu.text.UnicodeSet; +import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; import org.unicode.cldr.test.DateOrder; +import org.unicode.cldr.util.CLDRConfig; import org.unicode.cldr.util.CLDRFile; +import org.unicode.cldr.util.CLDRLocale; +import org.unicode.cldr.util.ICUServiceBuilder; +import org.unicode.cldr.util.PathHeader; +import org.unicode.cldr.util.PathHeader.Factory; import org.unicode.cldr.util.SimpleXMLSource; import org.unicode.cldr.util.XMLSource; +import org.unicode.cldr.util.XPathParts; public class TestDateOrder extends TestFmwk { + private static final Joiner JOIN_TAB = Joiner.on('\t'); + public static void main(String[] args) { new TestDateOrder().run(args); } @@ -51,7 +68,7 @@ public void TestDateImportance() { source.putValueAtPath(fullDate, "EEEE, y MMMM dd"); order = DateOrder.getOrderingInfo(cldrFile, cldrFile, fp); - values = new HashSet(order.get(fullDate).values()); // filter + values = new HashSet<>(order.get(fullDate).values()); // filter // duplicates assertEquals("There should be a conflict with other date values", 1, values.size()); assertTrue("No conflict with long date", values.contains(longDate)); @@ -68,4 +85,164 @@ public void TestDateImportance() { assertTrue("Available format conflict not found", values.contains(availableFormat)); assertTrue("Date format conflict not found", values.contains(fullDate)); } + + static final String stockPathPrefix = + "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateFormats/dateFormatLength"; + static final String availableFormatPathPrefix = + "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/availableFormats/dateFormatItem"; + static final String intervalFormatPathPrefix = + "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/intervalFormats/"; + + public void TestIso8601() { + ICUServiceBuilder isb = ICUServiceBuilder.forLocale(CLDRLocale.getInstance("en")); + CLDRFile english = CLDRConfig.getInstance().getEnglish(); + Factory phf = PathHeader.getFactory(); + Set paths = new TreeSet<>(); + for (String path : english) { + if (!path.startsWith("//ldml/dates/calendars/calendar[@type=\"gregorian\"]")) { + continue; + } else if (path.startsWith(stockPathPrefix)) { + if (!path.contains("datetimeSkeleton")) { + paths.add(phf.fromPath(path)); + } + } else if (path.startsWith(availableFormatPathPrefix)) { + paths.add(phf.fromPath(path)); + } else if (path.startsWith(intervalFormatPathPrefix)) { + if (!path.contains("intervalFormatFallback")) { + paths.add(phf.fromPath(path)); + } + } else { + int debug = 0; + } + } + Date sample = new Date(2024 - 1900, 0, 9, 19, 8, 9); + System.out.println(); + for (PathHeader pathHeader : paths) { + final String originalPath = pathHeader.getOriginalPath(); + String gregPat = english.getStringValue(originalPath); + String isoPat = + english.getStringValue(originalPath.replace("\"gregorian\"", "\"iso8601\"")); + String gregFormatted = null; + String isoFormatted = null; + + if (originalPath.contains("intervalFormats")) { + Date sample1 = (Date) sample.clone(); + Date sample2 = (Date) sample.clone(); + XPathParts parts = XPathParts.getFrozenInstance(originalPath); + String greatestDifference = parts.getAttributeValue(-1, "id"); + + switch (greatestDifference) { + case "G": + sample1.setYear(-sample2.getYear()); + break; + case "y": + sample2.setYear(sample2.getYear() + 1); + break; + case "M": + sample2.setMonth(sample2.getMonth() + 1); + break; + case "d": + sample2.setDate(sample2.getDate() + 1); + break; + case "h": + case "H": + sample2.setHours(sample2.getHours() + 1); + break; + case "a": + case "B": + sample2.setHours(sample2.getHours() + 12); + break; + case "m": + sample2.setMinutes(sample2.getMinutes() + 1); + break; + case "s": + sample2.setSeconds(sample2.getSeconds() + 1); + break; + default: + System.out.println("Missing" + greatestDifference); + break; + } + + gregFormatted = formatInterval(isb, sample1, sample2, gregPat); + isoFormatted = formatInterval(isb, sample1, sample2, isoPat); + } else { + SimpleDateFormat gregFormat = isb.getDateFormat("gregorian", gregPat); + SimpleDateFormat isoFormat = isb.getDateFormat("iso8601", isoPat); + + gregFormatted = gregFormat.format(sample); + isoFormatted = isoFormat.format(sample); + } + System.out.println( + JOIN_TAB.join( + pathHeader.getCode(), gregPat, gregFormatted, isoPat, isoFormatted)); + } + } + + public String formatInterval(ICUServiceBuilder isb, Date sample, Date sample2, String gregPat) { + List parts = splitIntervalPattern(gregPat); + SimpleDateFormat gregFormat1 = isb.getDateFormat("gregorian", parts.get(0)); + SimpleDateFormat gregFormat2 = isb.getDateFormat("gregorian", parts.get(2)); + return gregFormat1.format(sample) + parts.get(1) + gregFormat2.format(sample2); + } + + private List splitIntervalPattern(String intervalPattern) { + DateTimePatternGenerator.FormatParser parser = new DateTimePatternGenerator.FormatParser(); + List result = new ArrayList<>(); + StringBuilder current = new StringBuilder(); + Set soFar = new HashSet<>(); + + // we have something of the form (literal? field)* sepLiteral (field literal?)* + // that is, there are never 2 literals in a row. + // a literal is a sepLiteral if the field after it is already present (or rather, if its + // type is) + String lastString = null; + + for (Object p : parser.set(intervalPattern).getItems()) { + if (p instanceof String) { + lastString = (String) p; + } else if (p instanceof VariableField) { + VariableField pv = (VariableField) p; + if (soFar != null && soFar.contains(pv.getType())) { + // we hit the first repeated field + result.add(current.toString()); + current.setLength(0); + result.add( + lastString == null + ? "" + : lastString); // it would be strange to have "", but... + lastString = null; + soFar = null; + } else { + if (soFar != null) { + soFar.add(pv.getType()); + } + if (lastString != null) { + current.append(quoteIfNeeded(lastString)); + lastString = null; + } + } + current.append(p); + } else { + throw new IllegalArgumentException(); + } + } + if (lastString != null) { + current.append(quoteIfNeeded(lastString)); + } + result.add(current.toString()); + if (result.size() != 3) { + throw new IllegalArgumentException(); + } + return result; + } + + static final UnicodeSet VARIABLE = new UnicodeSet("[a-zA-Z']").freeze(); + + private Object quoteIfNeeded(String lastString) { + if (VARIABLE.containsSome(lastString)) { + lastString = lastString.replace("'", "''"); + lastString = "'" + lastString + "'"; + } + return lastString; + } } From ed6eac78260a07e6ccbe02503cdf468ba8c6bd2a Mon Sep 17 00:00:00 2001 From: macchiati Date: Wed, 11 Sep 2024 16:05:26 -0700 Subject: [PATCH 2/8] CLDR-17892 Updates to fix items noted by Peter, plus fixes in tests. --- common/main/root.xml | 410 +++++++++--------- .../org/unicode/cldr/util/data/PathHeader.txt | 3 + .../unicode/cldr/unittest/TestDateOrder.java | 187 +++++++- .../TestDisplayAndInputProcessor.java | 28 +- 4 files changed, 399 insertions(+), 229 deletions(-) diff --git a/common/main/root.xml b/common/main/root.xml index 8c484d4bab7..69080e8a4ed 100644 --- a/common/main/root.xml +++ b/common/main/root.xml @@ -482,11 +482,11 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ {0} – {1} - h B – h B + h B – h B h–h B - h:mm B – h:mm B + h:mm B – h:mm B h:mm–h:mm B h:mm–h:mm B @@ -494,14 +494,14 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ d–d - h a – h a - h–h a + h a – h a + h–h a HH–HH - h:mm a – h:mm a + h:mm a – h:mm a h:mm–h:mm a h:mm–h:mm a @@ -510,7 +510,7 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ HH:mm–HH:mm - h:mm a – h:mm a v + h:mm a – h:mm a v h:mm–h:mm a v h:mm–h:mm a v @@ -519,8 +519,8 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ HH:mm–HH:mm v - h a – h a v - h–h a v + h a – h a v + h–h a v HH–HH v @@ -529,58 +529,58 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ MM–MM - MM-dd – MM-dd - MM-dd – MM-dd + MM-dd – MM-dd + MM-dd – MM-dd - MM-dd, E – MM-dd, E - MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E LLL–LLL MMM d–d - MMM d – MMM d + MMM d – MMM d - MMM d, E – MMM d, E - MMM d, E – MMM d, E + MMM d, E – MMM d, E + MMM d, E – MMM d, E U–U - y-MM – y-MM - y-MM – y-MM + y-MM – y-MM + y-MM – y-MM - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd - y-MM-dd, E – y-MM-dd, E - y-MM-dd, E – y-MM-dd, E - y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E U MMM–MMM - U MMM – U MMM + U MMM – U MMM U MMM d–d - U MMM d – MMM d - U MMM d – U MMM d + U MMM d – MMM d + U MMM d – U MMM d - U MMM d, E – MMM d, E - U MMM d, E – MMM d, E - U MMM d, E – U MMM d, E + U MMM d, E – MMM d, E + U MMM d, E – MMM d, E + U MMM d, E – U MMM d, E U MMMM–MMMM - U MMMM – U MMMM + U MMMM – U MMMM @@ -956,7 +956,7 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ G y MMM G y MMM d G y MMM d, E - h a + h a HH h:mm a HH:mm @@ -998,11 +998,11 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ {0} – {1} - h B – h B + h B – h B h–h B - h:mm B – h:mm B + h:mm B – h:mm B h:mm–h:mm B h:mm–h:mm B @@ -1010,52 +1010,52 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ d–d - G y – G y + G y – G y G y–y - GGGGG y-MM – GGGGG y-MM - GGGGG y-MM – y-MM - GGGGG y-MM – y-MM + GGGGG y-MM – GGGGG y-MM + GGGGG y-MM – y-MM + GGGGG y-MM – y-MM - GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd – GGGGG y-MM-dd - GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – GGGGG y-MM-dd + GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd, E – y-MM-dd, E - GGGGG y-MM-dd, E – GGGGG y-MM-dd, E - GGGGG y-MM-dd, E – y-MM-dd, E - GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – GGGGG y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E - G y MMM – G y MMM + G y MMM – G y MMM G y MMM–MMM - G y MMM – y MMM + G y MMM – y MMM G y MMM d–d - G y MMM d – G y MMM d - G y MMM d – MMM d - G y MMM d – y MMM d + G y MMM d – G y MMM d + G y MMM d – MMM d + G y MMM d – y MMM d - G y MMM d, E – MMM d, E - G y MMM d, E – G y MMM d, E - G y MMM d, E – MMM d, E - G y MMM d, E – y MMM d, E + G y MMM d, E – MMM d, E + G y MMM d, E – G y MMM d, E + G y MMM d, E – MMM d, E + G y MMM d, E – y MMM d, E - h a – h a - h–h a + h a – h a + h–h a HH–HH - h:mm a – h:mm a + h:mm a – h:mm a h:mm–h:mm a h:mm–h:mm a @@ -1064,7 +1064,7 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ HH:mm–HH:mm - h:mm a – h:mm a v + h:mm a – h:mm a v h:mm–h:mm a v h:mm–h:mm a v @@ -1073,8 +1073,8 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ HH:mm–HH:mm v - h a – h a v - h–h a v + h a – h a v + h–h a v HH–HH v @@ -1083,58 +1083,58 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ MM–MM - MM-dd – MM-dd - MM-dd – MM-dd + MM-dd – MM-dd + MM-dd – MM-dd - MM-dd, E – MM-dd, E - MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E LLL–LLL MMM d–d - MMM d – MMM d + MMM d – MMM d - MMM d, E – MMM d, E - MMM d, E – MMM d, E + MMM d, E – MMM d, E + MMM d, E – MMM d, E G y–y - GGGGG y-MM – y-MM - GGGGG y-MM – y-MM + GGGGG y-MM – y-MM + GGGGG y-MM – y-MM - GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd, E – y-MM-dd, E - GGGGG y-MM-dd, E – y-MM-dd, E - GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E G y MMM–MMM - G y MMM – y MMM + G y MMM – y MMM G y MMM d–d - G y MMM d – MMM d - G y MMM d – y MMM d + G y MMM d – MMM d + G y MMM d – y MMM d - G y MMM d, E – MMM d, E - G y MMM d, E – MMM d, E - G y MMM d, E – y MMM d, E + G y MMM d, E – MMM d, E + G y MMM d, E – MMM d, E + G y MMM d, E – y MMM d, E G y MMMM–MMMM - G y MMMM – y MMMM + G y MMMM – y MMMM @@ -1398,7 +1398,7 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ G y MMM G y MMM d G y MMM d, E - h a + h a HH h:mm a HH:mm @@ -1445,11 +1445,11 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ {0} – {1} - h B – h B + h B – h B h–h B - h:mm B – h:mm B + h:mm B – h:mm B h:mm–h:mm B h:mm–h:mm B @@ -1457,52 +1457,52 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ d–d - G y – G y + G y – G y G y–y - GGGGG y-MM – GGGGG y-MM - GGGGG y-MM – y-MM - GGGGG y-MM – y-MM + GGGGG y-MM – GGGGG y-MM + GGGGG y-MM – y-MM + GGGGG y-MM – y-MM - GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd – GGGGG y-MM-dd - GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – GGGGG y-MM-dd + GGGGG y-MM-dd – y-MM-dd + GGGGG y-MM-dd – y-MM-dd - GGGGG y-MM-dd, E – y-MM-dd, E - GGGGG y-MM-dd, E – GGGGG y-MM-dd, E - GGGGG y-MM-dd, E – y-MM-dd, E - GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – GGGGG y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E + GGGGG y-MM-dd, E – y-MM-dd, E - G y MMM – G y MMM + G y MMM – G y MMM G y MMM–MMM - G y MMM – y MMM + G y MMM – y MMM G y MMM d–d - G y MMM d – G y MMM d - G y MMM d – MMM d - G y MMM d – y MMM d + G y MMM d – G y MMM d + G y MMM d – MMM d + G y MMM d – y MMM d - G y MMM d, E – MMM d, E - G y MMM d, E – G y MMM d, E - G y MMM d, E – MMM d, E - G y MMM d, E – y MMM d, E + G y MMM d, E – MMM d, E + G y MMM d, E – G y MMM d, E + G y MMM d, E – MMM d, E + G y MMM d, E – y MMM d, E - h a – h a - h–h a + h a – h a + h–h a HH–HH - h:mm a – h:mm a + h:mm a – h:mm a h:mm–h:mm a h:mm–h:mm a @@ -1511,7 +1511,7 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ HH:mm–HH:mm - h:mm a – h:mm a v + h:mm a – h:mm a v h:mm–h:mm a v h:mm–h:mm a v @@ -1520,8 +1520,8 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ HH:mm–HH:mm v - h a – h a v - h–h a v + h a – h a v + h–h a v HH–HH v @@ -1530,58 +1530,58 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ MM–MM - MM-dd – MM-dd - MM-dd – MM-dd + MM-dd – MM-dd + MM-dd – MM-dd - MM-dd, E – MM-dd, E - MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E LLL–LLL MMM d–d - MMM d – MMM d + MMM d – MMM d - MMM d, E – MMM d, E - MMM d, E – MMM d, E + MMM d, E – MMM d, E + MMM d, E – MMM d, E y–y - y-MM – y-MM - y-MM – y-MM + y-MM – y-MM + y-MM – y-MM - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd - y-MM-dd, E – y-MM-dd, E - y-MM-dd, E – y-MM-dd, E - y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E y MMM–MMM - y MMM – y MMM + y MMM – y MMM y MMM d–d - y MMM d – MMM d - y MMM d – y MMM d + y MMM d – MMM d + y MMM d – y MMM d - y MMM d, E – MMM d, E - y MMM d, E – MMM d, E - y MMM d, E – y MMM d, E + y MMM d, E – MMM d, E + y MMM d, E – MMM d, E + y MMM d, E – y MMM d, E y MMMM–MMMM - y MMMM – y MMMM + y MMMM – y MMMM @@ -1955,8 +1955,8 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ - y MMMM d - yMMMMd, EEEE + y MMMM d, EEEE + yMMMMEEEEd @@ -2046,24 +2046,24 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ E h:mm B E h:mm:ss B d, E - E HH:mm + E h:mm a E HH:mm - E HH:mm:ss + E h:mm:ss a E HH:mm:ss - y - y-MM-dd - y MMM - y MMM d - y MMM d, E - HH + G y + G y-MM-dd + G y MMM + G y MMM d + G y MMM d, E + h a HH - HH:mm + h:mm a HH:mm - HH:mm:ss + h:mm:ss a HH:mm:ss - HH:mm:ss v + h:mm:ss a v HH:mm:ss v - HH:mm v + h:mm a v HH:mm v L MM-dd @@ -2102,11 +2102,11 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ {0} – {1} - h B – h B + h B – h B h–h B - h:mm B – h:mm B + h:mm B – h:mm B h:mm–h:mm B h:mm–h:mm B @@ -2114,71 +2114,71 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ d–d - y – y + G y – G y y–y - y-MM – y-MM - y-MM – y-MM - y-MM – y-MM + G y-MM – G y-MM + G y-MM – y-MM + G y-MM – y-MM - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd + G y-MM-dd – y-MM-dd + G y-MM-dd – G y-MM-dd + G y-MM-dd – y-MM-dd + G y-MM-dd – y-MM-dd - y-MM-dd, E – y-MM-dd, E - y-MM-dd, E – GGGGG y-MM-dd, E - y-MM-dd, E – y-MM-dd, E - y-MM-dd, E – y-MM-dd, E + G y-MM-dd, E – y-MM-dd, E + G y-MM-dd, E – G y-MM-dd, E + G y-MM-dd, E – y-MM-dd, E + G y-MM-dd, E – y-MM-dd, E - y MMM – G y MMM - y MMM–MMM - y MMM – y MMM + G y MMM – G y MMM + G y MMM–MMM + G y MMM – y MMM - y MMM d–d - y MMM d – y MMM d - y MMM d – MMM d - y MMM d – y MMM d + G y MMM d–d + G y MMM d – G y MMM d + G y MMM d – MMM d + G y MMM d – y MMM d - y MMM d, E – MMM d, E - y MMM d, E – y MMM d, E - y MMM d, E – MMM d, E - y MMM d, E – y MMM d, E + G y MMM d, E – MMM d, E + G y MMM d, E – G y MMM d, E + G y MMM d, E – MMM d, E + G y MMM d, E – y MMM d, E - HH–HH - HH–HH + h a – h a + h–h a HH–HH - HH:mm–HH:mm - HH:mm–HH:mm - HH:mm–HH:mm + h:mm a – h:mm a + h:mm–h:mm a + h:mm–h:mm a HH:mm–HH:mm HH:mm–HH:mm - HH:mm–HH:mm v - HH:mm–HH:mm v - HH:mm–HH:mm v + h:mm a – h:mm a v + h:mm–h:mm a v + h:mm–h:mm a v HH:mm–HH:mm v HH:mm–HH:mm v - HH–HH v - HH–HH v + h a – h a v + h–h a v HH–HH v @@ -2187,58 +2187,58 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ MM–MM - MM-dd – MM-dd - MM-dd – MM-dd + MM-dd – MM-dd + MM-dd – MM-dd - MM-dd, E – MM-dd, E - MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E + MM-dd, E – MM-dd, E LLL–LLL MMM d–d - MMM d – MMM d + MMM d – MMM d - MMM d, E – MMM d, E - MMM d, E – MMM d, E + MMM d, E – MMM d, E + MMM d, E – MMM d, E y–y - y-MM – y-MM - y-MM – y-MM + y-MM – y-MM + y-MM – y-MM - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd - y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd + y-MM-dd – y-MM-dd - y-MM-dd, E – y-MM-dd, E - y-MM-dd, E – y-MM-dd, E - y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E + y-MM-dd, E – y-MM-dd, E y MMM–MMM - y MMM – y MMM + y MMM – y MMM y MMM d–d - y MMM d – MMM d - y MMM d – y MMM d + y MMM d – MMM d + y MMM d – y MMM d - y MMM d, E – MMM d, E - y MMM d, E – MMM d, E - y MMM d, E – y MMM d, E + y MMM d, E – MMM d, E + y MMM d, E – MMM d, E + y MMM d, E – y MMM d, E y MMMM–MMMM - y MMMM – y MMMM + y MMMM – y MMMM diff --git a/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt b/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt index 350f5cbc190..912dc2ba900 100644 --- a/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt +++ b/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt @@ -119,11 +119,14 @@ //ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@alt="ascii"] ; Special ; Suppress ; &calendar($1); &calField(Formats:Flexible:date)-$2-ascii ; HIDE //ldml/dates/calendars/calendar[@type="gregorian"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="gregorian"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS +//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS +//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="generic"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(generic); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="generic"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(generic); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="chinese"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(chinese); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="chinese"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(chinese); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="gregorian"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@count="%A"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:date) ; $1-$2 ; LTR_ALWAYS +//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@count="%A"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:date) ; $1-$2 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="%N"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(?![^"]*[hHms])%A"] ; DateTime ; &calendar($1); &calField(Formats:Flexible:date) ; $2 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@count="%A"] ; Special ; Suppress ; &calendar($1); &calField(Formats:Flexible:date)-$2-$3 ; HIDE //ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"] ; Special ; Suppress ; &calendar($1); &calField(Formats:Flexible:date)-$2 ; HIDE diff --git a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java index 9b1aaaba9ae..b50dfa614ea 100644 --- a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java +++ b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java @@ -1,17 +1,23 @@ package org.unicode.cldr.unittest; import com.google.common.base.Joiner; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import com.ibm.icu.dev.test.TestFmwk; import com.ibm.icu.text.DateTimePatternGenerator; import com.ibm.icu.text.DateTimePatternGenerator.VariableField; import com.ibm.icu.text.SimpleDateFormat; import com.ibm.icu.text.UnicodeSet; +import com.ibm.icu.util.TimeZone; +import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import org.unicode.cldr.test.DateOrder; @@ -86,22 +92,35 @@ public void TestDateImportance() { assertTrue("Date format conflict not found", values.contains(fullDate)); } - static final String stockPathPrefix = + static final String stockDatePathPrefix = "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateFormats/dateFormatLength"; + static final String stockTimePathPrefix = + "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/timeFormats/timeFormatLength"; static final String availableFormatPathPrefix = "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/availableFormats/dateFormatItem"; static final String intervalFormatPathPrefix = "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/intervalFormats/"; public void TestIso8601() { + List printout = null; + if (isVerbose()) { + printout = new ArrayList<>(); + } else { + warnln("Use -v to see a comparison between calendars"); + } + ICUServiceBuilder isb = ICUServiceBuilder.forLocale(CLDRLocale.getInstance("en")); + ICUServiceBuilder isbCan = ICUServiceBuilder.forLocale(CLDRLocale.getInstance("en_CA")); CLDRFile english = CLDRConfig.getInstance().getEnglish(); + CLDRFile englishCan = CLDRConfig.getInstance().getCldrFactory().make("en_CA", true); Factory phf = PathHeader.getFactory(); + Set paths = new TreeSet<>(); for (String path : english) { if (!path.startsWith("//ldml/dates/calendars/calendar[@type=\"gregorian\"]")) { continue; - } else if (path.startsWith(stockPathPrefix)) { + } else if (path.startsWith(stockTimePathPrefix) + || path.startsWith(stockDatePathPrefix)) { if (!path.contains("datetimeSkeleton")) { paths.add(phf.fromPath(path)); } @@ -115,15 +134,30 @@ public void TestIso8601() { int debug = 0; } } - Date sample = new Date(2024 - 1900, 0, 9, 19, 8, 9); - System.out.println(); + Date sample = Date.from(Instant.parse("2024-01-13T07:08:09Z")); + SimpleDateFormat neutralFormat = + new SimpleDateFormat("G yyyy-MM-dd HH:mm:ss X", Locale.ROOT); + neutralFormat.setTimeZone(TimeZone.GMT_ZONE); + for (PathHeader pathHeader : paths) { final String originalPath = pathHeader.getOriginalPath(); + String code = pathHeader.getCode(); + + if (originalPath.startsWith(stockTimePathPrefix)) { + code = "time-" + code; + } else if (originalPath.startsWith(stockDatePathPrefix)) { + code = "date-" + code; + } String gregPat = english.getStringValue(originalPath); String isoPat = english.getStringValue(originalPath.replace("\"gregorian\"", "\"iso8601\"")); + String canPat = englishCan.getStringValue(originalPath); + String gregFormatted = null; String isoFormatted = null; + String canFormatted = null; + + String sampleDate = null; if (originalPath.contains("intervalFormats")) { Date sample1 = (Date) sample.clone(); @@ -133,60 +167,169 @@ public void TestIso8601() { switch (greatestDifference) { case "G": - sample1.setYear(-sample2.getYear()); + sample1.setYear(sample.getYear() - 3000); break; case "y": - sample2.setYear(sample2.getYear() + 1); + sample2.setYear(sample.getYear() + 1); break; case "M": - sample2.setMonth(sample2.getMonth() + 1); + sample2.setMonth(sample.getMonth() + 1); break; case "d": - sample2.setDate(sample2.getDate() + 1); + sample2.setDate(sample.getDate() + 1); break; case "h": case "H": - sample2.setHours(sample2.getHours() + 1); + sample2.setHours(sample.getHours() + 1); break; case "a": case "B": - sample2.setHours(sample2.getHours() + 12); + sample2.setHours(sample.getHours() + 12); break; case "m": - sample2.setMinutes(sample2.getMinutes() + 1); + sample2.setMinutes(sample.getMinutes() + 1); break; case "s": - sample2.setSeconds(sample2.getSeconds() + 1); + sample2.setSeconds(sample.getSeconds() + 1); break; default: System.out.println("Missing" + greatestDifference); break; } + sampleDate = neutralFormat.format(sample1) + " - " + neutralFormat.format(sample2); + + check(isoPat, Set.of(Check.dayperiod)); + + List parts2 = splitIntervalPattern(isoPat); + check( + parts2.get(0), + Set.of(Check.order, Check.uniqueness)); // check first part of interval + check( + parts2.get(2), + Set.of(Check.order, Check.uniqueness)); // check second part of interval - gregFormatted = formatInterval(isb, sample1, sample2, gregPat); - isoFormatted = formatInterval(isb, sample1, sample2, isoPat); + gregFormatted = formatInterval(isb, sample1, sample2, "gregorian", gregPat); + isoFormatted = formatInterval(isb, sample1, sample2, "iso8601", isoPat); + canFormatted = formatInterval(isbCan, sample1, sample2, "gregorian", canPat); } else { + check(isoPat, Set.of(Check.order, Check.uniqueness, Check.dayperiod)); + + sampleDate = neutralFormat.format(sample); + SimpleDateFormat gregFormat = isb.getDateFormat("gregorian", gregPat); + gregFormat.setTimeZone(TimeZone.GMT_ZONE); SimpleDateFormat isoFormat = isb.getDateFormat("iso8601", isoPat); + isoFormat.setTimeZone(TimeZone.GMT_ZONE); + SimpleDateFormat caFormat = isbCan.getDateFormat("gregorian", gregPat); + caFormat.setTimeZone(TimeZone.GMT_ZONE); gregFormatted = gregFormat.format(sample); isoFormatted = isoFormat.format(sample); + canFormatted = caFormat.format(sample); + } + if (printout != null) { + printout.add( + JOIN_TAB.join( + code, + gregPat, + isoPat, + canPat, + sampleDate, + gregFormatted, + isoFormatted, + canFormatted)); + } + } + if (printout != null) { + System.out.println(); + for (String line : printout) { + System.out.println(line); + } + } + } + + static final List expectedOrder = + List.of( + DateTimePatternGenerator.ERA, + DateTimePatternGenerator.YEAR, + DateTimePatternGenerator.QUARTER, + DateTimePatternGenerator.MONTH, + DateTimePatternGenerator.DAY, + DateTimePatternGenerator.WEEK_OF_YEAR, + DateTimePatternGenerator.WEEK_OF_MONTH, + DateTimePatternGenerator.WEEKDAY, + DateTimePatternGenerator.HOUR, + DateTimePatternGenerator.MINUTE, + DateTimePatternGenerator.SECOND, + DateTimePatternGenerator.DAYPERIOD, + DateTimePatternGenerator.ZONE); + + enum Check { + order, + dayperiod, + uniqueness + } + + private void check(String isoPat, Set checks) { + VariableField last = null; + int lastType = -1; + Multimap types = HashMultimap.create(); + + // check the order. y M is ok, because type(y) < type(M) + + for (Object p : parser.set(isoPat).getItems()) { + if (p instanceof VariableField) { + VariableField pv = (VariableField) p; + final int rawType = pv.getType(); + int curType = expectedOrder.indexOf(rawType); + if (!assertTrue(pv + ": order > 0", curType >= 0)) { + int debug = 0; + } + if (checks.contains(Check.order) && lastType != -1) { + assertTrue(isoPat + ": " + last + " < " + pv, lastType < curType); + } + last = pv; + lastType = curType; + types.put(rawType, pv.toString()); + } + } + + // There is only one field of each type + + if (checks.contains(Check.uniqueness)) { + for (Entry> entry : types.asMap().entrySet()) { + assertEquals(entry.toString(), 1, entry.getValue().size()); + } + } + + // There is an a/B iff it is 12 hour + if (checks.contains(Check.dayperiod)) { + boolean hasDayPeriod = types.containsKey(DateTimePatternGenerator.DAYPERIOD); + Collection hours = types.get(DateTimePatternGenerator.HOUR); + char firstChar = + hours == null || hours.isEmpty() ? '\u0000' : hours.iterator().next().charAt(0); + boolean is12hour = firstChar == 'h' || firstChar == 'k'; + if (!assertEquals(isoPat + " has 'a' iff 12 hour", hasDayPeriod, is12hour)) { + int debug = 0; } - System.out.println( - JOIN_TAB.join( - pathHeader.getCode(), gregPat, gregFormatted, isoPat, isoFormatted)); } } - public String formatInterval(ICUServiceBuilder isb, Date sample, Date sample2, String gregPat) { - List parts = splitIntervalPattern(gregPat); - SimpleDateFormat gregFormat1 = isb.getDateFormat("gregorian", parts.get(0)); - SimpleDateFormat gregFormat2 = isb.getDateFormat("gregorian", parts.get(2)); + public String formatInterval( + ICUServiceBuilder isb, Date sample, Date sample2, String calendar, String pattern) { + List parts = splitIntervalPattern(pattern); + SimpleDateFormat gregFormat1 = isb.getDateFormat(calendar, parts.get(0)); + gregFormat1.setTimeZone(TimeZone.GMT_ZONE); + + SimpleDateFormat gregFormat2 = isb.getDateFormat(calendar, parts.get(2)); + gregFormat2.setTimeZone(TimeZone.GMT_ZONE); + return gregFormat1.format(sample) + parts.get(1) + gregFormat2.format(sample2); } + DateTimePatternGenerator.FormatParser parser = new DateTimePatternGenerator.FormatParser(); + private List splitIntervalPattern(String intervalPattern) { - DateTimePatternGenerator.FormatParser parser = new DateTimePatternGenerator.FormatParser(); List result = new ArrayList<>(); StringBuilder current = new StringBuilder(); Set soFar = new HashSet<>(); diff --git a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDisplayAndInputProcessor.java b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDisplayAndInputProcessor.java index 82270a558e4..463049568ea 100644 --- a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDisplayAndInputProcessor.java +++ b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDisplayAndInputProcessor.java @@ -1,6 +1,7 @@ package org.unicode.cldr.unittest; import com.ibm.icu.dev.test.TestFmwk; +import com.ibm.icu.impl.Utility; import com.ibm.icu.lang.CharSequences; import com.ibm.icu.text.UnicodeSet; import com.ibm.icu.text.UnicodeSetIterator; @@ -351,12 +352,13 @@ private void showCldrFile(final CLDRFile cldrFile) { String input = daip.processInput(path, display, internalException); String diff = diff(value, input, path); if (diff != null) { + // repeat for debugging display = daip.processForDisplay(path, value); input = daip.processInput(path, display, internalException); diff(value, input, path); errln( cldrFile.getLocaleID() - + "\tNo roundtrip in DAIP:" + + "\tNo roundtrip in DAIP, value ≠ processInput(display(value)):" + "\n\t value<" + value + ">\n\tdisplay<" @@ -463,7 +465,29 @@ private String diff(String value, String input, String path) { if (value2.equals(input)) { return null; } - return "?"; + + return firstDiff(value2, input); + } + + private String firstDiff(String v1, String v2) { + int i = 0; + while (i < v1.length() && i < v2.length()) { + int cp1 = v1.codePointAt(i); + int cp2 = v2.codePointAt(i); + if (cp1 != cp2) { + return v1.substring(0, i) + + " ⓥ:" + + Utility.hex(cp1) + + " ≠ Ⓘ(Ⓓ(ⓥ)):" + + Utility.hex(cp2); + } + i += cp1 <= 0xFFFF ? 1 : 2; + } + return v1.substring(0, i) + + " ⓥ:" + + v1.substring(i, v1.length()) + + " ≠ Ⓘ(Ⓓ(ⓥ)):" + + v2.substring(i, v2.length()); } /** Test whether DisplayAndInputProcessor.processInput removes backspaces */ From 6781023f9e5dd8d122992fdfdbb2ba72656c6e40 Mon Sep 17 00:00:00 2001 From: macchiati Date: Wed, 11 Sep 2024 16:37:28 -0700 Subject: [PATCH 3/8] CLDR-17892 Fix path headers for new calendar --- .../src/main/java/org/unicode/cldr/util/PathHeader.java | 1 + .../resources/org/unicode/cldr/util/data/PathHeader.txt | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/cldr-code/src/main/java/org/unicode/cldr/util/PathHeader.java b/tools/cldr-code/src/main/java/org/unicode/cldr/util/PathHeader.java index 0bb98b04850..fef2148fcb6 100644 --- a/tools/cldr-code/src/main/java/org/unicode/cldr/util/PathHeader.java +++ b/tools/cldr-code/src/main/java/org/unicode/cldr/util/PathHeader.java @@ -189,6 +189,7 @@ public enum PageId { Fields(SectionId.DateTime), Relative(SectionId.DateTime), Gregorian(SectionId.DateTime), + ISO8601(SectionId.DateTime, "ISO 8601"), Generic(SectionId.DateTime), Buddhist(SectionId.DateTime), Chinese(SectionId.DateTime), diff --git a/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt b/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt index 912dc2ba900..30d3c5b2260 100644 --- a/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt +++ b/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/PathHeader.txt @@ -119,14 +119,14 @@ //ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@alt="ascii"] ; Special ; Suppress ; &calendar($1); &calField(Formats:Flexible:date)-$2-ascii ; HIDE //ldml/dates/calendars/calendar[@type="gregorian"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="gregorian"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS -//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS -//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS +//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(iso8601); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS +//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(iso8601); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="generic"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(generic); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="generic"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(generic); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="chinese"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*(a|b|B)*[h]%a)"] ; DateTime ; &calendar(chinese); &calField(Formats:Flexible:time12) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="chinese"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(E*[Hms]%a)"] ; DateTime ; &calendar(chinese); &calField(Formats:Flexible:time24) ; $1 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="gregorian"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@count="%A"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:date) ; $1-$2 ; LTR_ALWAYS -//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@count="%A"] ; DateTime ; &calendar(gregorian); &calField(Formats:Flexible:date) ; $1-$2 ; LTR_ALWAYS +//ldml/dates/calendars/calendar[@type="iso8601"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@count="%A"] ; DateTime ; &calendar(iso8601); &calField(Formats:Flexible:date) ; $1-$2 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="%N"]/dateTimeFormats/availableFormats/dateFormatItem[@id="(?![^"]*[hHms])%A"] ; DateTime ; &calendar($1); &calField(Formats:Flexible:date) ; $2 ; LTR_ALWAYS //ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"][@count="%A"] ; Special ; Suppress ; &calendar($1); &calField(Formats:Flexible:date)-$2-$3 ; HIDE //ldml/dates/calendars/calendar[@type="%A"]/dateTimeFormats/availableFormats/dateFormatItem[@id="%A"] ; Special ; Suppress ; &calendar($1); &calField(Formats:Flexible:date)-$2 ; HIDE From f1852b6071c7db683de65f2c6a11432587dcb2e8 Mon Sep 17 00:00:00 2001 From: macchiati Date: Wed, 11 Sep 2024 17:34:13 -0700 Subject: [PATCH 4/8] CLDR-17892 Fix placeholder failure --- .../main/resources/org/unicode/cldr/util/data/Placeholders.txt | 3 ++- .../src/test/java/org/unicode/cldr/unittest/TestCLDRFile.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/Placeholders.txt b/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/Placeholders.txt index f8252955650..89464cf8327 100644 --- a/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/Placeholders.txt +++ b/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/Placeholders.txt @@ -11,7 +11,8 @@ ^//ldml/dates/calendars/calendar\[@type="%A"]/dateTimeFormats/dateTimeFormatLength\[@type="%A"]/dateTimeFormat\[@type="%A"]/pattern\[@type="%A"] ; {1}=DATE Dec 10, 2010 ; {0}=TIME 3:59 -# strange values +# The code does not currently allow for showing the placeholders in datetime formats + #^//ldml/dates/.*(pattern|available|intervalFormatItem) ; cccc=UNKNOWN ? #^//ldml/dates/.*(pattern|available|intervalFormatItem) ; ccc=UNKNOWN ? # diff --git a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestCLDRFile.java b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestCLDRFile.java index 202152c6a20..520fc88c9d7 100644 --- a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestCLDRFile.java +++ b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestCLDRFile.java @@ -192,6 +192,7 @@ public void testExtraPaths() { || path.contains("/gender") || path.startsWith("//ldml/numbers/currencies/currency") || path.startsWith("//ldml/personNames/sampleName") + || path.contains("/availableFormats") ? PlaceholderStatus.DISALLOWED : path.contains("/compoundUnitPattern1") ? PlaceholderStatus.REQUIRED From 4d6ee936c292771c3d59577e00af7ec3d9d3977d Mon Sep 17 00:00:00 2001 From: macchiati Date: Wed, 11 Sep 2024 18:09:06 -0700 Subject: [PATCH 5/8] CLDR-17892 Fixes for items Annemarie found --- common/main/root.xml | 10 +++++----- .../java/org/unicode/cldr/unittest/TestDateOrder.java | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/common/main/root.xml b/common/main/root.xml index 69080e8a4ed..6bce9850571 100644 --- a/common/main/root.xml +++ b/common/main/root.xml @@ -1981,25 +1981,25 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ - HH:mm:ss zzzz + h:mm:ss a zzzz HHmmsszzzz - HH:mm:ss z + h:mm:ss a z HHmmssz - HH:mm:ss + h:mm:ss a HHmmss - HH:mm + h:mm a HHmm @@ -2080,7 +2080,7 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ y-MM-dd, E y MMM y MMM d - y MMM d + y MMM d, E y MMMM y QQQ y QQQQ diff --git a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java index b50dfa614ea..85dd1068364 100644 --- a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java +++ b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestDateOrder.java @@ -134,7 +134,7 @@ public void TestIso8601() { int debug = 0; } } - Date sample = Date.from(Instant.parse("2024-01-13T07:08:09Z")); + Date sample = Date.from(Instant.parse("2024-01-13T19:08:09Z")); SimpleDateFormat neutralFormat = new SimpleDateFormat("G yyyy-MM-dd HH:mm:ss X", Locale.ROOT); neutralFormat.setTimeZone(TimeZone.GMT_ZONE); @@ -184,7 +184,7 @@ public void TestIso8601() { break; case "a": case "B": - sample2.setHours(sample.getHours() + 12); + sample1.setHours(sample.getHours() - 12); break; case "m": sample2.setMinutes(sample.getMinutes() + 1); @@ -228,6 +228,7 @@ public void TestIso8601() { canFormatted = caFormat.format(sample); } if (printout != null) { + canFormatted = canFormatted.replace("a.m.", "AM").replace("p.m.", "PM"); printout.add( JOIN_TAB.join( code, From 620d0fd3c691fe26390fbba8a0008025e5e92317 Mon Sep 17 00:00:00 2001 From: macchiati Date: Wed, 11 Sep 2024 18:27:27 -0700 Subject: [PATCH 6/8] CLDR-17892 Updated release page --- docs/site/downloads/cldr-46.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/site/downloads/cldr-46.md b/docs/site/downloads/cldr-46.md index eb6f9f2ae57..8efaa28028c 100644 --- a/docs/site/downloads/cldr-46.md +++ b/docs/site/downloads/cldr-46.md @@ -66,9 +66,13 @@ For a full listing, see [Delta DTDs](https://unicode.org/cldr/charts/46/suppleme 1. Currency 1. New currency code `ZWG` added — because it was late in the cycle, many locales will just support the code (no symbol or name). -2. Timezones and Metazones - 1. Changed the metazone for Kazakhstan to reflect removal of Asia/Almaty, thus dropping the distinction among different regions in Kazakhstan. - 2. Added support for deprecated codes by remapping: `CST6CDT → America/Chicago`, `EST → America/Panama`, `EST5EDT → America/New_York`, `MST7MDT → America/Denver`, `PST8PDT → America/Los_Angeles`. +2. Dates & Times + 1. Added a new calendar type, `iso8601`. +This is not the same as the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard format, which is designed just for data interchange. +It is all ASCII, doesn't have all the options for fields (like "Sunday", "BC", or "AM"). +The CLDR `iso8601` calendar uses patterns in the order: era, year, month, day, day-of-week, hour, minute, second, day-period, timezone + 2. Changed the metazone for Kazakhstan to reflect removal of Asia/Almaty, thus dropping the distinction among different regions in Kazakhstan. + 3. Added support for deprecated timezone codes by remapping: `CST6CDT → America/Chicago`, `EST → America/Panama`, `EST5EDT → America/New_York`, `MST7MDT → America/Denver`, `PST8PDT → America/Los_Angeles`. 3. Units 1. Added units: `portion-per-1e9` (aka per-billion), `night` (for hotel stays), `light-speed` (as an internal prefix for **light-second**, **light-minute**, etc.) 2. Changed preferred wind speed preference for some locales to `meter-per-second`. @@ -112,7 +116,11 @@ For a full listing, see [¤¤BCP47 Delta](https://unicode.org/cldr/charts/46/del 1. Major changes to emoji search keywords and short names (see below) 2. Major changes to Chinese collation, reflecting new data in Unicode 16.0 -3. Other changes +3. Added iso8601 patterns to root. +These will use localized months, days of the week, day periods, and timezones. +In this first version, the separators are not localized, and will use "-" within numeric dates, ":" within times, and " " or ", " between major elements. +Full localization will await the next submission phase for CLDR. +4. Other changes 1. Various locales also had smaller improvements agreed to by translators. 2. Additional test files have been added. From 797a9f0d921f637f0e9f869b14cd246bcd9dc987 Mon Sep 17 00:00:00 2001 From: macchiati Date: Wed, 11 Sep 2024 18:30:56 -0700 Subject: [PATCH 7/8] CLDR-17892 Minor fix to release page. --- docs/site/downloads/cldr-46.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/site/downloads/cldr-46.md b/docs/site/downloads/cldr-46.md index 8efaa28028c..97f8702ecdd 100644 --- a/docs/site/downloads/cldr-46.md +++ b/docs/site/downloads/cldr-46.md @@ -68,8 +68,8 @@ For a full listing, see [Delta DTDs](https://unicode.org/cldr/charts/46/suppleme 1. New currency code `ZWG` added — because it was late in the cycle, many locales will just support the code (no symbol or name). 2. Dates & Times 1. Added a new calendar type, `iso8601`. -This is not the same as the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard format, which is designed just for data interchange. -It is all ASCII, doesn't have all the options for fields (like "Sunday", "BC", or "AM"). +This is not the same as the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard format, which is designed just for data interchange: +it is all ASCII, doesn't have all the options for fields (like "Sunday", "BC", or "AM"), and does not contain spaces. The CLDR `iso8601` calendar uses patterns in the order: era, year, month, day, day-of-week, hour, minute, second, day-period, timezone 2. Changed the metazone for Kazakhstan to reflect removal of Asia/Almaty, thus dropping the distinction among different regions in Kazakhstan. 3. Added support for deprecated timezone codes by remapping: `CST6CDT → America/Chicago`, `EST → America/Panama`, `EST5EDT → America/New_York`, `MST7MDT → America/Denver`, `PST8PDT → America/Los_Angeles`. From d954cf9c5e574f1aeeb2ef0fc9773cae39808666 Mon Sep 17 00:00:00 2001 From: macchiati Date: Thu, 12 Sep 2024 08:03:41 -0700 Subject: [PATCH 8/8] CLDR-17892 Fix stock formats to have HH --- common/main/root.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/main/root.xml b/common/main/root.xml index 6bce9850571..5c87d314864 100644 --- a/common/main/root.xml +++ b/common/main/root.xml @@ -1981,25 +1981,25 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ - h:mm:ss a zzzz + HH:mm:ss zzzz HHmmsszzzz - h:mm:ss a z + HH:mm:ss z HHmmssz - h:mm:ss a + HH:mm:ss HHmmss - h:mm a + HH:mm HHmm