github.com/dolthub/go-mysql-server@v0.18.0/sql/planbuilder/dateparse/date_test.go (about) 1 package dateparse 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/require" 9 ) 10 11 func TestParseDate(t *testing.T) { 12 setupTimezone(t) 13 14 tests := [...]struct { 15 name string 16 date string 17 format string 18 expected string 19 }{ 20 {"simple", "Jan 3, 2000", "%b %e, %Y", "2000-01-03"}, 21 {"simple_with_spaces", "Nov 03 , 2000", "%b %e, %Y", "2000-11-03"}, 22 {"simple_with_spaces_2", "Dec 15 , 2000", "%b %e, %Y", "2000-12-15"}, 23 {"reverse", "2023/Feb/ 1", "%Y/%b/%e", "2023-02-01"}, 24 {"reverse_with_spaces", " 2023 /Apr/ 01 ", "%Y/%b/%e", "2023-04-01"}, 25 {"weekday", "Thu, Aug 5, 2021", "%a, %b %e, %Y", "2021-08-05"}, 26 {"weekday", "Fri, Aug 6, 2021", "%a, %b %e, %Y", "2021-08-06"}, 27 {"weekday", "Sat, Aug 7, 2021", "%a, %b %e, %Y", "2021-08-07"}, 28 {"weekday", "Sun, Aug 8, 2021", "%a, %b %e, %Y", "2021-08-08"}, 29 {"weekday", "Mon, Aug 9, 2021", "%a, %b %e, %Y", "2021-08-09"}, 30 {"weekday", "Tue, Aug 10, 2021", "%a, %b %e, %Y", "2021-08-10"}, 31 {"weekday", "Wed, Aug 11, 2021", "%a, %b %e, %Y", "2021-08-11"}, 32 33 {"time_only", "22:23:00", "%H:%i:%s", "22:23:00"}, 34 {"with_time", "Sep 3, 22:23:00 2000", "%b %e, %H:%i:%s %Y", "2000-09-03 22:23:00"}, 35 {"with_pm", "May 3, 10:23:00 PM 2000", "%b %e, %h:%i:%s %p %Y", "2000-05-03 22:23:00"}, 36 {"lowercase_pm", "Jul 3, 10:23:00 pm 2000", "%b %e, %h:%i:%s %p %Y", "2000-07-03 22:23:00"}, 37 {"with_am", "Mar 3, 10:23:00 am 2000", "%b %e, %h:%i:%s %p %Y", "2000-03-03 10:23:00"}, 38 39 {"month_number", "1 3, 10:23:00 pm 2000", "%c %e, %h:%i:%s %p %Y", "2000-01-03 22:23:00"}, 40 41 {"day_with_suffix", "Jun 3rd, 10:23:00 pm 2000", "%b %D, %h:%i:%s %p %Y", "2000-06-03 22:23:00"}, 42 {"day_with_suffix_2", "Oct 21st, 10:23:00 pm 2000", "%b %D, %h:%i:%s %p %Y", "2000-10-21 22:23:00"}, 43 {"with_timestamp", "01/02/2003, 12:13:14", "%c/%d/%Y, %T", "2003-01-02 12:13:14"}, 44 45 {"month_number", "03: 3, 20", "%m: %e, %y", "2020-03-03"}, 46 {"month_name", "march: 3, 20", "%M: %e, %y", "2020-03-03"}, 47 {"two_digit_date", "january: 3, 20", "%M: %e, %y", "2020-01-03"}, 48 {"two_digit_date_2000", "september: 3, 70", "%M: %e, %y", "1970-09-03"}, 49 {"two_digit_date_1900", "may: 3, 69", "%M: %e, %y", "2069-05-03"}, 50 51 {"microseconds", "01/02/99 314", "%m/%e/%y %f", "1999-01-02 00:00:00.314000"}, 52 {"hour_number", "01/02/99 5:14", "%m/%e/%y %h:%i", "1999-01-02 05:14:00"}, 53 {"hour_number_2", "01/02/99 5:14", "%m/%e/%y %I:%i", "1999-01-02 05:14:00"}, 54 55 {"timestamp", "01/02/99 05:14:12 PM", "%m/%e/%y %r", "1999-01-02 17:14:12"}, 56 {"date_with_seconds", "01/02/99 57", "%m/%e/%y %S", "1999-01-02 00:00:57"}, 57 58 {"date_by_year_offset", "100 20", "%j %y", "2020-04-09"}, 59 {"date_by_year_offset_singledigit_year", "100 5", "%j %y", "2005-04-10"}, 60 } 61 62 for _, tt := range tests { 63 t.Run(tt.name, func(t *testing.T) { 64 actual, err := ParseDateWithFormat(tt.date, tt.format) 65 require.NoError(t, err) 66 require.Equal(t, tt.expected, actual) 67 }) 68 } 69 } 70 71 func setupTimezone(t *testing.T) { 72 loc, err := time.LoadLocation("America/Chicago") 73 if err != nil { 74 t.Fatal(err) 75 } 76 old := time.Local 77 time.Local = loc 78 t.Cleanup(func() { time.Local = old }) 79 } 80 81 func TestConversionFailure(t *testing.T) { 82 tests := [...]struct { 83 name string 84 date string 85 format string 86 result interface{} 87 expectedError string 88 }{ 89 // with strict mode with NO_ZERO_IN_DATE,NO_ZERO_DATE enabled, these tests result NULL 90 {"no_year", "Jan 3", "%b %e", "0000-01-03", ""}, 91 {"no_day", "Jan 2000", "%b %y", "2020-01-00", ""}, 92 {"day_of_month_and_day_of_year", "Jan 3, 100 2000", "%b %e, %j %y", "2020-04-09", ""}, 93 94 {"24hour_time_with_pm", "May 3, 10:23:00 PM 2000", "%b %e, %H:%i:%s %p %Y", nil, "cannot use 24 hour time (H) with AM/PM (p)"}, 95 {"specifier_end_of_line", "Jan 3", "%b %e %", nil, `"%" found at end of format string`}, 96 {"unknown_format_specifier", "Jan 3", "%b %e %L", nil, `unknown format specifier "L"`}, 97 {"invalid_number_hour", "0021:12:14", "%T", nil, `specifier %T failed to parse "0021:12:14": expected literal ":", got "2"`}, 98 {"invalid_number_hour_2", "0012:12:14", "%r", nil, `specifier %r failed to parse "0012:12:14": expected literal ":", got "1"`}, 99 } 100 101 for _, tt := range tests { 102 t.Run(tt.name, func(t *testing.T) { 103 r, err := ParseDateWithFormat(tt.date, tt.format) 104 if tt.expectedError != "" { 105 require.Error(t, err) 106 require.Equal(t, tt.expectedError, err.Error()) 107 } else { 108 require.Equal(t, tt.result, r) 109 } 110 }) 111 } 112 } 113 114 func TestParseErr(t *testing.T) { 115 tests := [...]struct { 116 name string 117 date string 118 format string 119 expectedError interface{} 120 }{ 121 {"simple", "a", "b", ParseLiteralErr{ 122 Literal: 'b', Tokens: "a", err: fmt.Errorf(`expected literal "b", got "a"`)}, 123 }, 124 {"bad_numeral", "abc", "%e", ParseSpecifierErr{ 125 Specifier: 'e', Tokens: "abc", err: fmt.Errorf("strconv.ParseUint: parsing \"\": invalid syntax")}, 126 }, 127 {"bad_month", "1 Jen, 2000", "%e %b, %Y", ParseSpecifierErr{ 128 Specifier: 'b', Tokens: "jen, 2000", err: fmt.Errorf(`invalid month abbreviation "jen"`)}, 129 }, 130 {"bad_weekday", "Ten 1 Jan, 2000", "%a %e %b, %Y", ParseSpecifierErr{ 131 Specifier: 'a', Tokens: "ten 1 jan, 2000", err: fmt.Errorf(`invalid week abbreviation "ten"`)}, 132 }, 133 } 134 135 for _, tt := range tests { 136 t.Run(tt.name, func(t *testing.T) { 137 _, err := ParseDateWithFormat(tt.date, tt.format) 138 require.Error(t, err) 139 require.Equal(t, tt.expectedError.(error).Error(), err.Error()) 140 require.IsType(t, err, tt.expectedError) 141 }) 142 } 143 }