The LookEver since Martin Odersky gave us Generics in Java 5, we've become comfortable with reading parameterized types like Set<String> ("Set of String") for container classes. Unsurprisingly, with the move to Odersky's Scala has come further use of parameterization; for example Try[Double] and Future[User]. Essentially, I wanted a type that looked like this. Hence:
val pierreTime: TimeInZone[Paris] val johnTime: TimeInZone[Melbourne] val canonicalTime: TimeInZone[UTC]
BehaviourI want wrong code to look wrong but more than that, I want the compiler to consider it wrong too:
val pierreTime: TimeInZone[Paris] def doSomethingInMelbourne(mTime: TimeInZone[Melbourne]) ... // later... doSomethingInMelbourne(pierreTime) ^ [error] type mismatch; [error] found : TimeInZone[Paris] [error] required: TimeInZone[Melbourne]
Functional FamiliarityI'm only a tiny way down the path to true functional-programming enlightenment. Hell, I've only just started looking at Scalaz, mainly thanks to eed3si9n's excellent tutorials.
But the following patterns seem pretty sensible to me:
map from one timezone to anotherThe instant-in-time is unchanged, but the type changes, and the local time changes too:
val pierreTime: TimeInZone[Paris] // Local: 2015-04-29T09:15:49.739+02:00 // Millis (UTC): 1430291749739 val johnTime: TimeInZone[Melbourne] = pierreTime.map[Melbourne] // Local: 2015-04-29T17:15:49.739+10:00 // Millis (UTC): 1430291749739
transform the time inside the containerI can make adjustments* to the DateTime contained within the TimeInZone[T] using any Joda-Time method that returns another DateTime:
val pierreTime: TimeInZone[Paris] // Local: 2015-04-29T09:15:49.739+02:00 val pierreWakeUpTime: TimeInZone[Paris] = pierreTime.transform(_.withTime(7,0,0,0)) // Local: 2015-04-29T07:00:00.000+02:00 val pierreLunchTime: TimeInZone[Paris] = pierreTime.transform(_.plusHours(4)) // Local: 2015-04-29T13:15:49.739+02:00
(*) Everything is immutable (including within Joda-Time) so "adjustments" naturally result in a new object being returned. Do we have a word yet for "A modified copy of an immutable thing"?
Companion-object for constructionI should be able to get a TimeInZone[T] via its companion object for every conceivable scenario:
// "Now" in whatever TZ my JVM is running in: val myLocalTime: TimeInZone[TimeZone] = TimeInZone.now // -> TimeInZone[Melbourne] UTC: '2015-04-28T12:37:00.000Z' // "Now" in the given TZ: val myParisTime: TimeInZone[TimeZone] = TimeInZone.now("Europe/Paris") // -> TimeInZone[Paris] UTC: '2015-04-28T12:37:23.000Z' // "Now" in UTC: val myUTCTime: TimeInZone[UTC] = TimeInZone.nowUTC // -> TimeInZone[UTC] UTC: '2015-04-28T12:37:28.000Z' // If I pass millis, UTC is implied: val myUTCTime: TimeInZone[UTC] = TimeInZone.fromUTCMillis(1430703466430) // -> TimeInZone[UTC] UTC: '2015-05-04T01:37:46.430Z // Reflective methods where the desired [TimeZone] affects the result: // Give me "now" on the West Coast: val paloAlto = TimeInZone[PST] // -> TimeInZone[PST] UTC: '2015-05-04T01:37:56.430Z // Give me "then" on the West Coast: val paloAltoLastWeek = TimeInZone[PST](new DateTime().minusDays(7)) // -> TimeInZone[PST] UTC: '2015-04-28T01:37:59.430Z