1

I have a Play form that looks like this:

val form = Form( tuple( 
        /* 5 more fields */ 
        "dueDate" -> optional(date) 
)  )

I'm trying to insert "dueDate" into an object in Slick.

newAuditForm.bindFromRequest.fold(
    errors => BadRequest(views.html.error(form)),
    success => {
        Database.forDataSource(DB.getDataSource()) withSession {
            Things.forInsert.insert Thing(
                (success._6).asInstanceOf[Option[java.sql.Date]] 
            )
        }
    }
)

where Slick only deals with java.sql.Date, and Play only deals with java.util.Date (?) in the Form object.

Using asInstanceOf returns:

     ClassCastException: java.util.Date cannot be cast to java.sql.Date

There's got to be a way for me to write a rule for this cast to be possible ... would I need to write a new pattern matching rule?

Community
  • 1
  • 1
Meredith
  • 3,928
  • 4
  • 33
  • 58

2 Answers2

5

You cannot cast java.util.Date to java.sql.Date because java.sql.Date is a subclass. What you can do is create a new instance of java.sql.Date:

val x = new java.util.Date()
val y = new java.sql.Date(x.getTime())

You can define an implicit conversion if you consider it useful:

implicit def date2sqlDate(d: java.util.Date) = new java.sql.Date(d.getTime())

However, this will not convert inside the option (neither will the cast work, because it's not a cast but a conversion).

You can either:

val x: Option[java.util.Date]
x.map(_: java.sql.Date) // using implicit conversion

Or just write it explicitly:

x.map(d => new java.sql.Date(d.getTime()))

If you need the conversion very often, you might consider to write an implicit conversion from Option[java.util.Date] to Option[java.sql.Date].

gzm0
  • 14,752
  • 1
  • 36
  • 64
  • 2
    I don't think it is worth introducing implicit conversion if you're already doing explicit map with type ascription. – om-nom-nom Jun 21 '13 at 18:13
  • Thanks for your speedy reply. I appreciate how you went the extra length to explain what was going on. Am I right in understanding that explicit conversion is more of a one-time thing, and implicit conversions are equivalent to writing a new type-casting rule? – Meredith Jun 21 '13 at 18:30
  • 1
    @MeredithLeu Welcome. Implicit conversions are special functions used for conversion, not type casting: If you have a value `x: A` and you need a `B` and you have one implicit function `f: A => B` in scope, the compiler will replace `x` by `f(x)`. So on a bytecode-level, they are nothing more than function calls. Explicit conversion is writing the exact same function call yourself. See: http://stackoverflow.com/questions/2861501/can-someone-explain-me-implicit-conversions-in-scala – gzm0 Jun 21 '13 at 19:59
  • 1
    @om-nom-nom Yes, I agree. I added this more to show the general mechanism (and prevent confusion with the boxed type). If the conversion is required elsewhere too, it might be useful. – gzm0 Jun 21 '13 at 20:03
4

Try mapping the Option[java.util.Date] to an Option[java.sql.Date] like this:

(success._6).map(d => new java.sql.Date(d.getTime))

One more word of advice, you might want to actually map this to a java.sql.Timestamp so you don't lose any time precision when writing it to the DB as I believe will be the case with java.sql.Date. So the code would be:

(success._6).map(d => new java.sql.Timestamp(d.getTime))
cmbaxter
  • 35,283
  • 4
  • 86
  • 95
  • Thanks! I'm aware of using java.sql.Timestamp instead of Date. I use an Option[Timestamp] elsewhere in my schema, but for this particular object a granularity of day is fine ^.^ – Meredith Jun 21 '13 at 18:26