func (t datetimeType) ConvertWithoutRangeCheck(v interface{}) (time.Time, error) {
	var res time.Time
	switch value := v.(type) {
	case string:
		if value == zeroDateStr || value == zeroTimestampDatetimeStr {
			return zeroTime, nil
		}
		parsed := false
		for _, fmt := range TimestampDatetimeLayouts {
			if t, err := time.Parse(fmt, value); err == nil {
				res = t.UTC()
				parsed = true
				break
			}
		}
		if !parsed {
			return zeroTime, ErrConvertingToTime.New(v)
		}
	case time.Time:
		res = value.UTC()
	default:
		return zeroTime, ErrConvertToSQL.New(t)
	}
	if t.baseType == sqltypes.Date {
		res = res.Truncate(24 * time.Hour)
	}
	return res, nil
}
ConvertWithoutRangeCheck converts the parameter to time.Time without checking the range.
package sql
import (
	"math"
	"time"
	"github.com/dolthub/vitess/go/sqltypes"
	"github.com/dolthub/vitess/go/vt/proto/query"
	"gopkg.in/src-d/go-errors.v1"
)
const (
	DateLayout = "2006-01-02"
	TimestampDatetimeLayout = "2006-01-02 15:04:05.999999"
	zeroDateStr              = "0000-00-00"
	zeroTimestampDatetimeStr = "0000-00-00 00:00:00"
)
var (
	ErrConvertingToTime = errors.NewKind("value %q can't be converted to time.Time")
	ErrConvertingToTimeOutOfRange = errors.NewKind("value %q is outside of %v range")
	datetimeTypeMaxDatetime = time.Date(9999, 12, 31, 23, 59, 59, 999999000, time.UTC)
	datetimeTypeMinDatetime = time.Date(1000, 1, 1, 0, 0, 0, 0, time.UTC)
	datetimeTypeMaxTimestamp = time.Unix(math.MaxInt32, 999999000)
	datetimeTypeMinTimestamp = time.Unix(1, 0)
	TimestampDatetimeLayouts = []string{
		"2006-01-02 15:04:05.999999",
		"2006-01-02",
		"2006-1-2",
		"2006-1-2 15:4:5.999999",
		time.RFC3339,
		time.RFC3339Nano,
		"2006-01-02T15:04:05",
		"20060102150405",
		"20060102",
		"2006/01/02",
		"2006-01-02 15:04:05.999999999 -0700 MST",  
	}
	zeroTime = time.Unix(-62167219200, 0).UTC()
	Date = MustCreateDatetimeType(sqltypes.Date)
	Datetime = MustCreateDatetimeType(sqltypes.Datetime)
	Timestamp = MustCreateDatetimeType(sqltypes.Timestamp)
)
type DatetimeType interface {
	Type
	ConvertWithoutRangeCheck(v interface{}) (time.Time, error)
	MaximumTime() time.Time
	MinimumTime() time.Time
}
type datetimeType struct {
	baseType query.Type
}
func CreateDatetimeType(baseType query.Type) (DatetimeType, error) {
	switch baseType {
	case sqltypes.Date, sqltypes.Datetime, sqltypes.Timestamp:
		return datetimeType{
			baseType: baseType,
		}, nil
	}
	return nil, ErrInvalidBaseType.New(baseType.String(), "datetime")
}
func MustCreateDatetimeType(baseType query.Type) DatetimeType {
	dt, err := CreateDatetimeType(baseType)
	if err != nil {
		panic(err)
	}
	return dt
}
func (t datetimeType) Compare(a interface{}, b interface{}) (int, error) {
	if hasNulls, res := compareNulls(a, b); hasNulls {
		return res, nil
	}
	var at time.Time
	var bt time.Time
	var ok bool
	if at, ok = a.(time.Time); !ok {
		ai, err := t.Convert(a)
		if err != nil {
			return 0, err
		}
		at = ai.(time.Time)
	} else if t.baseType == sqltypes.Date {
		at = at.Truncate(24 * time.Hour)
	}
	if bt, ok = b.(time.Time); !ok {
		bi, err := t.Convert(b)
		if err != nil {
			return 0, err
		}
		bt = bi.(time.Time)
	} else if t.baseType == sqltypes.Date {
		bt = bt.Truncate(24 * time.Hour)
	}
	if at.Before(bt) {
		return -1, nil
	} else if at.After(bt) {
		return 1, nil
	}
	return 0, nil
}
func (t datetimeType) Convert(v interface{}) (interface{}, error) {
	if v == nil {
		return nil, nil
	}
	res, err := t.ConvertWithoutRangeCheck(v)
	if err != nil {
		return nil, err
	}
	if res.Equal(zeroTime) {
		return zeroTime, nil
	}
	switch t.baseType {
	case sqltypes.Date:
		if res.Year() < 1000 || res.Year() > 9999 {
			return nil, ErrConvertingToTimeOutOfRange.New(res.Format(DateLayout), t.String())
		}
	case sqltypes.Datetime:
		if res.Year() < 1000 || res.Year() > 9999 {
			return nil, ErrConvertingToTimeOutOfRange.New(res.Format(TimestampDatetimeLayout), t.String())
		}
	case sqltypes.Timestamp:
		if res.Before(datetimeTypeMinTimestamp) || res.After(datetimeTypeMaxTimestamp) {
			return nil, ErrConvertingToTimeOutOfRange.New(res.Format(TimestampDatetimeLayout), t.String())
		}
	}
	return res, nil
}