diff options
author | Jakob Odersky <jakob@driver.xyz> | 2018-09-12 15:56:41 -0700 |
---|---|---|
committer | Jakob Odersky <jakob@odersky.com> | 2018-10-09 16:19:39 -0700 |
commit | 7a793ffa068fda8f2146f84fa785328d928dba03 (patch) | |
tree | d489b0b9ebf30ca61e2b6ef1c9906b704bc1fa1e /core-types/src/main/scala/xyz/driver/core/date.scala | |
parent | 2cef01adfe3ebd3a0fa1e0bbbba7f6388198ba10 (diff) | |
download | driver-core-7a793ffa068fda8f2146f84fa785328d928dba03.tar.gz driver-core-7a793ffa068fda8f2146f84fa785328d928dba03.tar.bz2 driver-core-7a793ffa068fda8f2146f84fa785328d928dba03.zip |
Move core types into core-types project
Note that xyz.driver.core.FutureExtensions was moved to
xyz.driver.core.rest as it (only) contained logic that dealt with
service exceptions, something that belongs into core-rest and must not
be depended upon by core-types.
This is a breaking change.
Diffstat (limited to 'core-types/src/main/scala/xyz/driver/core/date.scala')
-rw-r--r-- | core-types/src/main/scala/xyz/driver/core/date.scala | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/core-types/src/main/scala/xyz/driver/core/date.scala b/core-types/src/main/scala/xyz/driver/core/date.scala new file mode 100644 index 0000000..5454093 --- /dev/null +++ b/core-types/src/main/scala/xyz/driver/core/date.scala @@ -0,0 +1,109 @@ +package xyz.driver.core + +import java.util.Calendar + +import enumeratum._ +import scalaz.std.anyVal._ +import scalaz.syntax.equal._ + +import scala.collection.immutable.IndexedSeq +import scala.util.Try + +/** + * 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 { + + sealed trait DayOfWeek extends EnumEntry + object DayOfWeek extends Enum[DayOfWeek] { + case object Monday extends DayOfWeek + case object Tuesday extends DayOfWeek + case object Wednesday extends DayOfWeek + case object Thursday extends DayOfWeek + case object Friday extends DayOfWeek + case object Saturday extends DayOfWeek + case object Sunday extends DayOfWeek + + val values: IndexedSeq[DayOfWeek] = findValues + + val All: Set[DayOfWeek] = values.toSet + + def fromString(day: String): Option[DayOfWeek] = withNameInsensitiveOption(day) + } + + 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 + + object Month { + 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) { + override def toString = f"$year%04d-${month + 1}%02d-$day%02d" + } + + object Date { + implicit def dateOrdering: Ordering[Date] = Ordering.fromLessThan { (date1, date2) => + if (date1.year != date2.year) { + date1.year < date2.year + } else if (date1.month != date2.month) { + date1.month < date2.month + } else { + date1.day < date2.day + } + } + + def fromString(dateString: String): Option[Date] = { + dateString.split('-') match { + case Array(Year(year), Month(month), Day(day)) => Some(Date(year, month, day)) + case _ => None + } + } + } +} |