github.com/vedadiyan/sqlparser@v1.0.0/pkg/sqlparser/parse_date.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package sqlparser 18 19 import ( 20 "fmt" 21 "strconv" 22 "strings" 23 "time" 24 25 "github.com/vedadiyan/sqlparser/pkg/vterrors" 26 vtrpcpb "github.com/vedadiyan/sqlparser/pkg/vtrpc" 27 ) 28 29 var dateFormats = []string{"2006-01-02", "06-01-02", "20060102", "060102"} 30 var datetimeFormats = []string{"2006-01-02 15:04:05.9", "06-01-02 15:04:05.9", "20060102150405.9", "060102150405.9"} 31 var timeWithDayFormats = []string{"15:04:05.9", "15:04", "15"} 32 var timeWithoutDayFormats = []string{"15:04:05.9", "15:04", "150405.9", "0405", "05"} 33 34 func ParseDate(in string) (t time.Time, err error) { 35 for _, f := range dateFormats { 36 t, err = time.Parse(f, in) 37 if err == nil { 38 return t, nil 39 } 40 } 41 return t, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongValue, "incorrect DATE value: '%s'", in) 42 } 43 44 func ParseTime(in string) (t time.Time, err error) { 45 // ParseTime is right now only excepting on specific 46 // time format and doesn't accept all formats MySQL accepts. 47 // Can be improved in the future as needed. 48 if in == "" { 49 return t, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongValue, "incorrect TIME value: '%s'", in) 50 } 51 start := 0 52 neg := in[start] == '-' 53 if neg { 54 start++ 55 } 56 57 parts := strings.Split(in[start:], " ") 58 if len(parts) > 2 { 59 return t, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongValue, "incorrect TIME value: '%s'", in) 60 } 61 days := 0 62 hourMinuteSeconds := parts[0] 63 if len(parts) == 2 { 64 days, err = strconv.Atoi(parts[0]) 65 if err != nil { 66 fmt.Printf("atoi failed: %+v\n", err) 67 return t, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongValue, "incorrect TIME value: '%s'", in) 68 } 69 if days < 0 { 70 // Double negative which is not allowed 71 return t, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongValue, "incorrect TIME value: '%s'", in) 72 } 73 if days > 34 { 74 return t, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongValue, "incorrect TIME value: '%s'", in) 75 } 76 for _, f := range timeWithDayFormats { 77 t, err = time.Parse(f, parts[1]) 78 if err == nil { 79 break 80 } 81 } 82 } else { 83 for _, f := range timeWithoutDayFormats { 84 t, err = time.Parse(f, hourMinuteSeconds) 85 if err == nil { 86 break 87 } 88 } 89 } 90 91 if err != nil { 92 return t, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongValue, "incorrect TIME value: '%s'", in) 93 } 94 95 // setting the date to today's date, because t is "0000-01-01 xx:xx:xx" 96 now := time.Now() 97 year, month, day := now.Date() 98 if neg { 99 // If we have a negative time, we start with the start of today 100 // and substract the total duration of the parsed time. 101 today := time.Date(year, month, day, 0, 0, 0, 0, t.Location()) 102 duration := time.Duration(days)*24*time.Hour + 103 time.Duration(t.Hour())*time.Hour + 104 time.Duration(t.Minute())*time.Minute + 105 time.Duration(t.Second())*time.Second + 106 time.Duration(t.Nanosecond())*time.Nanosecond 107 t = today.Add(-duration) 108 } else { 109 // In case of a positive time, we can take a quicker 110 // shortcut and add the date of today. 111 t = t.AddDate(year, int(month-1), day-1+days) 112 } 113 return t, nil 114 } 115 116 func ParseDateTime(in string) (t time.Time, err error) { 117 for _, f := range datetimeFormats { 118 t, err = time.Parse(f, in) 119 if err == nil { 120 return t, nil 121 } 122 } 123 return t, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.WrongValue, "incorrect DATETIME value: '%s'", in) 124 }