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  }