diff --git a/src/database/sql/convert.go b/src/database/sql/convert.go
index bba5a8843a0fcf9b2e6b3fc69589c58499bcedc4..740fd9d6e7c9af2a82a0f0d297e53b70d92e2d2e 100644
--- a/src/database/sql/convert.go
+++ b/src/database/sql/convert.go
@@ -12,6 +12,7 @@ import (
 	"fmt"
 	"reflect"
 	"strconv"
+	"time"
 )
 
 var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
@@ -127,6 +128,18 @@ func convertAssign(dest, src interface{}) error {
 			*d = s
 			return nil
 		}
+	case time.Time:
+		switch d := dest.(type) {
+		case *string:
+			*d = s.Format(time.RFC3339Nano)
+			return nil
+		case *[]byte:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = []byte(s.Format(time.RFC3339Nano))
+			return nil
+		}
 	case nil:
 		switch d := dest.(type) {
 		case *interface{}:
@@ -226,7 +239,8 @@ func convertAssign(dest, src interface{}) error {
 		s := asString(src)
 		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
 		if err != nil {
-			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+			err = strconvErr(err)
+			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 		}
 		dv.SetInt(i64)
 		return nil
@@ -234,7 +248,8 @@ func convertAssign(dest, src interface{}) error {
 		s := asString(src)
 		u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
 		if err != nil {
-			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+			err = strconvErr(err)
+			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 		}
 		dv.SetUint(u64)
 		return nil
@@ -242,13 +257,21 @@ func convertAssign(dest, src interface{}) error {
 		s := asString(src)
 		f64, err := strconv.ParseFloat(s, dv.Type().Bits())
 		if err != nil {
-			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+			err = strconvErr(err)
+			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 		}
 		dv.SetFloat(f64)
 		return nil
 	}
 
-	return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
+	return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
+}
+
+func strconvErr(err error) error {
+	if ne, ok := err.(*strconv.NumError); ok {
+		return ne.Err
+	}
+	return err
 }
 
 func cloneBytes(b []byte) []byte {
diff --git a/src/database/sql/convert_test.go b/src/database/sql/convert_test.go
index 1fab282b40896ab816d1ceb12a9b855d6a887a9b..342875e190c99ed12baf1e14d720e8b512e9526b 100644
--- a/src/database/sql/convert_test.go
+++ b/src/database/sql/convert_test.go
@@ -77,6 +77,14 @@ var conversionTests = []conversionTest{
 	{s: uint64(123), d: &scanstr, wantstr: "123"},
 	{s: 1.5, d: &scanstr, wantstr: "1.5"},
 
+	// From time.Time:
+	{s: time.Unix(1, 0).UTC(), d: &scanstr, wantstr: "1970-01-01T00:00:01Z"},
+	{s: time.Unix(1453874597, 0).In(time.FixedZone("here", -3600*8)), d: &scanstr, wantstr: "2016-01-26T22:03:17-08:00"},
+	{s: time.Unix(1, 2).UTC(), d: &scanstr, wantstr: "1970-01-01T00:00:01.000000002Z"},
+	{s: time.Time{}, d: &scanstr, wantstr: "0001-01-01T00:00:00Z"},
+	{s: time.Unix(1, 2).UTC(), d: &scanbytes, wantbytes: []byte("1970-01-01T00:00:01.000000002Z")},
+	{s: time.Unix(1, 2).UTC(), d: &scaniface, wantiface: time.Unix(1, 2).UTC()},
+
 	// To []byte
 	{s: nil, d: &scanbytes, wantbytes: nil},
 	{s: "string", d: &scanbytes, wantbytes: []byte("string")},
@@ -104,10 +112,16 @@ var conversionTests = []conversionTest{
 
 	// Strings to integers
 	{s: "255", d: &scanuint8, wantuint: 255},
-	{s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
+	{s: "256", d: &scanuint8, wanterr: "converting driver.Value type string (\"256\") to a uint8: value out of range"},
 	{s: "256", d: &scanuint16, wantuint: 256},
 	{s: "-1", d: &scanint, wantint: -1},
-	{s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`},
+	{s: "foo", d: &scanint, wanterr: "converting driver.Value type string (\"foo\") to a int: invalid syntax"},
+
+	// int64 to smaller integers
+	{s: int64(5), d: &scanuint8, wantuint: 5},
+	{s: int64(256), d: &scanuint8, wanterr: "converting driver.Value type int64 (\"256\") to a uint8: value out of range"},
+	{s: int64(256), d: &scanuint16, wantuint: 256},
+	{s: int64(65536), d: &scanuint16, wanterr: "converting driver.Value type int64 (\"65536\") to a uint16: value out of range"},
 
 	// True bools
 	{s: true, d: &scanbool, wantbool: true},
@@ -155,7 +169,10 @@ var conversionTests = []conversionTest{
 	{s: 1.5, d: new(userDefined), wantusrdef: 1.5},
 	{s: int64(123), d: new(userDefined), wantusrdef: 123},
 	{s: "1.5", d: new(userDefined), wantusrdef: 1.5},
-	{s: []byte{1, 2, 3}, d: new(userDefinedSlice), wanterr: `unsupported driver -> Scan pair: []uint8 -> *sql.userDefinedSlice`},
+	{s: []byte{1, 2, 3}, d: new(userDefinedSlice), wanterr: `unsupported Scan, storing driver.Value type []uint8 into type *sql.userDefinedSlice`},
+
+	// Other errors
+	{s: complex(1, 2), d: &scanstr, wanterr: `unsupported Scan, storing driver.Value type complex128 into type *string`},
 }
 
 func intPtrValue(intptr interface{}) interface{} {
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index b5a17f0fc1ac359146c1466851acccb12e725aa2..d8e7cb77af396e0d735ee766410adb91591b887c 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -189,8 +189,7 @@ func (n NullBool) Value() (driver.Value, error) {
 type Scanner interface {
 	// Scan assigns a value from a database driver.
 	//
-	// The src value will be of one of the following restricted
-	// set of types:
+	// The src value will be of one of the following types:
 	//
 	//    int64
 	//    float64
@@ -1786,17 +1785,56 @@ func (rs *Rows) Columns() ([]string, error) {
 }
 
 // Scan copies the columns in the current row into the values pointed
-// at by dest.
+// at by dest. The number of values in dest must be the same as the
+// number of columns in Rows.
 //
-// If an argument has type *[]byte, Scan saves in that argument a copy
-// of the corresponding data. The copy is owned by the caller and can
-// be modified and held indefinitely. The copy can be avoided by using
-// an argument of type *RawBytes instead; see the documentation for
-// RawBytes for restrictions on its use.
+// Scan converts columns read from the database into the following
+// common Go types and special types provided by the sql package:
+//
+//    *string
+//    *[]byte
+//    *int, *int8, *int16, *int32, *int64
+//    *uint, *uint8, *uint16, *uint32, *uint64
+//    *bool
+//    *float32, *float64
+//    *interface{}
+//    *RawBytes
+//    any type implementing Scanner (see Scanner docs)
+//
+// In the most simple case, if the type of the value from the source
+// column is an integer, bool or string type T and dest is of type *T,
+// Scan simply assigns the value through the pointer.
+//
+// Scan also converts between string and numeric types, as long as no
+// information would be lost. While Scan stringifies all numbers
+// scanned from numeric database columns into *string, scans into
+// numeric types are checked for overflow. For example, a float64 with
+// value 300 or a string with value "300" can scan into a uint16, but
+// not into a uint8, though float64(255) or "255" can scan into a
+// uint8. One exception is that scans of some float64 numbers to
+// strings may lose information when stringifying. In general, scan
+// floating point columns into *float64.
+//
+// If a dest argument has type *[]byte, Scan saves in that argument a
+// copy of the corresponding data. The copy is owned by the caller and
+// can be modified and held indefinitely. The copy can be avoided by
+// using an argument of type *RawBytes instead; see the documentation
+// for RawBytes for restrictions on its use.
 //
 // If an argument has type *interface{}, Scan copies the value
-// provided by the underlying driver without conversion. If the value
-// is of type []byte, a copy is made and the caller owns the result.
+// provided by the underlying driver without conversion. When scanning
+// from a source value of type []byte to *interface{}, a copy of the
+// slice is made and the caller owns the result.
+//
+// Source values of type time.Time may be scanned into values of type
+// *time.Time, *interface{}, *string, or *[]byte. When converting to
+// the latter two, time.Format3339Nano is used.
+//
+// Source values of type bool may be scanned into types *bool,
+// *interface{}, *string, *[]byte, or *RawBytes.
+//
+// For scanning into *bool, the source may be true, false, 1, 0, or
+// string inputs parseable by strconv.ParseBool.
 func (rs *Rows) Scan(dest ...interface{}) error {
 	if rs.closed {
 		return errors.New("sql: Rows are closed")
@@ -1845,8 +1883,9 @@ type Row struct {
 }
 
 // Scan copies the columns from the matched row into the values
-// pointed at by dest.  If more than one row matches the query,
-// Scan uses the first row and discards the rest.  If no row matches
+// pointed at by dest. See the documentation on Rows.Scan for details.
+// If more than one row matches the query,
+// Scan uses the first row and discards the rest. If no row matches
 // the query, Scan returns ErrNoRows.
 func (r *Row) Scan(dest ...interface{}) error {
 	if r.err != nil {