aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlad <vlad@driver.xyz>2017-03-20 18:55:58 -0700
committervlad <vlad@driver.xyz>2017-03-20 18:55:58 -0700
commitdcceb9aae8073617f43335c83647af5ccf8685ef (patch)
treee055c0556a58614588473b862b9f315f945e8163
parent7f03501bf652214a4a8d12f62764f73257714d7e (diff)
parent5b96449bfcb9117c755e1b48a8462f79d6e1230c (diff)
downloaddriver-core-dcceb9aae8073617f43335c83647af5ccf8685ef.tar.gz
driver-core-dcceb9aae8073617f43335c83647af5ccf8685ef.tar.bz2
driver-core-dcceb9aae8073617f43335c83647af5ccf8685ef.zip
Merge remote-tracking branch 'origin/master' into master3v0.10.31
-rw-r--r--src/main/scala/xyz/driver/core/database/package.scala4
-rw-r--r--src/main/scala/xyz/driver/core/date.scala75
-rw-r--r--src/main/scala/xyz/driver/core/json.scala10
-rw-r--r--src/main/scala/xyz/driver/core/time.scala2
-rw-r--r--src/test/scala/xyz/driver/core/DateTest.scala2
5 files changed, 72 insertions, 21 deletions
diff --git a/src/main/scala/xyz/driver/core/database/package.scala b/src/main/scala/xyz/driver/core/database/package.scala
index 32b240e..791a688 100644
--- a/src/main/scala/xyz/driver/core/database/package.scala
+++ b/src/main/scala/xyz/driver/core/database/package.scala
@@ -3,7 +3,7 @@ package xyz.driver.core
import java.sql.{Date => SqlDate}
import java.util.Calendar
-import date.Date
+import date.{Date, Month}
import slick.dbio.{DBIOAction, NoStream}
package object database {
@@ -18,7 +18,7 @@ package object database {
// should only be interpreted in the running JVMs timezone.
val cal = Calendar.getInstance()
cal.setTime(sqlDate)
- Date(cal.get(Calendar.YEAR), date.tagMonth(cal.get(Calendar.MONTH)), cal.get(Calendar.DAY_OF_MONTH))
+ Date(cal.get(Calendar.YEAR), Month(cal.get(Calendar.MONTH)), cal.get(Calendar.DAY_OF_MONTH))
}
private[database] def dateToSqlDate(date: Date): SqlDate = {
diff --git a/src/main/scala/xyz/driver/core/date.scala b/src/main/scala/xyz/driver/core/date.scala
index 5a6f736..d6f64e4 100644
--- a/src/main/scala/xyz/driver/core/date.scala
+++ b/src/main/scala/xyz/driver/core/date.scala
@@ -2,24 +2,67 @@ package xyz.driver.core
import java.util.Calendar
+import scala.util.Try
+
+import scalaz.std.anyVal._
+import scalaz.syntax.equal._
+
+/**
+ * Driver Date type and related validators/extractors.
+ * Day, Month, and Year extractors are from ISO 8601 strings => driver...Date integers.
+ * TODO: Decouple extractors from ISO 8601, as we might want to parse other formats.
+ */
object date {
+ type Day = Int @@ Day.type
+
+ object Day {
+ def apply(value: Int): Day = {
+ require(1 to 31 contains value, "Day must be in range 1 <= value <= 31")
+ value.asInstanceOf[Day]
+ }
+
+ def unapply(dayString: String): Option[Int] = {
+ require(dayString.length === 2, s"ISO 8601 day string, DD, must have length 2: $dayString")
+ Try(dayString.toInt).toOption.map(apply)
+ }
+ }
+
type Month = Int @@ Month.type
- private[core] def tagMonth(value: Int): Month = value.asInstanceOf[Month]
object Month {
- val JANUARY = tagMonth(Calendar.JANUARY)
- val FEBRUARY = tagMonth(Calendar.FEBRUARY)
- val MARCH = tagMonth(Calendar.MARCH)
- val APRIL = tagMonth(Calendar.APRIL)
- val MAY = tagMonth(Calendar.MAY)
- val JUNE = tagMonth(Calendar.JUNE)
- val JULY = tagMonth(Calendar.JULY)
- val AUGUST = tagMonth(Calendar.AUGUST)
- val SEPTEMBER = tagMonth(Calendar.SEPTEMBER)
- val OCTOBER = tagMonth(Calendar.OCTOBER)
- val NOVEMBER = tagMonth(Calendar.NOVEMBER)
- val DECEMBER = tagMonth(Calendar.DECEMBER)
+ def apply(value: Int): Month = {
+ require(0 to 11 contains value, "Month is zero-indexed: 0 <= value <= 11")
+ value.asInstanceOf[Month]
+ }
+ val JANUARY = Month(Calendar.JANUARY)
+ val FEBRUARY = Month(Calendar.FEBRUARY)
+ val MARCH = Month(Calendar.MARCH)
+ val APRIL = Month(Calendar.APRIL)
+ val MAY = Month(Calendar.MAY)
+ val JUNE = Month(Calendar.JUNE)
+ val JULY = Month(Calendar.JULY)
+ val AUGUST = Month(Calendar.AUGUST)
+ val SEPTEMBER = Month(Calendar.SEPTEMBER)
+ val OCTOBER = Month(Calendar.OCTOBER)
+ val NOVEMBER = Month(Calendar.NOVEMBER)
+ val DECEMBER = Month(Calendar.DECEMBER)
+
+ def unapply(monthString: String): Option[Month] = {
+ require(monthString.length === 2, s"ISO 8601 month string, MM, must have length 2: $monthString")
+ Try(monthString.toInt).toOption.map(isoM => apply(isoM - 1))
+ }
+ }
+
+ type Year = Int @@ Year.type
+
+ object Year {
+ def apply(value: Int): Year = value.asInstanceOf[Year]
+
+ def unapply(yearString: String): Option[Int] = {
+ require(yearString.length === 4, s"ISO 8601 year string, YYYY, must have length 4: $yearString")
+ Try(yearString.toInt).toOption.map(apply)
+ }
}
final case class Date(year: Int, month: Month, day: Int) {
@@ -38,9 +81,9 @@ object date {
}
def fromString(dateString: String): Option[Date] = {
- util.Try(dateString.split("-").map(_.toInt)).toOption collect {
- case Array(year, month, day) if (1 to 12 contains month) && (1 to 31 contains day) =>
- Date(year, tagMonth(month - 1), day)
+ dateString.split('-') match {
+ case Array(Year(year), Month(month), Day(day)) => Some(Date(year, month, day))
+ case _ => None
}
}
}
diff --git a/src/main/scala/xyz/driver/core/json.scala b/src/main/scala/xyz/driver/core/json.scala
index 01efd57..457a087 100644
--- a/src/main/scala/xyz/driver/core/json.scala
+++ b/src/main/scala/xyz/driver/core/json.scala
@@ -7,7 +7,7 @@ import akka.http.scaladsl.unmarshalling.Unmarshaller
import spray.json.{DeserializationException, JsNumber, _}
import xyz.driver.core.auth.AuthCredentials
import xyz.driver.core.time.Time
-import xyz.driver.core.date.Date
+import xyz.driver.core.date.{Date, Month}
import xyz.driver.core.domain.{Email, PhoneNumber}
import scala.reflect.runtime.universe._
@@ -81,6 +81,14 @@ object json {
}
}
+ implicit val monthFormat = new RootJsonFormat[Month] {
+ def write(month: Month) = JsNumber(month)
+ def read(value: JsValue): Month = value match {
+ case JsNumber(month) if 0 <= month && month <= 11 => Month(month.toInt)
+ case _ => throw DeserializationException("Expected a number from 0 to 11")
+ }
+ }
+
def RevisionInPath[T]: PathMatcher1[Revision[T]] =
PathMatcher("""[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}""".r) flatMap { string =>
Some(Revision[T](string))
diff --git a/src/main/scala/xyz/driver/core/time.scala b/src/main/scala/xyz/driver/core/time.scala
index cbb86ed..ed5eb11 100644
--- a/src/main/scala/xyz/driver/core/time.scala
+++ b/src/main/scala/xyz/driver/core/time.scala
@@ -30,7 +30,7 @@ object time {
def toDate(timezone: TimeZone): date.Date = {
val cal = Calendar.getInstance(timezone)
cal.setTimeInMillis(millis)
- date.Date(cal.get(Calendar.YEAR), date.tagMonth(cal.get(Calendar.MONTH)), cal.get(Calendar.DAY_OF_MONTH))
+ date.Date(cal.get(Calendar.YEAR), date.Month(cal.get(Calendar.MONTH)), cal.get(Calendar.DAY_OF_MONTH))
}
}
diff --git a/src/test/scala/xyz/driver/core/DateTest.scala b/src/test/scala/xyz/driver/core/DateTest.scala
index dc9bca3..c1185cd 100644
--- a/src/test/scala/xyz/driver/core/DateTest.scala
+++ b/src/test/scala/xyz/driver/core/DateTest.scala
@@ -10,7 +10,7 @@ class DateTest extends FlatSpec with Matchers with Checkers {
year <- Gen.choose(0, 3000)
month <- Gen.choose(0, 11)
day <- Gen.choose(1, 31)
- } yield Date(year, date.tagMonth(month), day)
+ } yield Date(year, date.Month(month), day)
implicit val arbitraryDate = Arbitrary[Date](dateGenerator)
"Date" should "correctly convert to and from String" in {