52
52
53
53
datetimeTypeMaxDate = time .Date (9999 , 12 , 31 , 0 , 0 , 0 , 0 , time .UTC )
54
54
55
+ // datetimeTypeMinDate is the minimum representable Date value, MYSQL: 1000-01-01 00:00:00.000000 (microseconds)
55
56
datetimeTypeMinDate = time .Date (1000 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC )
56
57
58
+ // The MAX and MIN are extrapolated from commit ff05628a530 in the MySQL source code from my_time.cc
59
+ // datetimeMaxTime is the maximum representable time value, MYSQL: 9999-12-31 23:59:59.999999 (microseconds)
60
+ datetimeMaxTime = time .Date (9999 , 12 , 31 , 23 , 59 , 59 , 999999000 , time .UTC )
61
+
62
+ // datetimeMinTime is the minimum representable time value, MYSQL: 0000-01-01 00:00:00.000000 (microseconds)
63
+ datetimeMinTime = time .Date (0000 , 0 , 0 , 0 , 0 , 0 , 0 , time .UTC )
64
+
57
65
DateOnlyLayouts = []string {
58
66
"20060102" ,
59
67
"2006-1-2" ,
74
82
"2006-01-02 15:04:" ,
75
83
"2006-01-02 15:04:." ,
76
84
"2006-01-02 15:04:05." ,
77
- "2006-01-02 15:04:05.999999" ,
78
- "2006-1-2 15:4:5.999999" ,
85
+ "2006-01-02 15:04:05.999999999" ,
86
+ "2006-1-2 15:4:5.999999999" ,
87
+ "2006-1-2:15:4:5.999999999" ,
79
88
"2006-01-02T15:04:05" ,
80
89
"20060102150405" ,
81
90
"2006-01-02 15:04:05.999999999 -0700 MST" , // represents standard Time.time.UTC()
@@ -202,26 +211,7 @@ func ConvertToTime(ctx context.Context, v interface{}, t datetimeType) (time.Tim
202
211
return zeroTime , nil
203
212
}
204
213
205
- // Round the date to the precision of this type
206
- truncationDuration := time .Second
207
- truncationDuration /= time .Duration (precisionConversion [t .precision ])
208
- res = res .Round (truncationDuration )
209
-
210
- switch t .baseType {
211
- case sqltypes .Date :
212
- if validated := ValidateDate (res ); validated == nil {
213
- return time.Time {}, ErrConvertingToTimeOutOfRange .New (res .Format (sql .DateLayout ), t .String ())
214
- }
215
- case sqltypes .Datetime :
216
- if validated := ValidateDatetime (res ); validated == nil {
217
- return time.Time {}, ErrConvertingToTimeOutOfRange .New (res .Format (sql .TimestampDatetimeLayout ), t .String ())
218
- }
219
- case sqltypes .Timestamp :
220
- if validated := ValidateTimestamp (res ); validated == nil {
221
- return time.Time {}, ErrConvertingToTimeOutOfRange .New (res .Format (sql .TimestampDatetimeLayout ), t .String ())
222
- }
223
- }
224
- return res , nil
214
+ return res .Round (time .Microsecond ), nil
225
215
}
226
216
227
217
// ConvertWithoutRangeCheck converts the parameter to time.Time without checking the range.
@@ -341,8 +331,8 @@ func (t datetimeType) ConvertWithoutRangeCheck(ctx context.Context, v interface{
341
331
}
342
332
343
333
func parseDatetime (value string ) (time.Time , bool ) {
344
- for _ , fmt := range TimestampDatetimeLayouts {
345
- if t , err := time .Parse (fmt , value ); err == nil {
334
+ for _ , layout := range TimestampDatetimeLayouts {
335
+ if t , err := time .Parse (layout , value ); err == nil {
346
336
return t .UTC (), true
347
337
}
348
338
}
@@ -473,9 +463,20 @@ func (t datetimeType) MinimumTime() time.Time {
473
463
return datetimeTypeMinDatetime
474
464
}
475
465
476
- // validateDatetime receives a time and returns either that time or nil if it's
466
+ // ValidateTime receives a time and returns either that time or nil if it's
477
467
// not a valid time.
468
+ func ValidateTime (t time.Time ) interface {} {
469
+ if t .Before (datetimeMinTime ) || t .After (datetimeMaxTime ) {
470
+ return nil
471
+ }
472
+
473
+ return t
474
+ }
475
+
476
+ // ValidateDatetime receives a time and returns either that time or nil if it's
477
+ // not a valid datetime.
478
478
func ValidateDatetime (t time.Time ) interface {} {
479
+ t = t .Round (time .Microsecond )
479
480
if t .Before (datetimeTypeMinDatetime ) || t .After (datetimeTypeMaxDatetime ) {
480
481
return nil
481
482
}
@@ -485,6 +486,7 @@ func ValidateDatetime(t time.Time) interface{} {
485
486
// ValidateTimestamp receives a time and returns either that time or nil if it's
486
487
// not a valid timestamp.
487
488
func ValidateTimestamp (t time.Time ) interface {} {
489
+ t = t .Round (time .Microsecond )
488
490
if t .Before (datetimeTypeMinTimestamp ) || t .After (datetimeTypeMaxTimestamp ) {
489
491
return nil
490
492
}
@@ -494,7 +496,8 @@ func ValidateTimestamp(t time.Time) interface{} {
494
496
// validateDate receives a time and returns either that time or nil if it's
495
497
// not a valid date.
496
498
func ValidateDate (t time.Time ) interface {} {
497
- if t .Before (datetimeTypeMinDatetime ) || t .After (datetimeTypeMaxDate ) {
499
+ t = t .Round (time .Microsecond )
500
+ if t .Before (datetimeTypeMinDate ) || t .After (datetimeTypeMaxDate ) {
498
501
return nil
499
502
}
500
503
return t
0 commit comments