Skip to content

Commit

Permalink
Merge pull request #49 from cquiroz/number-format
Browse files Browse the repository at this point in the history
Date and Number Format basic implementation
  • Loading branch information
cquiroz authored Jul 21, 2016
2 parents 84b6259 + 21c2f4b commit 6050e0b
Show file tree
Hide file tree
Showing 13 changed files with 1,197 additions and 11 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
```
Expand Down
105 changes: 105 additions & 0 deletions core/src/main/scala/java/text/DateFormat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
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 = ???
// 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 = 0
val LONG: Int = 1
val MEDIUM: Int = 2
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 =
getTimeInstance(style, Locale.getDefault(Locale.Category.FORMAT))

final def getTimeInstance(style: Int, aLocale: Locale): DateFormat =
LocaleRegistry.ldml(aLocale).flatMap { ldml =>
val ptrn = patternsR(ldml, _.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 = patternsR(ldml, _.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 = patternsR(ldml, _.datePatterns.get(dateStyle))
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))
case (None, Some(t)) => Some(new SimpleDateFormat(s"$t", aLocale))
case _ => Some(new SimpleDateFormat("", aLocale))
}
}.getOrElse(new SimpleDateFormat("", aLocale))

final def getInstance(): DateFormat =
getDateTimeInstance(SHORT, SHORT)

def getAvailableLocales(): Array[Locale] = Locale.getAvailableLocales
}
2 changes: 1 addition & 1 deletion core/src/main/scala/java/text/DateFormatSymbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =>
Expand Down
57 changes: 57 additions & 0 deletions core/src/main/scala/java/text/DecimalFormat.scala
Original file line number Diff line number Diff line change
@@ -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 = ???
}
7 changes: 4 additions & 3 deletions core/src/main/scala/java/text/DecimalFormatSymbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
53 changes: 53 additions & 0 deletions core/src/main/scala/java/text/NumberFormat.scala
Original file line number Diff line number Diff line change
@@ -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] = ???
}
34 changes: 34 additions & 0 deletions core/src/main/scala/java/text/SimpleDateFormat.scala
Original file line number Diff line number Diff line change
@@ -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 = ???
}
4 changes: 2 additions & 2 deletions core/src/main/scala/locales/LocaleRegistry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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()
}
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/scala/locales/cldr/cldr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -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

Expand Down
Loading

0 comments on commit 6050e0b

Please sign in to comment.