title: Have an SQLAlchemy + SQLite "create_function" issue with datetime representations
body: <p>We have sqlite databases, and datetimes are actually stored in Excel format (there is a decent reason for this; it's our system's standard representation of choice, and the sqlite databases may be accessed by multiple languages/systems)</p>
  
  <p>Have been introducing Python into the mix with great success in recent months, and SQLAlchemy is a part of that. The ability of the sqlite3 dbapi layer to swiftly bind custom Python functions where SQLite lacks a given SQL function is particularly appreciated.</p>
  
  <p>I wrote an ExcelDateTime type decorator, and that works fine when retrieving result sets from the sqlite databases; Python gets proper datetimes back.</p>
  
  <p>However, I'm having a real problem binding custom python functions that expect input params to be python datetimes; I'd have thought this was what the bindparam was for, but I'm obviously missing something, as I cannot get this scenario to work. Unfortunately, modifying the functions to convert from excel datetimes to python datetimes is not an option, and neither is changing the representation of the datetimes in the database, as more than one system/language may access it.</p>
  
  <p>The code below is a self-contained example that can be run "as-is", and is representative of the issue. The custom function "get_month" is created, but fails because it receives the raw data, not the type-converted data from the "Born" column. At the end you can see what I've tried so far, and the errors it spits out...</p>
  
  <p>Is what I'm trying to do impossible? Or is there a different way of ensuring the bound function receives the appropriate python type? It's the only problem I've been unable to overcome so far, would be great to find a solution!</p>
  
  <pre><code>import sqlalchemy.types as types
  from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData
  from sqlalchemy.sql.expression import bindparam
  from sqlalchemy.sql import select, text
  from sqlalchemy.interfaces import PoolListener
  import datetime
  
  # setup type decorator for excel&lt;-&gt;python date conversions
  class ExcelDateTime( types.TypeDecorator ):
      impl = types.FLOAT
  
      def process_result_value( self, value, dialect ):
          lxdays = int( value )
          lxsecs = int( round((value-lxdays) * 86400.0) )
          if lxsecs == 86400:
              lxsecs = 0
              lxdays += 1
          return ( datetime.datetime.fromordinal(lxdays+693594)
                 + datetime.timedelta(seconds=lxsecs) )
  
      def process_bind_param( self, value, dialect ):
          if( value &lt; 200000 ): # already excel float?
              return value
          elif( isinstance(value,datetime.date) ):
              return value.toordinal() - 693594.0
          elif( isinstance(value,datetime.datetime) ):
              date_part = value.toordinal() - 693594.0
              time_part = ((value.hour*3600) + (value.minute*60) + value.second) / 86400.0
              return date_part + time_part  # time part = day fraction
  
  # create sqlite memory db via sqlalchemy
  def get_month( dt ):
      return dt.month
  
  class ConnectionFactory( PoolListener ):
      def connect( self, dbapi_con, con_record ):
          dbapi_con.create_function( 'GET_MONTH',1,get_month )
  
  eng = create_engine('sqlite:///:memory:',listeners=[ConnectionFactory()])
  eng.dialect.dbapi.enable_callback_tracebacks( 1 ) # show better errors from user functions
  meta = MetaData()
  birthdays = Table('Birthdays', meta, Column('Name',String,primary_key=True), Column('Born',ExcelDateTime), Column('BirthMonth',Integer))
  meta.create_all(eng)
  dbconn = eng.connect()
  dbconn.execute( "INSERT INTO Birthdays VALUES('Jimi Hendrix',15672,NULL)" )
  
  # demonstrate the type decorator works and we get proper datetimes out
  res = dbconn.execute( select([birthdays]) )
  tuple(res)
  # &gt;&gt;&gt; ((u'Jimi Hendrix', datetime.datetime(1942, 11, 27, 0, 0)),)
  
  # simple attempt (blows up with "AttributeError: 'float' object has no attribute 'month'")
  dbconn.execute( text("UPDATE Birthdays SET BirthMonth = GET_MONTH(Born)") )
  
  # more involved attempt( blows up with "InterfaceError: (InterfaceError) Error binding parameter 0 - probably unsupported type")
  dbconn.execute( text( "UPDATE Birthdays SET BirthMonth = GET_MONTH(:Born)",
                         bindparams=[bindparam('Born',ExcelDateTime)],
                         typemap={'Born':ExcelDateTime} ),
                  Born=birthdays.c.Born )
  </code></pre>
  
  <p>Many thanks.</p>