From cccfa8d841cd739f3a1247955367de4a8ab9e43a Mon Sep 17 00:00:00 2001 From: Carlos Quiroz Date: Tue, 12 Jul 2016 17:12:23 -0400 Subject: [PATCH 1/8] Initial NumberFormat stubs --- README.md | 2 +- .../main/scala/java/text/NumberFormat.scala | 53 +++++++++++++++++++ .../javalib/text/NumberFormatTest.scala | 13 +++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 core/src/main/scala/java/text/NumberFormat.scala create mode 100644 testSuite/shared/src/test/scala/testsuite/javalib/text/NumberFormatTest.scala diff --git a/README.md b/README.md index e12028de..2754c308 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ If you have a `crossProject`, the setting must be used only in the JS part: ```scala lazy val myCross = crossProject. ... - jsSettings.( + .jsSettings( libraryDependencies += "com.github.cquiroz" %%% "scala-java-locales" % "0.2.0+29" ) ``` diff --git a/core/src/main/scala/java/text/NumberFormat.scala b/core/src/main/scala/java/text/NumberFormat.scala new file mode 100644 index 00000000..2829d530 --- /dev/null +++ b/core/src/main/scala/java/text/NumberFormat.scala @@ -0,0 +1,53 @@ +package java.text + +import java.util.Locale + +abstract class NumberFormat protected () extends Format { + override final def parseObject(source: String, pos: ParsePosition): AnyRef = ??? + + override def format(obj: AnyRef, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + + // TODO implement + // final def format(number: Double): String = ??? + // final def format(number: Long): String = ??? + // def format(number: Double, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + // def format(number: Long, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + // def parse(source: String, parsePosition: ParsePosition): Number = ??? + // def parse(source: String): Number = ??? + // def isParseIntegerOnly(): Boolean = ??? + // def setParseIntegerOnly(value: Boolean): Unit = ??? + // override def hashCode(): Int = ??? + // override def equals(obj: Any): Boolean = ??? + // override def clone(): Any = ??? + // def isGroupingUsed(): Boolean = ??? + // def setGroupingUsed(newValue: Boolean): Unit = ??? + // def getMaximumIntegerDigits(): Int = ??? + // def setMaximumIntegerDigits(newValue: Int): Unit = ??? + // def getMinimumIntegerDigits(): Int = ??? + // def setMinimumIntegerDigits(newValue: Int): Unit = ??? + // def getMaximumFractionDigits(): Int = ??? + // def setMaximumFractionDigits(newValue: Int): Unit = ??? + // def getMinimumFractionDigits(): Int = ??? + // def setMinimumFractionDigits(newValue: Int): Unit = ??? + // def getCurrency(): Currency = ??? + // def setCurrency(currency: Currency): Unit = ??? + // def getRoundingMode(): RoundingMode = ??? + // def setRoundingMode(currency: RoundingMode): Unit = ??? +} + +object NumberFormat { + val INTEGER_FIELD: Int = 0 + val FRACTION_FIELD: Int = 1 + + //final def getInstance(): NumberFormat = ??? + //def getInstance(inLocale: Locale): NumberFormat = ??? + //final def getNumberInstance(): NumberFormat = ??? + //def getNumberInstance(inLocale: Locale): NumberFormat = ??? + //final def getIntegerInstance(): NumberFormat = ??? + //def getIntegerInstance(inLocale: Locale): NumberFormat = ??? + //final def getCurrencyInstance(): NumberFormat = ??? + //def getCurrencyInstance(inLocale: Locale): NumberFormat = ??? + //final def getPercentInstance(): NumberFormat = ??? + //def getPercentInstance(inLocale: Locale): NumberFormat = ??? + //def getAvailableLocales(): Array[Locale] = ??? +} diff --git a/testSuite/shared/src/test/scala/testsuite/javalib/text/NumberFormatTest.scala b/testSuite/shared/src/test/scala/testsuite/javalib/text/NumberFormatTest.scala new file mode 100644 index 00000000..2bf46a3a --- /dev/null +++ b/testSuite/shared/src/test/scala/testsuite/javalib/text/NumberFormatTest.scala @@ -0,0 +1,13 @@ +package testsuite.javalib.text + +import java.text.NumberFormat + +import org.junit.Test +import org.junit.Assert._ + +class NumberFormatTest { + @Test def test_constants(): Unit = { + assertEquals(0, NumberFormat.INTEGER_FIELD) + assertEquals(1, NumberFormat.FRACTION_FIELD) + } +} From a76712760c9aa82a583f9b741b9e6ac15a020e36 Mon Sep 17 00:00:00 2001 From: Carlos Quiroz Date: Tue, 12 Jul 2016 18:00:36 -0400 Subject: [PATCH 2/8] Initial DecimalFormat stubs --- .../main/scala/java/text/DecimalFormat.scala | 57 +++++++++++++++++++ .../javalib/text/DecimalFormatTest.scala | 14 +++++ 2 files changed, 71 insertions(+) create mode 100644 core/src/main/scala/java/text/DecimalFormat.scala create mode 100644 testSuite/shared/src/test/scala/testsuite/javalib/text/DecimalFormatTest.scala diff --git a/core/src/main/scala/java/text/DecimalFormat.scala b/core/src/main/scala/java/text/DecimalFormat.scala new file mode 100644 index 00000000..08867547 --- /dev/null +++ b/core/src/main/scala/java/text/DecimalFormat.scala @@ -0,0 +1,57 @@ +package java.text + +class DecimalFormat(private[this] val pattern: String, private[this] var symbols: DecimalFormatSymbols) extends Format { + def this(pattern: String) = this(pattern, DecimalFormatSymbols.getInstance()) + + //def this() = this("???", DecimalFormatSymbols.getInstance()) + + override final def format(obj: AnyRef, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + + override final def parseObject(source: String, pos: ParsePosition): AnyRef = ??? + + // TODO implement + //def format(number: Double, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + //def format(number: Long, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + //def parse(source: String, parsePosition: ParsePosition): Number = ??? + //def parse(source: String): Number = ??? + def getDecimalFormatSymbols(): DecimalFormatSymbols = symbols + + def setDecimalFormatSymbols(symbols: DecimalFormatSymbols): Unit = + this.symbols = symbols + + // def getPositivePrefix(): String = ??? + // def setPositivePrefix(newValue: String): Unit = ??? + // def getNegativePrefix(): String = ??? + // def setNegativePrefix(newValue: String): Unit = ??? + // def getPositiveSuffix(): String = ??? + // def setPositiveSuffix(newValue: String): Unit = ??? + // def getNegativeSuffix(): String = ??? + // def setNegativeSuffix(newValue: String): Unit = ??? + // def getMultiplier(): Int = ??? + // def setMultiplier(newValue: Int): Unit = ??? + // override def setGroupingUsed(newValue: Boolean): Unit = ??? + // def getGroupingSize(): Int = ??? + // def setGroupingSize(newValue: Int): Unit = ??? + // def isDecimalSeparatorAlwaysShown(): Boolean = ??? + // def setDecimalSeparatorAlwaysShown(newValue: Boolean): Unit = ??? + // def isParseBigDecimal(): Boolean = ??? + // def setParseBigDecimal(newValue: Boolean): Unit = ??? + // override def clone(): Any = ??? + // override def hashCode(): Int = ??? + // override def equals(obj: Any): Boolean = ??? + def toPattern(): String = pattern + // def toLocalizedPattern(): String = pattern + // def applyPattern(pattern: String): Unit = ??? + // def setMaximumIntegerDigits(newValue: Int): Unit = ??? + // def setMinimumIntegerDigits(newValue: Int): Unit = ??? + // def setMaximumFractionDigits(newValue: Int): Unit = ??? + // def setMinimumFractionDigits(newValue: Int): Unit = ??? + // def getMaximumIntegerDigits(): Int = ??? + // def getMinimumIntegerDigits(): Int = ??? + // def getMaximumFractionDigits(): Int = ??? + // def getMinimumFractionDigits(): Int = ??? + // def getCurrency(): Currency = ??? + // def setCurrency(currency: Currency): Unit = ??? + // def getRoundingMode(): RoundingMode = ??? + // def setRoundingMode(currency: RoundingMode): Unit = ??? +} diff --git a/testSuite/shared/src/test/scala/testsuite/javalib/text/DecimalFormatTest.scala b/testSuite/shared/src/test/scala/testsuite/javalib/text/DecimalFormatTest.scala new file mode 100644 index 00000000..34122ca8 --- /dev/null +++ b/testSuite/shared/src/test/scala/testsuite/javalib/text/DecimalFormatTest.scala @@ -0,0 +1,14 @@ +package testsuite.javalib.text + +import java.text.{DecimalFormat, DecimalFormatSymbols} + +import org.junit.Assert._ +import org.junit.Test + +class DecimalFormatTest { + @Test def test_constructor(): Unit = { + val f = new DecimalFormat("##0.#####E0") + assertEquals("##0.#####E0", f.toPattern) + assertEquals(DecimalFormatSymbols.getInstance(), f.getDecimalFormatSymbols()) + } +} From 9db9b7873ca7cdd6f5e8004bf593c45d45df9c48 Mon Sep 17 00:00:00 2001 From: Carlos Quiroz Date: Tue, 12 Jul 2016 19:39:36 -0400 Subject: [PATCH 3/8] Fixed initialization of the default category locales --- core/src/main/scala/locales/LocaleRegistry.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/locales/LocaleRegistry.scala b/core/src/main/scala/locales/LocaleRegistry.scala index 8a90ce45..073f94d6 100644 --- a/core/src/main/scala/locales/LocaleRegistry.scala +++ b/core/src/main/scala/locales/LocaleRegistry.scala @@ -63,7 +63,7 @@ object LocaleRegistry { private var defaultLocale: Locale = en.toLocale private var defaultPerCategory: Map[Locale.Category, Option[Locale]] = - Locale.Category.values().map(_ -> None).toMap + Locale.Category.values().map(_ -> Some(defaultLocale)).toMap private lazy val ldmls: mutable.Map[String, LDML] = mutable.Map.empty @@ -80,7 +80,7 @@ object LocaleRegistry { def resetRegistry(): Unit = { defaultLocale = en.toLocale defaultPerCategory = - Locale.Category.values().map(_ -> None).toMap + Locale.Category.values().map(_ -> Some(defaultLocale)).toMap ldmls.empty initDefaultLocales() } From 46396b0ce86dab09da5d2488ec991a2a161a94b7 Mon Sep 17 00:00:00 2001 From: Carlos Quiroz Date: Wed, 13 Jul 2016 16:34:57 -0400 Subject: [PATCH 4/8] Stubs for DateFormat and SimpleDateFormat --- .../src/main/scala/java/text/DateFormat.scala | 64 +++++++++++++++++++ .../scala/java/text/SimpleDateFormat.scala | 34 ++++++++++ .../javalib/text/DateFormatTest.scala | 35 ++++++++++ 3 files changed, 133 insertions(+) create mode 100644 core/src/main/scala/java/text/DateFormat.scala create mode 100644 core/src/main/scala/java/text/SimpleDateFormat.scala create mode 100644 testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala diff --git a/core/src/main/scala/java/text/DateFormat.scala b/core/src/main/scala/java/text/DateFormat.scala new file mode 100644 index 00000000..d417dad6 --- /dev/null +++ b/core/src/main/scala/java/text/DateFormat.scala @@ -0,0 +1,64 @@ +package java.text + +import java.util.Locale + +abstract class DateFormat protected () extends Format { + // override final def format(obj: AnyRef, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + // def format(date: Date, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + + // TODO implement + // final def format(date: Date): String = ??? + // def parse(source: String, parsePosition: ParsePosition): Date = ??? + // def parse(source: String): Date = ??? + // override final def parseObject(source: String, pos: ParsePosition): AnyRef = ??? + // def setCalendar(newCalendar: Calendar): Unit = ??? + // def getCalendar(): Calendar = ??? + // def setNumberFormat(newNumberFormat: NumberFormat): Unit = ??? + // def getNumberFormat(): NumberFormat = ??? + // def setTimeZone(zone: TimeZone): Unit = ??? + // def getTimeZone(): TimeZone = ??? + // def setLenient(lenient: Boolean): Unit = ??? + // def isLenient(): Boolean = ??? + // override def hashCode(): Int = ??? + // override def equals(obj: Any): Boolean = ??? + // override def clone(): Any = ??? +} + +object DateFormat { + val ERA_FIELD: Int = 0 + val YEAR_FIELD: Int = 1 + val MONTH_FIELD: Int = 2 + val DATE_FIELD: Int = 3 + val HOUR_OF_DAY1_FIELD: Int = 4 + val HOUR_OF_DAY0_FIELD: Int = 5 + val MINUTE_FIELD: Int = 6 + val SECOND_FIELD: Int = 7 + val MILLISECOND_FIELD: Int = 8 + val DAY_OF_WEEK_FIELD: Int = 9 + val DAY_OF_YEAR_FIELD: Int = 10 + val DAY_OF_WEEK_IN_MONTH_FIELD: Int = 11 + val WEEK_OF_YEAR_FIELD: Int = 12 + val WEEK_OF_MONTH_FIELD: Int = 13 + val AM_PM_FIELD: Int = 14 + val HOUR1_FIELD: Int = 15 + val HOUR0_FIELD: Int = 16 + val TIMEZONE_FIELD: Int = 17 + + val FULL: Int = 1 + val LONG: Int = 2 + val MEDIUM: Int = 3 + val SHORT: Int = 4 + val DEFAULT: Int = 2 + + final def getTimeInstance(): DateFormat = ??? + final def getTimeInstance(style: Int): DateFormat = ??? + final def getTimeInstance(style: Int, aLocale: Locale): DateFormat = ??? + final def getDateInstance(): DateFormat = ??? + final def getDateInstance(style: Int): DateFormat = ??? + final def getDateInstance(style: Int, aLocale: Locale): DateFormat = ??? + final def getDateTimeInstance(): DateFormat = ??? + final def getDateTimeInstance(style: Int): DateFormat = ??? + final def getDateTimeInstance(style: Int, aLocale: Locale): DateFormat = ??? + final def getInstance(style: Int, aLocale: Locale): DateFormat = ??? + def getAvailableLocales(): Array[Locale] = ??? +} diff --git a/core/src/main/scala/java/text/SimpleDateFormat.scala b/core/src/main/scala/java/text/SimpleDateFormat.scala new file mode 100644 index 00000000..38cf5980 --- /dev/null +++ b/core/src/main/scala/java/text/SimpleDateFormat.scala @@ -0,0 +1,34 @@ +package java.text + +import java.util.Locale + +class SimpleDateFormat(private[this] val pattern: String, + private[this] var symbols: DateFormatSymbols) extends DateFormat { + def this(pattern: String) = this(pattern, DateFormatSymbols.getInstance()) + + def this(pattern: String, aLocale: Locale) = this(pattern, DateFormatSymbols.getInstance(aLocale)) + + //def this() = this("???", DecimalFormatSymbols.getInstance()) + + override final def format(obj: AnyRef, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + + override final def parseObject(source: String, pos: ParsePosition): AnyRef = ??? + + // def set2DigitYearStart(startDate: Date): Unit = ??? + // def get2DigitYearStart(): Date = ??? + // override final def format(date: Date, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? + // def formatToCharacterIterator(obj: AnyRef): AttributedCharacterIterator = + // def parse(text: String, pos: ParsePosition): Date = ??? + def toPattern(): String = pattern + // def toLocalizedPattern(): String = pattern + // def applyPattern(pattern: String): Unit = ??? + // def applyLocalizedPattern(pattern: String): Unit = ??? + def getDateFormatSymbols(): DateFormatSymbols = symbols + + def setDateFormatSymbols(symbols: DateFormatSymbols): Unit = + this.symbols = symbols + + // override def clone(): Any = ??? + // override def hashCode(): Int = ??? + // override def equals(obj: Any): Boolean = ??? +} diff --git a/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala b/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala new file mode 100644 index 00000000..6e6ca94c --- /dev/null +++ b/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala @@ -0,0 +1,35 @@ +package testsuite.javalib.text + +import java.text.DateFormat + +import org.junit.Assert._ +import org.junit.Test + +class DateFormatTest { + @Test def test_constants(): Unit = { + assertEquals(0, DateFormat.ERA_FIELD) + assertEquals(1, DateFormat.YEAR_FIELD) + assertEquals(2, DateFormat.MONTH_FIELD) + assertEquals(3, DateFormat.DATE_FIELD) + assertEquals(4, DateFormat.HOUR_OF_DAY1_FIELD) + assertEquals(5, DateFormat.HOUR_OF_DAY0_FIELD) + assertEquals(6, DateFormat.MINUTE_FIELD) + assertEquals(7, DateFormat.SECOND_FIELD) + assertEquals(8, DateFormat.MILLISECOND_FIELD) + assertEquals(9, DateFormat.DAY_OF_WEEK_FIELD) + assertEquals(10, DateFormat.DAY_OF_YEAR_FIELD) + assertEquals(11, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD) + assertEquals(12, DateFormat.WEEK_OF_YEAR_FIELD) + assertEquals(13, DateFormat.WEEK_OF_MONTH_FIELD) + assertEquals(14, DateFormat.AM_PM_FIELD) + assertEquals(15, DateFormat.HOUR1_FIELD) + assertEquals(16, DateFormat.HOUR0_FIELD) + assertEquals(17, DateFormat.TIMEZONE_FIELD) + + assertEquals(0, DateFormat.FULL) + assertEquals(1, DateFormat.LONG) + assertEquals(2, DateFormat.MEDIUM) + assertEquals(3, DateFormat.SHORT) + assertEquals(2, DateFormat.DEFAULT) + } +} From 5c4bac2166381ec0748b22df53b5820640108aed Mon Sep 17 00:00:00 2001 From: Carlos Quiroz Date: Thu, 14 Jul 2016 16:08:49 -0400 Subject: [PATCH 5/8] Read date and time patterns from CLDR --- .../scala/java/text/DateFormatSymbols.scala | 2 +- core/src/main/scala/locales/cldr/cldr.scala | 4 +- .../scala/locales/ScalaLocaleCodeGen.scala | 57 ++++++++++++++++++- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/core/src/main/scala/java/text/DateFormatSymbols.scala b/core/src/main/scala/java/text/DateFormatSymbols.scala index 4a69a320..e91d29cc 100644 --- a/core/src/main/scala/java/text/DateFormatSymbols.scala +++ b/core/src/main/scala/java/text/DateFormatSymbols.scala @@ -38,7 +38,7 @@ object DateFormatSymbols { private def toDFS(locale: Locale, dfs: DateFormatSymbols, ldml: LDML): DateFormatSymbols = { def parentSymbols(ldml: LDML): Option[CalendarSymbols] = - ldml.calendar.orElse(ldml.parent.flatMap(parentSymbols)) + ldml.calendarSymbols.orElse(ldml.parent.flatMap(parentSymbols)) def elementsArray(ldml: LDML, read: CalendarSymbols => Option[List[String]]): Option[List[String]] = parentSymbols(ldml).flatMap { s => diff --git a/core/src/main/scala/locales/cldr/cldr.scala b/core/src/main/scala/locales/cldr/cldr.scala index 797fa2e3..bb715133 100644 --- a/core/src/main/scala/locales/cldr/cldr.scala +++ b/core/src/main/scala/locales/cldr/cldr.scala @@ -18,6 +18,8 @@ case class CalendarSymbols(months: List[String], shortMonths: List[String], weekdays: List[String], shortWeekdays: List[String], amPm: List[String], eras: List[String]) +case class CalendarPatterns(datePatterns: Map[Int, String], timePatterns: Map[Int, String]) + /** * Interfaces describing an LDML Locale */ @@ -29,7 +31,7 @@ case class LDMLLocale(language: String, territory: Option[String], */ case class LDML(parent: Option[LDML], locale: LDMLLocale, defaultNS: Option[NumberingSystem], digitSymbols: List[Symbols] = Nil, - calendar: Option[CalendarSymbols]) { + calendarSymbols: Option[CalendarSymbols], calendarPatterns: Option[CalendarPatterns]) { def languageTag: String = toLocale.toLanguageTag diff --git a/project/src/main/scala/locales/ScalaLocaleCodeGen.scala b/project/src/main/scala/locales/ScalaLocaleCodeGen.scala index a6cbdc89..ff4e80f3 100644 --- a/project/src/main/scala/locales/ScalaLocaleCodeGen.scala +++ b/project/src/main/scala/locales/ScalaLocaleCodeGen.scala @@ -40,6 +40,14 @@ object EraSymbols { case class CalendarSymbols(months: MonthSymbols, weekdays: WeekdaysSymbols, amPm: AmPmSymbols, eras: EraSymbols) +case class DateTimePattern(patternType: String, pattern: String) + +case class CalendarPatterns(datePatterns: List[DateTimePattern], timePatterns: List[DateTimePattern]) + +object CalendarPatterns { + val zero = CalendarPatterns(Nil, Nil) +} + case class NumericSystem(id: String, digits: String) case class NumberSymbols(system: NumericSystem, @@ -64,7 +72,9 @@ case class XMLLDMLLocale(language: String, territory: Option[String], variant: Option[String], script: Option[String]) case class XMLLDML(locale: XMLLDMLLocale, defaultNS: Option[NumericSystem], - digitSymbols: Map[NumericSystem, NumberSymbols], calendar: Option[CalendarSymbols]) { + digitSymbols: Map[NumericSystem, NumberSymbols], calendar: Option[CalendarSymbols], + datePatterns: Option[CalendarPatterns]) { + val scalaSafeName: String = { List(Some(locale.language), locale.script, locale.territory, locale.variant) .flatten.mkString("_") @@ -96,6 +106,7 @@ object CodeGenerator { IMPORT("locales.cldr.LDMLLocale"), IMPORT("locales.cldr.Symbols"), IMPORT("locales.cldr.CalendarSymbols"), + IMPORT("locales.cldr.CalendarPatterns"), IMPORT("locales.cldr.data.numericsystems._")) ++ objectBlock ) inPackage "locales.cldr.data" } @@ -118,6 +129,7 @@ object CodeGenerator { val ldmlSym = getModule("LDML") val ldmlNumericSym = getModule("Symbols") val ldmlCalendarSym = getModule("CalendarSymbols") + val ldmlCalendarPatternsSym = getModule("CalendarPatterns") val ldmlLocaleSym = getModule("LDMLLocale") val parent = findParent(root, langs, ldml).fold(NONE)(v => SOME(REF(v))) @@ -151,8 +163,21 @@ object CodeGenerator { LIST(cs.amPm.amPm.map(LIT(_))), LIST(cs.eras.eras.map(LIT(_)))) }.fold(NONE)(s => SOME(s)) + val gcp = ldml.datePatterns.map { cs => + def patternToIndex(i: String) = i match { + case "full" => 1 + case "long" => 2 + case "medium" => 3 + case "short" => 4 + } + + val dates = MAKE_MAP(cs.datePatterns.map(p => TUPLE(LIT(patternToIndex(p.patternType)), LIT(p.pattern)))) + val times = MAKE_MAP(cs.timePatterns.map(p => TUPLE(LIT(patternToIndex(p.patternType)), LIT(p.pattern)))) + Apply(ldmlCalendarPatternsSym, dates, times) + }.fold(NONE)(s => SOME(s)) + OBJECTDEF(ldml.scalaSafeName) withParents Apply(ldmlSym, parent, - ldmlLocaleTree, defaultNS, LIST(numericSymbols), gc) + ldmlLocaleTree, defaultNS, LIST(numericSymbols), gc, gcp) } def metadata(codes: List[String], languages: List[String], scripts: List[String]): Tree = { @@ -289,6 +314,26 @@ object ScalaLocaleCodeGen { } } + def readCalendarPatterns(xml: Node): Option[CalendarPatterns] = { + def readPatterns(n: Node, formatType: String): Seq[DateTimePattern] = + for { + p <- n \\ formatType + } yield DateTimePattern((p \ "@type").text, (p \\ "pattern").text) + + val datePatterns = (for { + df <- xml \\ "dateFormats" + } yield { + readPatterns(df, "dateFormatLength") + }).headOption.map(_.toList) + + val timePatterns = (for { + df <- xml \\ "timeFormats" + } yield { + readPatterns(df, "timeFormatLength") + }).headOption.map(_.toList) + + Some(CalendarPatterns(datePatterns.getOrElse(Nil), timePatterns.getOrElse(Nil))) + } /** * Parse the xml into an XMLLDML object */ @@ -309,6 +354,12 @@ object ScalaLocaleCodeGen { if n.text.nonEmpty } yield readCalendarData(n) + val gregorianDatePatterns = for { + n <- xml \ "dates" \\ "calendar" + if (n \ "@type").text == "gregorian" + if n.text.nonEmpty + } yield readCalendarPatterns(n) + // Find out the default numeric system val defaultNS = Option((xml \ "numbers" \ "defaultNumberingSystem").text) .filter(_.nonEmpty).filter(ns.contains) @@ -352,7 +403,7 @@ object ScalaLocaleCodeGen { nsSymbols } XMLLDML(XMLLDMLLocale(language, territory, variant, script), - defaultNS.flatMap(ns.get), symbols.toMap, gregorian.flatten.headOption) + defaultNS.flatMap(ns.get), symbols.toMap, gregorian.flatten.headOption, gregorianDatePatterns.flatten.headOption) } // Note this must be a def or there could be issues with concurrency From c16fd09dd5db42b354426d3e264a3c9d9d834825 Mon Sep 17 00:00:00 2001 From: Carlos Quiroz Date: Thu, 14 Jul 2016 20:02:31 -0400 Subject: [PATCH 6/8] Initial implementation of DateFormat.getXXInstance() --- .../src/main/scala/java/text/DateFormat.scala | 58 ++++++++++++++----- .../scala/locales/ScalaLocaleCodeGen.scala | 8 +-- .../javalib/text/DateFormatTest.scala | 31 +++++++++- 3 files changed, 79 insertions(+), 18 deletions(-) diff --git a/core/src/main/scala/java/text/DateFormat.scala b/core/src/main/scala/java/text/DateFormat.scala index d417dad6..34f9c8b7 100644 --- a/core/src/main/scala/java/text/DateFormat.scala +++ b/core/src/main/scala/java/text/DateFormat.scala @@ -2,6 +2,8 @@ package java.text import java.util.Locale +import locales.LocaleRegistry + abstract class DateFormat protected () extends Format { // override final def format(obj: AnyRef, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? // def format(date: Date, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? @@ -44,21 +46,51 @@ object DateFormat { val HOUR0_FIELD: Int = 16 val TIMEZONE_FIELD: Int = 17 - val FULL: Int = 1 - val LONG: Int = 2 - val MEDIUM: Int = 3 - val SHORT: Int = 4 + val FULL: Int = 0 + val LONG: Int = 1 + val MEDIUM: Int = 2 + val SHORT: Int = 3 val DEFAULT: Int = 2 - final def getTimeInstance(): DateFormat = ??? - final def getTimeInstance(style: Int): DateFormat = ??? - final def getTimeInstance(style: Int, aLocale: Locale): DateFormat = ??? - final def getDateInstance(): DateFormat = ??? - final def getDateInstance(style: Int): DateFormat = ??? - final def getDateInstance(style: Int, aLocale: Locale): DateFormat = ??? - final def getDateTimeInstance(): DateFormat = ??? - final def getDateTimeInstance(style: Int): DateFormat = ??? - final def getDateTimeInstance(style: Int, aLocale: Locale): DateFormat = ??? + final def getTimeInstance(): DateFormat = getTimeInstance(DEFAULT) + + final def getTimeInstance(style: Int): DateFormat = + getTimeInstance(style, Locale.getDefault(Locale.Category.FORMAT)) + + final def getTimeInstance(style: Int, aLocale: Locale): DateFormat = + LocaleRegistry.ldml(aLocale).flatMap { ldml => + val ptrn = ldml.calendarPatterns.flatMap(_.timePatterns.get(style)) + ptrn.map(new SimpleDateFormat(_, aLocale)) + }.getOrElse(new SimpleDateFormat("", aLocale)) + + final def getDateInstance(): DateFormat = getDateInstance(DEFAULT) + + final def getDateInstance(style: Int): DateFormat = + getDateInstance(style, Locale.getDefault(Locale.Category.FORMAT)) + + final def getDateInstance(style: Int, aLocale: Locale): DateFormat = + LocaleRegistry.ldml(aLocale).flatMap { ldml => + val ptrn = ldml.calendarPatterns.flatMap(_.datePatterns.get(style)) + ptrn.map(new SimpleDateFormat(_, aLocale)) + }.getOrElse(new SimpleDateFormat("", aLocale)) + + final def getDateTimeInstance(): DateFormat = getDateInstance(DEFAULT) + + final def getDateTimeInstance(dateStyle: Int, timeStyle: Int): DateFormat = + getDateTimeInstance(dateStyle, timeStyle, Locale.getDefault(Locale.Category.FORMAT)) + + final def getDateTimeInstance(dateStyle: Int, timeStyle: Int, aLocale: Locale): DateFormat = + LocaleRegistry.ldml(aLocale).flatMap { ldml => + val datePtrn = ldml.calendarPatterns.flatMap(_.datePatterns.get(dateStyle)) + val timePtrn = ldml.calendarPatterns.flatMap(_.timePatterns.get(timeStyle)) + (datePtrn, timePtrn) match { + case (Some(d), Some(t)) => Some(new SimpleDateFormat(s"$d $t", aLocale)) + case (Some(d), None) => Some(new SimpleDateFormat(s"$d", aLocale)) + case (None, Some(t)) => Some(new SimpleDateFormat(s"$t", aLocale)) + case _ => Some(new SimpleDateFormat("", aLocale)) + } + }.getOrElse(new SimpleDateFormat("", aLocale)) + final def getInstance(style: Int, aLocale: Locale): DateFormat = ??? def getAvailableLocales(): Array[Locale] = ??? } diff --git a/project/src/main/scala/locales/ScalaLocaleCodeGen.scala b/project/src/main/scala/locales/ScalaLocaleCodeGen.scala index ff4e80f3..ba8fb678 100644 --- a/project/src/main/scala/locales/ScalaLocaleCodeGen.scala +++ b/project/src/main/scala/locales/ScalaLocaleCodeGen.scala @@ -165,10 +165,10 @@ object CodeGenerator { val gcp = ldml.datePatterns.map { cs => def patternToIndex(i: String) = i match { - case "full" => 1 - case "long" => 2 - case "medium" => 3 - case "short" => 4 + case "full" => 0 + case "long" => 1 + case "medium" => 2 + case "short" => 3 } val dates = MAKE_MAP(cs.datePatterns.map(p => TUPLE(LIT(patternToIndex(p.patternType)), LIT(p.pattern)))) diff --git a/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala b/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala index 6e6ca94c..b6cf5fdc 100644 --- a/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala +++ b/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala @@ -1,6 +1,6 @@ package testsuite.javalib.text -import java.text.DateFormat +import java.text.{DateFormat, SimpleDateFormat} import org.junit.Assert._ import org.junit.Test @@ -32,4 +32,33 @@ class DateFormatTest { assertEquals(3, DateFormat.SHORT) assertEquals(2, DateFormat.DEFAULT) } + + @Test def test_default_date_format(): Unit = { + assertEquals("EEEE, MMMM d, y", DateFormat.getDateInstance(DateFormat.FULL).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMMM d, y", DateFormat.getDateInstance(DateFormat.LONG).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMM d, y", DateFormat.getDateInstance(DateFormat.MEDIUM).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("M/d/yy", DateFormat.getDateInstance(DateFormat.SHORT).asInstanceOf[SimpleDateFormat].toPattern()) + + assertEquals("h:mm:ss a zzzz", DateFormat.getTimeInstance(DateFormat.FULL).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("h:mm:ss a z", DateFormat.getTimeInstance(DateFormat.LONG).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("h:mm:ss a", DateFormat.getTimeInstance(DateFormat.MEDIUM).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("h:mm a", DateFormat.getTimeInstance(DateFormat.SHORT).asInstanceOf[SimpleDateFormat].toPattern()) + + assertEquals("EEEE, MMMM d, y h:mm:ss a zzzz", DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("EEEE, MMMM d, y h:mm:ss a z", DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.LONG).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("EEEE, MMMM d, y h:mm:ss a", DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.MEDIUM).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("EEEE, MMMM d, y h:mm a", DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMMM d, y h:mm:ss a zzzz", DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.FULL).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMMM d, y h:mm:ss a z", DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMMM d, y h:mm:ss a", DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMMM d, y h:mm a", DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMM d, y h:mm:ss a zzzz", DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMM d, y h:mm:ss a z", DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMM d, y h:mm:ss a", DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("MMM d, y h:mm a", DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("M/d/yy h:mm:ss a zzzz", DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.FULL).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("M/d/yy h:mm:ss a z", DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("M/d/yy h:mm:ss a", DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM).asInstanceOf[SimpleDateFormat].toPattern()) + assertEquals("M/d/yy h:mm a", DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).asInstanceOf[SimpleDateFormat].toPattern()) + } } From b25c5e9c4dbd7a5faa1841479812666d9c20c4c9 Mon Sep 17 00:00:00 2001 From: Carlos Quiroz Date: Fri, 15 Jul 2016 15:45:35 -0400 Subject: [PATCH 7/8] Added tests for Language based locales DateFormats --- .../src/main/scala/java/text/DateFormat.scala | 25 +- .../java/text/DecimalFormatSymbols.scala | 7 +- .../scala/locales/ScalaLocaleCodeGen.scala | 13 +- .../javalib/text/DateFormatTest.scala | 444 +++++++++++++++++- 4 files changed, 474 insertions(+), 15 deletions(-) diff --git a/core/src/main/scala/java/text/DateFormat.scala b/core/src/main/scala/java/text/DateFormat.scala index 34f9c8b7..3578c181 100644 --- a/core/src/main/scala/java/text/DateFormat.scala +++ b/core/src/main/scala/java/text/DateFormat.scala @@ -3,6 +3,7 @@ package java.text import java.util.Locale import locales.LocaleRegistry +import locales.cldr.{CalendarPatterns, LDML} abstract class DateFormat protected () extends Format { // override final def format(obj: AnyRef, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer = ??? @@ -52,6 +53,12 @@ object DateFormat { val SHORT: Int = 3 val DEFAULT: Int = 2 + private def parentPatterns(ldml: LDML): Option[CalendarPatterns] = + ldml.calendarPatterns.orElse(ldml.parent.flatMap(parentPatterns)) + + private def patternsR(ldml: LDML, get: CalendarPatterns => Option[String]): Option[String] = + ldml.calendarPatterns.flatMap(get).orElse(ldml.parent.flatMap(patternsR(_, get))) + final def getTimeInstance(): DateFormat = getTimeInstance(DEFAULT) final def getTimeInstance(style: Int): DateFormat = @@ -59,7 +66,7 @@ object DateFormat { final def getTimeInstance(style: Int, aLocale: Locale): DateFormat = LocaleRegistry.ldml(aLocale).flatMap { ldml => - val ptrn = ldml.calendarPatterns.flatMap(_.timePatterns.get(style)) + val ptrn = patternsR(ldml, _.timePatterns.get(style)) ptrn.map(new SimpleDateFormat(_, aLocale)) }.getOrElse(new SimpleDateFormat("", aLocale)) @@ -70,7 +77,9 @@ object DateFormat { final def getDateInstance(style: Int, aLocale: Locale): DateFormat = LocaleRegistry.ldml(aLocale).flatMap { ldml => - val ptrn = ldml.calendarPatterns.flatMap(_.datePatterns.get(style)) + //val ptrn = parentPatterns(ldml).flatMap(_.datePatterns.get(style)) + val ptrn = patternsR(ldml, _.datePatterns.get(style)) + println(ptrn) ptrn.map(new SimpleDateFormat(_, aLocale)) }.getOrElse(new SimpleDateFormat("", aLocale)) @@ -81,8 +90,10 @@ object DateFormat { final def getDateTimeInstance(dateStyle: Int, timeStyle: Int, aLocale: Locale): DateFormat = LocaleRegistry.ldml(aLocale).flatMap { ldml => - val datePtrn = ldml.calendarPatterns.flatMap(_.datePatterns.get(dateStyle)) - val timePtrn = ldml.calendarPatterns.flatMap(_.timePatterns.get(timeStyle)) + //val datePtrn = parentPatterns(ldml).flatMap(_.datePatterns.get(dateStyle)) + val datePtrn = patternsR(ldml, _.datePatterns.get(dateStyle)) + //val timePtrn = parentPatterns(ldml).flatMap(_.timePatterns.get(timeStyle)) + val timePtrn = patternsR(ldml, _.timePatterns.get(timeStyle)) (datePtrn, timePtrn) match { case (Some(d), Some(t)) => Some(new SimpleDateFormat(s"$d $t", aLocale)) case (Some(d), None) => Some(new SimpleDateFormat(s"$d", aLocale)) @@ -91,6 +102,8 @@ object DateFormat { } }.getOrElse(new SimpleDateFormat("", aLocale)) - final def getInstance(style: Int, aLocale: Locale): DateFormat = ??? - def getAvailableLocales(): Array[Locale] = ??? + final def getInstance(): DateFormat = + getDateTimeInstance(SHORT, SHORT) + + def getAvailableLocales(): Array[Locale] = Locale.getAvailableLocales } diff --git a/core/src/main/scala/java/text/DecimalFormatSymbols.scala b/core/src/main/scala/java/text/DecimalFormatSymbols.scala index fed2777c..668f8680 100644 --- a/core/src/main/scala/java/text/DecimalFormatSymbols.scala +++ b/core/src/main/scala/java/text/DecimalFormatSymbols.scala @@ -21,13 +21,14 @@ object DecimalFormatSymbols { private def initialize(locale: Locale, dfs: DecimalFormatSymbols): DecimalFormatSymbols = { // Find the correct numbering systems for the ldml - def ns(ldml: LDML): NumberingSystem = + def ns(ldml: LDML): NumberingSystem = { ldml.defaultNS.flatMap { n => root.digitSymbols.find(_.ns == n).collect { - case s @ Symbols(_, Some(alias), _, _, _, _, _, _, _, _, _) => alias - case s => n + case s@Symbols(_, Some(alias), _, _, _, _, _, _, _, _, _) => alias + case s => n } }.getOrElse(latn) + } LocaleRegistry .ldml(locale) diff --git a/project/src/main/scala/locales/ScalaLocaleCodeGen.scala b/project/src/main/scala/locales/ScalaLocaleCodeGen.scala index ba8fb678..952a7e8f 100644 --- a/project/src/main/scala/locales/ScalaLocaleCodeGen.scala +++ b/project/src/main/scala/locales/ScalaLocaleCodeGen.scala @@ -169,6 +169,7 @@ object CodeGenerator { case "long" => 1 case "medium" => 2 case "short" => 3 + case x => throw new IllegalArgumentException(s"Unknown format $x, abort ") } val dates = MAKE_MAP(cs.datePatterns.map(p => TUPLE(LIT(patternToIndex(p.patternType)), LIT(p.pattern)))) @@ -315,21 +316,23 @@ object ScalaLocaleCodeGen { } def readCalendarPatterns(xml: Node): Option[CalendarPatterns] = { - def readPatterns(n: Node, formatType: String): Seq[DateTimePattern] = + def readPatterns(n: Node, sub: String, formatType: String): Seq[DateTimePattern] = for { - p <- n \\ formatType - } yield DateTimePattern((p \ "@type").text, (p \\ "pattern").text) + ft <- n \ formatType + p <- ft \ sub \ "pattern" + if (p \ "@alt").text != "variant" + } yield DateTimePattern((ft \ "@type").text, p.text) val datePatterns = (for { df <- xml \\ "dateFormats" } yield { - readPatterns(df, "dateFormatLength") + readPatterns(df, "dateFormat", "dateFormatLength") }).headOption.map(_.toList) val timePatterns = (for { df <- xml \\ "timeFormats" } yield { - readPatterns(df, "timeFormatLength") + readPatterns(df, "timeFormat", "timeFormatLength") }).headOption.map(_.toList) Some(CalendarPatterns(datePatterns.getOrElse(Nil), timePatterns.getOrElse(Nil))) diff --git a/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala b/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala index b6cf5fdc..3cbc8961 100644 --- a/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala +++ b/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala @@ -1,11 +1,15 @@ package testsuite.javalib.text import java.text.{DateFormat, SimpleDateFormat} +import java.util.Locale import org.junit.Assert._ import org.junit.Test +import testsuite.utils.{LocaleTestSetup, Platform} + +class DateFormatTest extends LocaleTestSetup { + case class TestCase(l: Locale, cldr21: Boolean, dateFormats: Map[Int, String], timeFormats: Map[Int, String]) -class DateFormatTest { @Test def test_constants(): Unit = { assertEquals(0, DateFormat.ERA_FIELD) assertEquals(1, DateFormat.YEAR_FIELD) @@ -33,6 +37,10 @@ class DateFormatTest { assertEquals(2, DateFormat.DEFAULT) } + @Test def test_available_locales(): Unit = { + assertTrue(DateFormat.getAvailableLocales.contains(Locale.ENGLISH)) + } + @Test def test_default_date_format(): Unit = { assertEquals("EEEE, MMMM d, y", DateFormat.getDateInstance(DateFormat.FULL).asInstanceOf[SimpleDateFormat].toPattern()) assertEquals("MMMM d, y", DateFormat.getDateInstance(DateFormat.LONG).asInstanceOf[SimpleDateFormat].toPattern()) @@ -61,4 +69,438 @@ class DateFormatTest { assertEquals("M/d/yy h:mm:ss a", DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM).asInstanceOf[SimpleDateFormat].toPattern()) assertEquals("M/d/yy h:mm a", DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).asInstanceOf[SimpleDateFormat].toPattern()) } + + val stdLocales = List( + TestCase(Locale.ENGLISH, cldr21 = false, Map( + DateFormat.FULL -> "EEEE, MMMM d, y", + DateFormat.LONG -> "MMMM d, y", + DateFormat.MEDIUM -> "MMM d, y", + DateFormat.SHORT -> "M/d/yy"), + Map( + DateFormat.FULL -> "h:mm:ss a zzzz", + DateFormat.LONG -> "h:mm:ss a z", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")), + TestCase(Locale.US, cldr21 = false, Map( + DateFormat.FULL -> "EEEE, MMMM d, y", + DateFormat.LONG -> "MMMM d, y", + DateFormat.MEDIUM -> "MMM d, y", + DateFormat.SHORT -> "M/d/yy"), + Map( + DateFormat.FULL -> "h:mm:ss a zzzz", + DateFormat.LONG -> "h:mm:ss a z", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")) + ) + + val stdLocalesDiff = List( + TestCase(Locale.FRENCH, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "dd/MM/yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.FRENCH, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "dd/MM/y"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.GERMAN, cldr21 = true, Map( + DateFormat.FULL -> "EEEE, d. MMMM y", + DateFormat.LONG -> "d. MMMM y", + DateFormat.MEDIUM -> "dd.MM.yyyy", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.GERMAN, cldr21 = false, Map( + DateFormat.FULL -> "EEEE, d. MMMM y", + DateFormat.LONG -> "d. MMMM y", + DateFormat.MEDIUM -> "dd.MM.y", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.ITALIAN, cldr21 = true, Map( + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "dd MMMM y", + DateFormat.MEDIUM -> "dd/MMM/y", + DateFormat.SHORT -> "dd/MM/yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.ITALIAN, cldr21 = false, Map( + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "dd MMM y", + DateFormat.SHORT -> "dd/MM/yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.JAPANESE, cldr21 = true, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy/MM/dd", + DateFormat.SHORT -> "yyyy/MM/dd"), + Map( + DateFormat.FULL -> "H時mm分ss秒 zzzz", + DateFormat.LONG -> "H:mm:ss z", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(Locale.JAPANESE, cldr21 = false, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y/MM/dd", + DateFormat.SHORT -> "y/MM/dd"), + Map( + DateFormat.FULL -> "H時mm分ss秒 zzzz", + DateFormat.LONG -> "H:mm:ss z", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(Locale.KOREAN, cldr21 = true, Map( + DateFormat.FULL -> "y년 M월 d일 EEEE", + DateFormat.LONG -> "y년 M월 d일", + DateFormat.MEDIUM -> "yyyy. M. d.", + DateFormat.SHORT -> "yy. M. d."), + Map( + DateFormat.FULL -> "a h시 m분 s초 zzzz", + DateFormat.LONG -> "a h시 m분 s초 z", + DateFormat.MEDIUM -> "a h:mm:ss", + DateFormat.SHORT -> "a h:mm")), + TestCase(Locale.KOREAN, cldr21 = false, Map( + DateFormat.FULL -> "y년 M월 d일 EEEE", + DateFormat.LONG -> "y년 M월 d일", + DateFormat.MEDIUM -> "y. M. d.", + DateFormat.SHORT -> "yy. M. d."), + Map( + DateFormat.FULL -> "a h시 m분 s초 zzzz", + DateFormat.LONG -> "a h시 m분 s초 z", + DateFormat.MEDIUM -> "a h:mm:ss", + DateFormat.SHORT -> "a h:mm")), + TestCase(Locale.CHINESE, cldr21 = true, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy-M-d", + DateFormat.SHORT -> "yy-M-d"), + Map( + DateFormat.FULL -> "zzzzah时mm分ss秒", + DateFormat.LONG -> "zah时mm分ss秒", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.CHINESE, cldr21 = false, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y年M月d日", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "zzzz ah:mm:ss", + DateFormat.LONG -> "z ah:mm:ss", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.SIMPLIFIED_CHINESE, cldr21 = true, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy-M-d", + DateFormat.SHORT -> "yy-M-d"), + Map( + DateFormat.FULL -> "zzzzah时mm分ss秒", + DateFormat.LONG -> "zah时mm分ss秒", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.SIMPLIFIED_CHINESE, cldr21 = false, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y年M月d日", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "zzzz ah:mm:ss", + DateFormat.LONG -> "z ah:mm:ss", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.TRADITIONAL_CHINESE, cldr21 = true, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy/M/d", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "zzzzah時mm分ss秒", + DateFormat.LONG -> "zah時mm分ss秒", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.TRADITIONAL_CHINESE, cldr21 = false, Map( + DateFormat.FULL -> "y年M月d日 EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y年M月d日", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "ah:mm:ss [zzzz]", + DateFormat.LONG -> "ah:mm:ss [z]", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.FRANCE, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "dd/MM/yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.FRANCE, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "dd/MM/y"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.GERMANY, cldr21 = true, Map( + DateFormat.FULL -> "EEEE, d. MMMM y", + DateFormat.LONG -> "d. MMMM y", + DateFormat.MEDIUM -> "dd.MM.yyyy", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.GERMANY, cldr21 = false, Map( + DateFormat.FULL -> "EEEE, d. MMMM y", + DateFormat.LONG -> "d. MMMM y", + DateFormat.MEDIUM -> "dd.MM.y", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.ITALY, cldr21 = true, Map( + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "dd MMMM y", + DateFormat.MEDIUM -> "dd/MMM/y", + DateFormat.SHORT -> "dd/MM/yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.ITALY, cldr21 = false, Map( + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "dd MMM y", + DateFormat.SHORT -> "dd/MM/yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.JAPAN, cldr21 = true, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy/MM/dd", + DateFormat.SHORT -> "yyyy/MM/dd"), + Map( + DateFormat.FULL -> "H時mm分ss秒 zzzz", + DateFormat.LONG -> "H:mm:ss z", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(Locale.JAPAN, cldr21 = false, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y/MM/dd", + DateFormat.SHORT -> "y/MM/dd"), + Map( + DateFormat.FULL -> "H時mm分ss秒 zzzz", + DateFormat.LONG -> "H:mm:ss z", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(Locale.KOREA, cldr21 = true, Map( + DateFormat.FULL -> "y년 M월 d일 EEEE", + DateFormat.LONG -> "y년 M월 d일", + DateFormat.MEDIUM -> "yyyy. M. d.", + DateFormat.SHORT -> "yy. M. d."), + Map( + DateFormat.FULL -> "a h시 m분 s초 zzzz", + DateFormat.LONG -> "a h시 m분 s초 z", + DateFormat.MEDIUM -> "a h:mm:ss", + DateFormat.SHORT -> "a h:mm")), + TestCase(Locale.KOREA, cldr21 = false, Map( + DateFormat.FULL -> "y년 M월 d일 EEEE", + DateFormat.LONG -> "y년 M월 d일", + DateFormat.MEDIUM -> "y. M. d.", + DateFormat.SHORT -> "yy. M. d."), + Map( + DateFormat.FULL -> "a h시 m분 s초 zzzz", + DateFormat.LONG -> "a h시 m분 s초 z", + DateFormat.MEDIUM -> "a h:mm:ss", + DateFormat.SHORT -> "a h:mm")), + TestCase(Locale.CHINA, cldr21 = true, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy-M-d", + DateFormat.SHORT -> "yy-M-d"), + Map( + DateFormat.FULL -> "zzzzah时mm分ss秒", + DateFormat.LONG -> "zah时mm分ss秒", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.CHINA, cldr21 = false, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y年M月d日", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "zzzz ah:mm:ss", + DateFormat.LONG -> "z ah:mm:ss", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.TAIWAN, cldr21 = true, Map( + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy/M/d", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "zzzzah時mm分ss秒", + DateFormat.LONG -> "zah時mm分ss秒", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.TAIWAN, cldr21 = false, Map( + DateFormat.FULL -> "y年M月d日 EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y年M月d日", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "ah:mm:ss [zzzz]", + DateFormat.LONG -> "ah:mm:ss [z]", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(Locale.UK, cldr21 = true, Map( + DateFormat.FULL -> "EEEE, d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "dd/MM/yyyy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.UK, cldr21 = false, Map( + DateFormat.FULL -> "EEEE, MMMM d, y", + DateFormat.LONG -> "MMMM d, y", + DateFormat.MEDIUM -> "MMM d, y", + DateFormat.SHORT -> "M/d/yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.CANADA, cldr21 = true, Map( + DateFormat.FULL -> "EEEE, d MMMM, y", + DateFormat.LONG -> "d MMMM, y", + DateFormat.MEDIUM -> "yyyy-MM-dd", + DateFormat.SHORT -> "yy-MM-dd"), + Map( + DateFormat.FULL -> "h:mm:ss a zzzz", + DateFormat.LONG -> "h:mm:ss a z", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")), + TestCase(Locale.CANADA, cldr21 = false, Map( + DateFormat.FULL -> "EEEE, MMMM d, y", + DateFormat.LONG -> "MMMM d, y", + DateFormat.MEDIUM -> "MMM d, y", + DateFormat.SHORT -> "y-MM-dd"), + Map( + DateFormat.FULL -> "h:mm:ss a zzzz", + DateFormat.LONG -> "h:mm:ss a z", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")), + TestCase(Locale.CANADA_FRENCH, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "yyyy-MM-dd", + DateFormat.SHORT -> "yy-MM-dd"), + Map( + DateFormat.FULL -> "HH 'h' mm 'min' ss 's' zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(Locale.CANADA_FRENCH, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "yy-MM-dd"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")) + ) + + @Test def test_standard_locales(): Unit = { + stdLocales.foreach { tc => + for { + df <- tc.dateFormats + } yield { + assertEquals(df._2, DateFormat.getDateInstance(df._1, tc.l).asInstanceOf[SimpleDateFormat].toPattern()) + } + + for { + tf <- tc.timeFormats + } yield { + assertEquals(tf._2, DateFormat.getTimeInstance(tf._1, tc.l).asInstanceOf[SimpleDateFormat].toPattern()) + } + + for { + df <- tc.dateFormats + tf <- tc.timeFormats + } yield { + assertEquals(s"${df._2} ${tf._2}", DateFormat.getDateTimeInstance(df._1, tf._1, tc.l).asInstanceOf[SimpleDateFormat].toPattern()) + } + } + } + + @Test def test_standard_locales_diff(): Unit = { + stdLocalesDiff.filter(tc => (Platform.executingInJVM && tc.cldr21) || (!Platform.executingInJVM && !tc.cldr21)).foreach { tc => + println(tc.l.toLanguageTag()) + + for { + df <- tc.dateFormats + } yield { + assertEquals(df._2, DateFormat.getDateInstance(df._1, tc.l).asInstanceOf[SimpleDateFormat].toPattern()) + } + + for { + tf <- tc.timeFormats + } yield { + assertEquals(tf._2, DateFormat.getTimeInstance(tf._1, tc.l).asInstanceOf[SimpleDateFormat].toPattern()) + } + + for { + df <- tc.dateFormats + tf <- tc.timeFormats + } yield { + assertEquals(s"${df._2} ${tf._2}", DateFormat.getDateTimeInstance(df._1, tf._1, tc.l).asInstanceOf[SimpleDateFormat].toPattern()) + } + } + } } From 21c2f4bffa4aaca6a7bbf65aec05bb45ddd6a498 Mon Sep 17 00:00:00 2001 From: Carlos Quiroz Date: Wed, 20 Jul 2016 13:56:48 -0400 Subject: [PATCH 8/8] Test non standard locales --- .../src/main/scala/java/text/DateFormat.scala | 4 - .../javalib/text/DateFormatTest.scala | 429 ++++++++++++++++-- 2 files changed, 388 insertions(+), 45 deletions(-) diff --git a/core/src/main/scala/java/text/DateFormat.scala b/core/src/main/scala/java/text/DateFormat.scala index 3578c181..2c4ebfb8 100644 --- a/core/src/main/scala/java/text/DateFormat.scala +++ b/core/src/main/scala/java/text/DateFormat.scala @@ -77,9 +77,7 @@ object DateFormat { final def getDateInstance(style: Int, aLocale: Locale): DateFormat = LocaleRegistry.ldml(aLocale).flatMap { ldml => - //val ptrn = parentPatterns(ldml).flatMap(_.datePatterns.get(style)) val ptrn = patternsR(ldml, _.datePatterns.get(style)) - println(ptrn) ptrn.map(new SimpleDateFormat(_, aLocale)) }.getOrElse(new SimpleDateFormat("", aLocale)) @@ -90,9 +88,7 @@ object DateFormat { final def getDateTimeInstance(dateStyle: Int, timeStyle: Int, aLocale: Locale): DateFormat = LocaleRegistry.ldml(aLocale).flatMap { ldml => - //val datePtrn = parentPatterns(ldml).flatMap(_.datePatterns.get(dateStyle)) val datePtrn = patternsR(ldml, _.datePatterns.get(dateStyle)) - //val timePtrn = parentPatterns(ldml).flatMap(_.timePatterns.get(timeStyle)) val timePtrn = patternsR(ldml, _.timePatterns.get(timeStyle)) (datePtrn, timePtrn) match { case (Some(d), Some(t)) => Some(new SimpleDateFormat(s"$d $t", aLocale)) diff --git a/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala b/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala index 3cbc8961..99f7021d 100644 --- a/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala +++ b/testSuite/shared/src/test/scala/testsuite/javalib/text/DateFormatTest.scala @@ -3,12 +3,15 @@ package testsuite.javalib.text import java.text.{DateFormat, SimpleDateFormat} import java.util.Locale +import locales.LocaleRegistry +import locales.cldr.LDML +import locales.cldr.data._ import org.junit.Assert._ import org.junit.Test import testsuite.utils.{LocaleTestSetup, Platform} class DateFormatTest extends LocaleTestSetup { - case class TestCase(l: Locale, cldr21: Boolean, dateFormats: Map[Int, String], timeFormats: Map[Int, String]) + case class TestCase(ldml: LDML, tag: String, l: Locale, cldr21: Boolean, dateFormats: Map[Int, String], timeFormats: Map[Int, String]) @Test def test_constants(): Unit = { assertEquals(0, DateFormat.ERA_FIELD) @@ -71,7 +74,7 @@ class DateFormatTest extends LocaleTestSetup { } val stdLocales = List( - TestCase(Locale.ENGLISH, cldr21 = false, Map( + TestCase(root, "", Locale.ENGLISH, cldr21 = false, Map( DateFormat.FULL -> "EEEE, MMMM d, y", DateFormat.LONG -> "MMMM d, y", DateFormat.MEDIUM -> "MMM d, y", @@ -81,7 +84,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "h:mm:ss a z", DateFormat.MEDIUM -> "h:mm:ss a", DateFormat.SHORT -> "h:mm a")), - TestCase(Locale.US, cldr21 = false, Map( + TestCase(root, "", Locale.US, cldr21 = false, Map( DateFormat.FULL -> "EEEE, MMMM d, y", DateFormat.LONG -> "MMMM d, y", DateFormat.MEDIUM -> "MMM d, y", @@ -94,7 +97,7 @@ class DateFormatTest extends LocaleTestSetup { ) val stdLocalesDiff = List( - TestCase(Locale.FRENCH, cldr21 = true, Map( // JVM + TestCase(root, "", Locale.FRENCH, cldr21 = true, Map( // JVM DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "d MMM y", @@ -104,7 +107,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.FRENCH, cldr21 = false, Map( // JS + TestCase(root, "", Locale.FRENCH, cldr21 = false, Map( // JS DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "d MMM y", @@ -114,7 +117,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.GERMAN, cldr21 = true, Map( + TestCase(root, "", Locale.GERMAN, cldr21 = true, Map( DateFormat.FULL -> "EEEE, d. MMMM y", DateFormat.LONG -> "d. MMMM y", DateFormat.MEDIUM -> "dd.MM.yyyy", @@ -124,7 +127,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.GERMAN, cldr21 = false, Map( + TestCase(root, "", Locale.GERMAN, cldr21 = false, Map( DateFormat.FULL -> "EEEE, d. MMMM y", DateFormat.LONG -> "d. MMMM y", DateFormat.MEDIUM -> "dd.MM.y", @@ -134,7 +137,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.ITALIAN, cldr21 = true, Map( + TestCase(root, "", Locale.ITALIAN, cldr21 = true, Map( DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "dd MMMM y", DateFormat.MEDIUM -> "dd/MMM/y", @@ -144,7 +147,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.ITALIAN, cldr21 = false, Map( + TestCase(root, "", Locale.ITALIAN, cldr21 = false, Map( DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "dd MMM y", @@ -154,7 +157,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.JAPANESE, cldr21 = true, Map( + TestCase(root, "", Locale.JAPANESE, cldr21 = true, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "yyyy/MM/dd", @@ -164,7 +167,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "H:mm:ss z", DateFormat.MEDIUM -> "H:mm:ss", DateFormat.SHORT -> "H:mm")), - TestCase(Locale.JAPANESE, cldr21 = false, Map( + TestCase(root, "", Locale.JAPANESE, cldr21 = false, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "y/MM/dd", @@ -174,7 +177,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "H:mm:ss z", DateFormat.MEDIUM -> "H:mm:ss", DateFormat.SHORT -> "H:mm")), - TestCase(Locale.KOREAN, cldr21 = true, Map( + TestCase(root, "", Locale.KOREAN, cldr21 = true, Map( DateFormat.FULL -> "y년 M월 d일 EEEE", DateFormat.LONG -> "y년 M월 d일", DateFormat.MEDIUM -> "yyyy. M. d.", @@ -184,7 +187,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "a h시 m분 s초 z", DateFormat.MEDIUM -> "a h:mm:ss", DateFormat.SHORT -> "a h:mm")), - TestCase(Locale.KOREAN, cldr21 = false, Map( + TestCase(root, "", Locale.KOREAN, cldr21 = false, Map( DateFormat.FULL -> "y년 M월 d일 EEEE", DateFormat.LONG -> "y년 M월 d일", DateFormat.MEDIUM -> "y. M. d.", @@ -194,7 +197,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "a h시 m분 s초 z", DateFormat.MEDIUM -> "a h:mm:ss", DateFormat.SHORT -> "a h:mm")), - TestCase(Locale.CHINESE, cldr21 = true, Map( + TestCase(root, "", Locale.CHINESE, cldr21 = true, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "yyyy-M-d", @@ -204,7 +207,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "zah时mm分ss秒", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.CHINESE, cldr21 = false, Map( + TestCase(root, "", Locale.CHINESE, cldr21 = false, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "y年M月d日", @@ -214,7 +217,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "z ah:mm:ss", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.SIMPLIFIED_CHINESE, cldr21 = true, Map( + TestCase(root, "", Locale.SIMPLIFIED_CHINESE, cldr21 = true, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "yyyy-M-d", @@ -224,7 +227,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "zah时mm分ss秒", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.SIMPLIFIED_CHINESE, cldr21 = false, Map( + TestCase(root, "", Locale.SIMPLIFIED_CHINESE, cldr21 = false, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "y年M月d日", @@ -234,7 +237,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "z ah:mm:ss", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.TRADITIONAL_CHINESE, cldr21 = true, Map( + TestCase(root, "", Locale.TRADITIONAL_CHINESE, cldr21 = true, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "yyyy/M/d", @@ -244,7 +247,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "zah時mm分ss秒", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.TRADITIONAL_CHINESE, cldr21 = false, Map( + TestCase(root, "", Locale.TRADITIONAL_CHINESE, cldr21 = false, Map( DateFormat.FULL -> "y年M月d日 EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "y年M月d日", @@ -254,7 +257,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "ah:mm:ss [z]", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.FRANCE, cldr21 = true, Map( // JVM + TestCase(root, "", Locale.FRANCE, cldr21 = true, Map( // JVM DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "d MMM y", @@ -264,7 +267,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.FRANCE, cldr21 = false, Map( // JS + TestCase(root, "", Locale.FRANCE, cldr21 = false, Map( // JS DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "d MMM y", @@ -274,7 +277,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.GERMANY, cldr21 = true, Map( + TestCase(root, "", Locale.GERMANY, cldr21 = true, Map( DateFormat.FULL -> "EEEE, d. MMMM y", DateFormat.LONG -> "d. MMMM y", DateFormat.MEDIUM -> "dd.MM.yyyy", @@ -284,7 +287,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.GERMANY, cldr21 = false, Map( + TestCase(root, "", Locale.GERMANY, cldr21 = false, Map( DateFormat.FULL -> "EEEE, d. MMMM y", DateFormat.LONG -> "d. MMMM y", DateFormat.MEDIUM -> "dd.MM.y", @@ -294,7 +297,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.ITALY, cldr21 = true, Map( + TestCase(root, "", Locale.ITALY, cldr21 = true, Map( DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "dd MMMM y", DateFormat.MEDIUM -> "dd/MMM/y", @@ -304,7 +307,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.ITALY, cldr21 = false, Map( + TestCase(root, "", Locale.ITALY, cldr21 = false, Map( DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "dd MMM y", @@ -314,7 +317,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.JAPAN, cldr21 = true, Map( + TestCase(root, "", Locale.JAPAN, cldr21 = true, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "yyyy/MM/dd", @@ -324,7 +327,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "H:mm:ss z", DateFormat.MEDIUM -> "H:mm:ss", DateFormat.SHORT -> "H:mm")), - TestCase(Locale.JAPAN, cldr21 = false, Map( + TestCase(root, "", Locale.JAPAN, cldr21 = false, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "y/MM/dd", @@ -334,7 +337,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "H:mm:ss z", DateFormat.MEDIUM -> "H:mm:ss", DateFormat.SHORT -> "H:mm")), - TestCase(Locale.KOREA, cldr21 = true, Map( + TestCase(root, "", Locale.KOREA, cldr21 = true, Map( DateFormat.FULL -> "y년 M월 d일 EEEE", DateFormat.LONG -> "y년 M월 d일", DateFormat.MEDIUM -> "yyyy. M. d.", @@ -344,7 +347,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "a h시 m분 s초 z", DateFormat.MEDIUM -> "a h:mm:ss", DateFormat.SHORT -> "a h:mm")), - TestCase(Locale.KOREA, cldr21 = false, Map( + TestCase(root, "", Locale.KOREA, cldr21 = false, Map( DateFormat.FULL -> "y년 M월 d일 EEEE", DateFormat.LONG -> "y년 M월 d일", DateFormat.MEDIUM -> "y. M. d.", @@ -354,7 +357,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "a h시 m분 s초 z", DateFormat.MEDIUM -> "a h:mm:ss", DateFormat.SHORT -> "a h:mm")), - TestCase(Locale.CHINA, cldr21 = true, Map( + TestCase(root, "", Locale.CHINA, cldr21 = true, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "yyyy-M-d", @@ -364,7 +367,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "zah时mm分ss秒", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.CHINA, cldr21 = false, Map( + TestCase(root, "", Locale.CHINA, cldr21 = false, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "y年M月d日", @@ -374,7 +377,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "z ah:mm:ss", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.TAIWAN, cldr21 = true, Map( + TestCase(root, "", Locale.TAIWAN, cldr21 = true, Map( DateFormat.FULL -> "y年M月d日EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "yyyy/M/d", @@ -384,7 +387,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "zah時mm分ss秒", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.TAIWAN, cldr21 = false, Map( + TestCase(root, "", Locale.TAIWAN, cldr21 = false, Map( DateFormat.FULL -> "y年M月d日 EEEE", DateFormat.LONG -> "y年M月d日", DateFormat.MEDIUM -> "y年M月d日", @@ -394,7 +397,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "ah:mm:ss [z]", DateFormat.MEDIUM -> "ah:mm:ss", DateFormat.SHORT -> "ah:mm")), - TestCase(Locale.UK, cldr21 = true, Map( + TestCase(root, "", Locale.UK, cldr21 = true, Map( DateFormat.FULL -> "EEEE, d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "d MMM y", @@ -404,7 +407,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.UK, cldr21 = false, Map( + TestCase(root, "", Locale.UK, cldr21 = false, Map( DateFormat.FULL -> "EEEE, MMMM d, y", DateFormat.LONG -> "MMMM d, y", DateFormat.MEDIUM -> "MMM d, y", @@ -414,7 +417,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.CANADA, cldr21 = true, Map( + TestCase(root, "", Locale.CANADA, cldr21 = true, Map( DateFormat.FULL -> "EEEE, d MMMM, y", DateFormat.LONG -> "d MMMM, y", DateFormat.MEDIUM -> "yyyy-MM-dd", @@ -424,7 +427,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "h:mm:ss a z", DateFormat.MEDIUM -> "h:mm:ss a", DateFormat.SHORT -> "h:mm a")), - TestCase(Locale.CANADA, cldr21 = false, Map( + TestCase(root, "", Locale.CANADA, cldr21 = false, Map( DateFormat.FULL -> "EEEE, MMMM d, y", DateFormat.LONG -> "MMMM d, y", DateFormat.MEDIUM -> "MMM d, y", @@ -434,7 +437,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "h:mm:ss a z", DateFormat.MEDIUM -> "h:mm:ss a", DateFormat.SHORT -> "h:mm a")), - TestCase(Locale.CANADA_FRENCH, cldr21 = true, Map( // JVM + TestCase(root, "", Locale.CANADA_FRENCH, cldr21 = true, Map( // JVM DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "yyyy-MM-dd", @@ -444,7 +447,7 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.LONG -> "HH:mm:ss z", DateFormat.MEDIUM -> "HH:mm:ss", DateFormat.SHORT -> "HH:mm")), - TestCase(Locale.CANADA_FRENCH, cldr21 = false, Map( // JS + TestCase(root, "", Locale.CANADA_FRENCH, cldr21 = false, Map( // JS DateFormat.FULL -> "EEEE d MMMM y", DateFormat.LONG -> "d MMMM y", DateFormat.MEDIUM -> "d MMM y", @@ -456,6 +459,294 @@ class DateFormatTest extends LocaleTestSetup { DateFormat.SHORT -> "HH:mm")) ) + // Test cases by language tag where the JVM gives the same asJS + val localesByTag = List( + TestCase(bn, "bn", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, d MMMM, y", + DateFormat.LONG -> "d MMMM, y", + DateFormat.MEDIUM -> "d MMM, y", + DateFormat.SHORT -> "d/M/yy"), + Map( + DateFormat.FULL -> "h:mm:ss a zzzz", + DateFormat.LONG -> "h:mm:ss a z", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")), + TestCase(lv, "lv", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE, y. 'gada' d. MMMM", + DateFormat.LONG -> "y. 'gada' d. MMMM", + DateFormat.MEDIUM -> "y. 'gada' d. MMM", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")) + ) + + // Test cases by language tag where the JVM differs from JS + val localesByTagDiff = List( + TestCase(af, "af", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE dd MMMM y", + DateFormat.LONG -> "dd MMMM y", + DateFormat.MEDIUM -> "dd MMM y", + DateFormat.SHORT -> "yyyy-MM-dd"), + Map( + DateFormat.FULL -> "h:mm:ss a zzzz", + DateFormat.LONG -> "h:mm:ss a z", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")), + TestCase(af, "af", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE, dd MMMM y", + DateFormat.LONG -> "dd MMMM y", + DateFormat.MEDIUM -> "dd MMM y", + DateFormat.SHORT -> "y-MM-dd"), + Map( + DateFormat.FULL -> "h:mm:ss a zzzz", + DateFormat.LONG -> "h:mm:ss a z", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")), + TestCase(az, "az", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, d, MMMM, y", + DateFormat.LONG -> "d MMMM , y", + DateFormat.MEDIUM -> "d MMM, y", + DateFormat.SHORT -> "yyyy-MM-dd"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(az, "az", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "d MMMM y, EEEE", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(az_Cyrl, "az-Cyrl", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, d, MMMM, y", + DateFormat.LONG -> "d MMMM , y", + DateFormat.MEDIUM -> "d MMM, y", + DateFormat.SHORT -> "yyyy-MM-dd"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(az_Cyrl, "az-Cyrl", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE, d, MMMM, y", + DateFormat.LONG -> "d MMMM, y", + DateFormat.MEDIUM -> "d MMM, y", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(es_CL, "es-CL", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, d 'de' MMMM 'de' y", + DateFormat.LONG -> "d 'de' MMMM 'de' y", + DateFormat.MEDIUM -> "dd-MM-yyyy", + DateFormat.SHORT -> "dd-MM-yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "H:mm:ss z", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(es_CL, "es-CL", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE, d 'de' MMMM 'de' y", + DateFormat.LONG -> "d 'de' MMMM 'de' y", + DateFormat.MEDIUM -> "dd-MM-y", + DateFormat.SHORT -> "dd-MM-yy"), + Map( + DateFormat.FULL -> "H:mm:ss (zzzz)", + DateFormat.LONG -> "H:mm:ss z", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(it_CH, "it-CH", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d-MMM-y", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH.mm:ss 'h' zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(it_CH, "it-CH", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE, d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(zh, "zh", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy-M-d", + DateFormat.SHORT -> "yy-M-d"), + Map( + DateFormat.FULL -> "zzzzah时mm分ss秒", + DateFormat.LONG -> "zah时mm分ss秒", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(zh, "zh", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y年M月d日", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "zzzz ah:mm:ss", + DateFormat.LONG -> "z ah:mm:ss", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(zh_Hant, "zh-Hant", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "y年M月d日EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "yyyy/M/d", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "zzzzah時mm分ss秒", + DateFormat.LONG -> "zah時mm分ss秒", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(zh_Hant, "zh-Hant", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "y年M月d日 EEEE", + DateFormat.LONG -> "y年M月d日", + DateFormat.MEDIUM -> "y年M月d日", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "ah:mm:ss [zzzz]", + DateFormat.LONG -> "ah:mm:ss [z]", + DateFormat.MEDIUM -> "ah:mm:ss", + DateFormat.SHORT -> "ah:mm")), + TestCase(ar, "ar", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE، d MMMM، y", + DateFormat.LONG -> "d MMMM، y", + DateFormat.MEDIUM -> "dd‏/MM‏/yyyy", + DateFormat.SHORT -> "d‏/M‏/yyyy"), + Map( + DateFormat.FULL -> "zzzz h:mm:ss a", + DateFormat.LONG -> "z h:mm:ss a", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")), + TestCase(ar, "ar", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE، d MMMM، y", + DateFormat.LONG -> "d MMMM، y", + DateFormat.MEDIUM -> "dd‏/MM‏/y", + DateFormat.SHORT -> "d‏/M‏/y"), + Map( + DateFormat.FULL -> "h:mm:ss a zzzz", + DateFormat.LONG -> "h:mm:ss a z", + DateFormat.MEDIUM -> "h:mm:ss a", + DateFormat.SHORT -> "h:mm a")), + TestCase(fa, "fa", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "yyyy/M/d"), + Map( + DateFormat.FULL -> "H:mm:ss (zzzz)", + DateFormat.LONG -> "H:mm:ss (z)", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(fa, "fa", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE d MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "y/M/d"), + Map( + DateFormat.FULL -> "H:mm:ss (zzzz)", + DateFormat.LONG -> "H:mm:ss (z)", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(fi_FI, "fi-FI", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, d. MMMM y", + DateFormat.LONG -> "d. MMMM y", + DateFormat.MEDIUM -> "d.M.yyyy", + DateFormat.SHORT -> "d.M.yyyy"), + Map( + DateFormat.FULL -> "H.mm.ss zzzz", + DateFormat.LONG -> "H.mm.ss z", + DateFormat.MEDIUM -> "H.mm.ss", + DateFormat.SHORT -> "H.mm")), + TestCase(fi_FI, "fi-FI", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "cccc d. MMMM y", + DateFormat.LONG -> "d. MMMM y", + DateFormat.MEDIUM -> "d.M.y", + DateFormat.SHORT -> "d.M.y"), + Map( + DateFormat.FULL -> "H.mm.ss zzzz", + DateFormat.LONG -> "H.mm.ss z", + DateFormat.MEDIUM -> "H.mm.ss", + DateFormat.SHORT -> "H.mm")), + TestCase(ka, "ka", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, y MMMM dd", + DateFormat.LONG -> "y MMMM d", + DateFormat.MEDIUM -> "y MMM d", + DateFormat.SHORT -> "yyyy-MM-dd"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(ka, "ka", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE, dd MMMM, y", + DateFormat.LONG -> "d MMMM, y", + DateFormat.MEDIUM -> "d MMM. y", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(my, "my", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, y MMMM dd", + DateFormat.LONG -> "y MMMM d", + DateFormat.MEDIUM -> "y MMM d", + DateFormat.SHORT -> "yy/MM/dd"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(my, "my", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE၊ dd MMMM y", + DateFormat.LONG -> "d MMMM y", + DateFormat.MEDIUM -> "d MMM y", + DateFormat.SHORT -> "dd-MM-yy"), + Map( + DateFormat.FULL -> "HH:mm:ss zzzz", + DateFormat.LONG -> "HH:mm:ss z", + DateFormat.MEDIUM -> "HH:mm:ss", + DateFormat.SHORT -> "HH:mm")), + TestCase(ru_RU, "ru-RU", Locale.ROOT, cldr21 = true, Map( // JVM + DateFormat.FULL -> "EEEE, d MMMM y\u00A0'г'.", + DateFormat.LONG -> "d MMMM y\u00A0'г'.", + DateFormat.MEDIUM -> "dd.MM.yyyy", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "H:mm:ss zzzz", + DateFormat.LONG -> "H:mm:ss z", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")), + TestCase(ru_RU, "ru-RU", Locale.ROOT, cldr21 = false, Map( // JS + DateFormat.FULL -> "EEEE, d MMMM y 'г'.", + DateFormat.LONG -> "d MMMM y 'г'.", + DateFormat.MEDIUM -> "d MMM y 'г'.", + DateFormat.SHORT -> "dd.MM.yy"), + Map( + DateFormat.FULL -> "H:mm:ss zzzz", + DateFormat.LONG -> "H:mm:ss z", + DateFormat.MEDIUM -> "H:mm:ss", + DateFormat.SHORT -> "H:mm")) + ) + @Test def test_standard_locales(): Unit = { stdLocales.foreach { tc => for { @@ -481,8 +772,6 @@ class DateFormatTest extends LocaleTestSetup { @Test def test_standard_locales_diff(): Unit = { stdLocalesDiff.filter(tc => (Platform.executingInJVM && tc.cldr21) || (!Platform.executingInJVM && !tc.cldr21)).foreach { tc => - println(tc.l.toLanguageTag()) - for { df <- tc.dateFormats } yield { @@ -503,4 +792,62 @@ class DateFormatTest extends LocaleTestSetup { } } } + + @Test def test_extra_locales(): Unit = { + localesByTag.foreach { tc => + if (!Platform.executingInJVM) { + LocaleRegistry.installLocale(tc.ldml) + } + val locale = Locale.forLanguageTag(tc.tag) + + for { + df <- tc.dateFormats + } yield { + assertEquals(df._2, DateFormat.getDateInstance(df._1, locale).asInstanceOf[SimpleDateFormat].toPattern()) + } + + for { + tf <- tc.timeFormats + } yield { + assertEquals(tf._2, DateFormat.getTimeInstance(tf._1, locale).asInstanceOf[SimpleDateFormat].toPattern()) + } + + for { + df <- tc.dateFormats + tf <- tc.timeFormats + } yield { + assertEquals(s"${df._2} ${tf._2}", DateFormat.getDateTimeInstance(df._1, tf._1, locale).asInstanceOf[SimpleDateFormat].toPattern()) + } + } + } + + @Test def test_extra_locales_diff(): Unit = { + localesByTagDiff.filter(tc => (Platform.executingInJVM && tc.cldr21) || (!Platform.executingInJVM && !tc.cldr21)).foreach { tc => + if (!Platform.executingInJVM) { + LocaleRegistry.installLocale(tc.ldml) + } + val locale = Locale.forLanguageTag(tc.tag) + + for { + df <- tc.dateFormats + } yield { + assertEquals(df._2, DateFormat.getDateInstance(df._1, locale).asInstanceOf[SimpleDateFormat].toPattern()) + } + + for { + tf <- tc.timeFormats + } yield { + assertEquals(tf._2, DateFormat.getTimeInstance(tf._1, locale).asInstanceOf[SimpleDateFormat].toPattern()) + } + + for { + df <- tc.dateFormats + tf <- tc.timeFormats + } yield { + if (!tc.cldr21) { + assertEquals(s"${df._2} ${tf._2}", DateFormat.getDateTimeInstance(df._1, tf._1, locale).asInstanceOf[SimpleDateFormat].toPattern()) + } + } + } + } }