github.com/dolthub/go-mysql-server@v0.18.0/sql/planbuilder/dateparse/parsers.go (about)

     1  package dateparse
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  )
     7  
     8  // parser defines a function that processes a string and returns the
     9  // remaining characters unconsumed by the given parser.
    10  //
    11  // The data parsed from the consumed characters should be
    12  // written to the `datetime` struct.
    13  type parser func(result *datetime, chars string) (rest string, err error)
    14  
    15  func trimPrefix(count int, str string) string {
    16  	if len(str) > count {
    17  		return str[count:]
    18  	}
    19  	return ""
    20  }
    21  
    22  func literalParser(literal byte) parser {
    23  	return func(dt *datetime, chars string) (rest string, _ error) {
    24  		if len(chars) < 1 && literal != ' ' {
    25  			return "", fmt.Errorf("expected literal \"%c\", found empty string", literal)
    26  		}
    27  		chars = takeAllSpaces(chars)
    28  		if literal == ' ' {
    29  			return chars, nil
    30  		}
    31  		if chars[0] != literal {
    32  			return "", fmt.Errorf("expected literal \"%c\", got \"%c\"", literal, chars[0])
    33  		}
    34  		return trimPrefix(1, chars), nil
    35  	}
    36  }
    37  
    38  func parseAmPm(result *datetime, chars string) (rest string, _ error) {
    39  	if len(chars) < 2 {
    40  		return "", fmt.Errorf("expected > 2 chars, found %d", len(chars))
    41  	}
    42  	switch chars[:2] {
    43  	case "am":
    44  		result.am = boolPtr(true)
    45  	case "pm":
    46  		result.am = boolPtr(false)
    47  	default:
    48  		return "", fmt.Errorf("expected AM or PM, got \"%s\"", chars[:2])
    49  	}
    50  	return trimPrefix(2, chars), nil
    51  }
    52  
    53  func parseWeekdayAbbreviation(result *datetime, chars string) (rest string, _ error) {
    54  	if len(chars) < 3 {
    55  		return "", fmt.Errorf("expected at least 3 chars, got %d", len(chars))
    56  	}
    57  	weekday, ok := weekdayAbbrev(chars[:3])
    58  	if !ok {
    59  		return "", fmt.Errorf("invalid week abbreviation \"%s\"", chars[:3])
    60  	}
    61  	result.weekday = &weekday
    62  	return trimPrefix(3, chars), nil
    63  }
    64  
    65  func parseMonthAbbreviation(result *datetime, chars string) (rest string, _ error) {
    66  	if len(chars) < 3 {
    67  		return "", fmt.Errorf("expected at least 3 chars, got %d", len(chars))
    68  	}
    69  	month, ok := monthAbbrev(chars[:3])
    70  	if !ok {
    71  		return "", fmt.Errorf("invalid month abbreviation \"%s\"", chars[:3])
    72  	}
    73  	result.month = &month
    74  	return trimPrefix(3, chars), nil
    75  }
    76  
    77  func parseMonthNumeric(result *datetime, chars string) (rest string, _ error) {
    78  	num, rest, err := takeNumber(chars)
    79  	if err != nil {
    80  		return "", err
    81  	}
    82  	month := time.Month(num)
    83  	result.month = &month
    84  	return rest, nil
    85  }
    86  
    87  func parseDayOfMonthNumeric(result *datetime, chars string) (rest string, _ error) {
    88  	num, rest, err := takeNumber(chars)
    89  	if err != nil {
    90  		return "", err
    91  	}
    92  	result.day = &num
    93  	return rest, nil
    94  }
    95  
    96  func parseMicrosecondsNumeric(result *datetime, chars string) (rest string, _ error) {
    97  	num, rest, err := takeNumber(chars)
    98  	if err != nil {
    99  		return "", err
   100  	}
   101  	result.microseconds = &num
   102  	return rest, nil
   103  }
   104  
   105  func parse24HourNumeric(result *datetime, chars string) (rest string, _ error) {
   106  	hour, rest, err := takeNumber(chars)
   107  	if err != nil {
   108  		return "", err
   109  	}
   110  	result.hours = &hour
   111  	return rest, nil
   112  }
   113  
   114  func parse12HourNumeric(result *datetime, chars string) (rest string, _ error) {
   115  	num, rest, err := takeNumber(chars)
   116  	if err != nil {
   117  		return "", err
   118  	}
   119  	result.hours = &num
   120  	return rest, nil
   121  }
   122  
   123  func parseMinuteNumeric(result *datetime, chars string) (rest string, _ error) {
   124  	min, rest, err := takeNumber(chars)
   125  	if err != nil {
   126  		return "", err
   127  	}
   128  	result.minutes = &min
   129  	return rest, nil
   130  }
   131  
   132  func parseMonthName(result *datetime, chars string) (rest string, _ error) {
   133  	month, charCount, ok := monthName(chars)
   134  	if !ok {
   135  		return "", fmt.Errorf("unknown month name, got \"%s\"", chars)
   136  	}
   137  	result.month = &month
   138  	return trimPrefix(charCount, chars), nil
   139  }
   140  
   141  func parse12HourTimestamp(result *datetime, chars string) (rest string, _ error) {
   142  	hour, rest, err := takeNumberAtMostNChars(2, chars)
   143  	if err != nil {
   144  		return "", err
   145  	}
   146  	rest, err = literalParser(':')(result, rest)
   147  	if err != nil {
   148  		return "", err
   149  	}
   150  	min, rest, err := takeNumberAtMostNChars(2, rest)
   151  	if err != nil {
   152  		return "", err
   153  	}
   154  	rest, err = literalParser(':')(result, rest)
   155  	if err != nil {
   156  		return "", err
   157  	}
   158  	sec, rest, err := takeNumberAtMostNChars(2, rest)
   159  	if err != nil {
   160  		return "", err
   161  	}
   162  	rest = takeAllSpaces(rest)
   163  	rest, err = parseAmPm(result, rest)
   164  	if err != nil {
   165  		return "", err
   166  	}
   167  	result.seconds = &sec
   168  	result.minutes = &min
   169  	result.hours = &hour
   170  	return rest, nil
   171  }
   172  
   173  func parseSecondsNumeric(result *datetime, chars string) (rest string, _ error) {
   174  	sec, rest, err := takeNumber(chars)
   175  	if err != nil {
   176  		return "", err
   177  	}
   178  	result.seconds = &sec
   179  	return rest, nil
   180  }
   181  
   182  func parse24HourTimestamp(result *datetime, chars string) (rest string, _ error) {
   183  	hour, rest, err := takeNumberAtMostNChars(2, chars)
   184  	if err != nil {
   185  		return "", err
   186  	}
   187  	rest, err = literalParser(':')(result, rest)
   188  	if err != nil {
   189  		return "", err
   190  	}
   191  	minute, rest, err := takeNumberAtMostNChars(2, rest)
   192  	if err != nil {
   193  		return "", err
   194  	}
   195  	rest, err = literalParser(':')(result, rest)
   196  	if err != nil {
   197  		return "", err
   198  	}
   199  	seconds, rest, err := takeNumberAtMostNChars(2, rest)
   200  	if err != nil {
   201  		return "", err
   202  	}
   203  	result.hours = &hour
   204  	result.minutes = &minute
   205  	result.seconds = &seconds
   206  	return rest, err
   207  }
   208  
   209  func parseYear2DigitNumeric(result *datetime, chars string) (rest string, _ error) {
   210  	year, rest, err := takeNumberAtMostNChars(2, chars)
   211  	if err != nil {
   212  		return "", err
   213  	}
   214  	if year >= 70 {
   215  		year += 1900
   216  	} else {
   217  		year += 2000
   218  	}
   219  	result.year = &year
   220  	return rest, nil
   221  }
   222  
   223  func parseYear4DigitNumeric(result *datetime, chars string) (rest string, _ error) {
   224  	if len(chars) < 4 {
   225  		return "", fmt.Errorf("expected at least 4 chars, got %d", len(chars))
   226  	}
   227  	year, rest, err := takeNumber(chars)
   228  	if err != nil {
   229  		return "", err
   230  	}
   231  	result.year = &year
   232  	return rest, nil
   233  }
   234  
   235  func parseDayNumericWithEnglishSuffix(result *datetime, chars string) (rest string, _ error) {
   236  	num, rest, err := takeNumber(chars)
   237  	if err != nil {
   238  		return "", err
   239  	}
   240  	result.day = &num
   241  	return trimPrefix(2, rest), nil
   242  }
   243  
   244  func parseDayOfYearNumeric(result *datetime, chars string) (rest string, _ error) {
   245  	num, rest, err := takeNumber(chars)
   246  	if err != nil {
   247  		return "", err
   248  	}
   249  	result.dayOfYear = &num
   250  	return rest, nil
   251  }