github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/date_format_test.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package function 16 17 import ( 18 "fmt" 19 "testing" 20 "time" 21 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 25 "github.com/dolthub/go-mysql-server/sql/expression" 26 "github.com/dolthub/go-mysql-server/sql/types" 27 ) 28 29 func TestDateFormatting(t *testing.T) { 30 dt := time.Date(2020, 2, 3, 4, 5, 6, 7000, time.UTC) 31 tests := []struct { 32 formatStr string 33 expected string 34 expectErr bool 35 }{ 36 {"%a", "Mon", false}, // Abbreviated weekday name (Sun to Sat) 37 {"%b", "Feb", false}, // Abbreviated month name (Jan to Dec) 38 {"%c", "2", false}, // Numeric month name (0 to 12) 39 {"%D", "3rd", false}, // Day of the month as a numeric value, followed by suffix (1st, 2nd, 3rd, ...) 40 {"%d", "03", false}, // Day of the month as a numeric value (00 to 31) 41 {"%e", "3", false}, // Day of the month as a numeric value (0 to 31) 42 {"%f", "000007", false}, // Microseconds (000000 to 999999) 43 {"%H", "04", false}, // Hour (00 to 23) 44 {"%h", "04", false}, // Hour (00 to 12) 45 {"%I", "04", false}, // Hour (00 to 12) 46 {"%i", "05", false}, // Minutes (00 to 59) 47 {"%j", "034", false}, // Day of the year (001 to 366) 48 {"%k", "4", false}, // Hour (0 to 23) 49 {"%l", "4", false}, // Hour (1 to 12) 50 {"%M", "February", false}, // Month name in full (January to December) 51 {"%m", "02", false}, // Month name as a numeric value (00 to 12) 52 {"%p", "AM", false}, // AM or PM 53 {"%r", "04:05:06 AM", false}, // Time in 12 hour AM or PM format (hh:mm:ss AM/PM) 54 {"%S", "06", false}, // Seconds (00 to 59) 55 {"%s", "06", false}, // Seconds (00 to 59) 56 {"%T", "04:05:06", false}, // Time in 24 hour format (hh:mm:ss) 57 {"%W", "Monday", false}, // Weekday name in full (Sunday to Saturday) 58 {"%w", "1", false}, // Day of the week where Sunday=0 and Saturday=6 59 {"%Y", "2020", false}, // Year as a numeric, 4-digit value 60 {"%y", "20", false}, // Year as a numeric, 2-digit value 61 {"%U", "05", false}, // Week where Sunday is the first day of the week (00 to 53) 62 {"%u", "06", false}, // Week where Monday is the first day of the week (00 to 53) 63 {"%V", "05", false}, // Week where Sunday is the first day of the week (01 to 53). Used with %X 64 {"%v", "06", false}, // Week where Monday is the first day of the week (01 to 53). Used with %X 65 {"%X", "2020", false}, // Year for the week where Sunday is the first day of the week. Used with %V 66 {"%x", "2020", false}, // Year for the week where Monday is the first day of the week. Used with %V 67 } 68 69 for _, test := range tests { 70 t.Run(dt.String()+test.formatStr, func(t *testing.T) { 71 result, err := formatDate(test.formatStr, dt) 72 73 if test.expectErr { 74 assert.Error(t, err) 75 } else { 76 assert.NoError(t, err) 77 t.Log(result) 78 assert.Equal(t, test.expected, result) 79 } 80 }) 81 } 82 } 83 84 func TestUnsupportedSpecifiers(t *testing.T) { 85 testFunc := func(t *testing.T, b byte) { 86 if _, ok := dateFormatSpecifierToFunc[b]; !ok { 87 name := fmt.Sprintf("%%%s", string(b)) 88 t.Run(name, func(t *testing.T) { 89 result, err := formatDate(name, time.Now()) 90 assert.NoError(t, err) 91 assert.Equal(t, string(b), result) 92 }) 93 } 94 } 95 96 capToLower := byte('a' - 'A') 97 for i := byte('A'); i <= 'Z'; i++ { 98 testFunc(t, i) 99 testFunc(t, i+capToLower) 100 } 101 } 102 103 func TestWeekYearFormatting(t *testing.T) { 104 weekYearStartingMonday := "%x-W%v" 105 weekYearStartingSunday := "%X-W%V" 106 weekStartingMonday := "%u" 107 weekStartingSunday := "%U" 108 tests := []struct { 109 name string 110 dateStr string 111 expectedWYForMonStart string 112 expectedWYForSunStart string 113 expectedWForMonStart string 114 expectedWForSunStart string 115 }{ 116 {"Sat 1 Jan 2005", "2005-01-01", "2004-W53", "2004-W52", "00", "00"}, 117 {"Sun 2 Jan 2005", "2005-01-02", "2004-W53", "2005-W01", "00", "01"}, 118 {"Sat 31 Dec 2005", "2005-12-31", "2005-W52", "2005-W52", "52", "52"}, 119 {"Sun 1 Jan 2006", "2006-01-01", "2005-W52", "2006-W01", "00", "01"}, 120 {"Mon 2 Jan 2006", "2006-01-02", "2006-W01", "2006-W01", "01", "01"}, 121 {"Sun 31 Dec 2006", "2006-12-31", "2006-W52", "2006-W53", "52", "53"}, 122 {"Mon 1 Jan 2007", "2007-01-01", "2007-W01", "2006-W53", "01", "00"}, 123 {"Sun 30 Dec 2007", "2007-12-30", "2007-W52", "2007-W52", "52", "52"}, 124 {"Mon 31 Dec 2007", "2007-12-31", "2008-W01", "2007-W52", "53", "52"}, 125 {"Tue 1 Jan 2008", "2008-01-01", "2008-W01", "2007-W52", "01", "00"}, 126 {"Sun 28 Dec 2008", "2008-12-28", "2008-W52", "2008-W52", "52", "52"}, 127 {"Mon 29 Dec 2008", "2008-12-29", "2009-W01", "2008-W52", "53", "52"}, 128 {"Tue 30 Dec 2008", "2008-12-30", "2009-W01", "2008-W52", "53", "52"}, 129 {"Wed 31 Dec 2008", "2008-12-31", "2009-W01", "2008-W52", "53", "52"}, 130 {"Thu 1 Jan 2009", "2009-01-01", "2009-W01", "2008-W52", "01", "00"}, 131 {"Thu 31 Dec 2009", "2009-12-31", "2009-W53", "2009-W52", "53", "52"}, 132 {"Fri 1 Jan 2010", "2010-01-01", "2009-W53", "2009-W52", "00", "00"}, 133 {"Sat 2 Jan 2010", "2010-01-02", "2009-W53", "2009-W52", "00", "00"}, 134 {"Sun 3 Jan 2010", "2010-01-03", "2009-W53", "2010-W01", "00", "01"}, 135 } 136 137 for _, test := range tests { 138 t.Run(test.name, func(t *testing.T) { 139 dt, err := time.Parse("2006-01-02", test.dateStr) 140 require.NoError(t, err) 141 142 mondayWYStartResult, err := formatDate(weekYearStartingMonday, dt) 143 assert.NoError(t, err) 144 assert.Equal(t, test.expectedWYForMonStart, mondayWYStartResult) 145 146 sundayWYStartResult, err := formatDate(weekYearStartingSunday, dt) 147 assert.NoError(t, err) 148 assert.Equal(t, test.expectedWYForSunStart, sundayWYStartResult) 149 150 mondayWStartResult, err := formatDate(weekStartingMonday, dt) 151 assert.NoError(t, err) 152 assert.Equal(t, test.expectedWForMonStart, mondayWStartResult) 153 154 sundayWStartResult, err := formatDate(weekStartingSunday, dt) 155 assert.NoError(t, err) 156 assert.Equal(t, test.expectedWForSunStart, sundayWStartResult) 157 }) 158 } 159 } 160 161 func TestDateFormatEval(t *testing.T) { 162 dt := time.Date(2020, 2, 3, 4, 5, 6, 7000, time.UTC) 163 dateLit := expression.NewLiteral(dt, types.DatetimeMaxPrecision) 164 format := expression.NewLiteral("%Y-%m-%d %H:%i:%s.%f", types.Text) 165 nullLiteral := expression.NewLiteral(nil, types.Null) 166 167 dateFormat := NewDateFormat(dateLit, format) 168 res, err := dateFormat.Eval(nil, nil) 169 assert.NoError(t, err) 170 assert.Equal(t, "2020-02-03 04:05:06.000007", res) 171 172 dateFormat = NewDateFormat(dateLit, nil) 173 res, err = dateFormat.Eval(nil, nil) 174 assert.NoError(t, err) 175 assert.Nil(t, res) 176 177 dateFormat = NewDateFormat(nil, format) 178 res, err = dateFormat.Eval(nil, nil) 179 assert.NoError(t, err) 180 assert.Nil(t, res) 181 182 dateFormat = NewDateFormat(dateLit, nullLiteral) 183 res, err = dateFormat.Eval(nil, nil) 184 assert.NoError(t, err) 185 assert.Nil(t, res) 186 187 dateFormat = NewDateFormat(nullLiteral, format) 188 res, err = dateFormat.Eval(nil, nil) 189 assert.NoError(t, err) 190 assert.Nil(t, res) 191 }