From 465d3c327fc42f1ae8852948b7215b80da1d60a1 Mon Sep 17 00:00:00 2001 From: Dan Hansen Date: Thu, 25 Jan 2024 16:57:49 -0800 Subject: [PATCH] [Date] Implement `%y` year without century parser / formatter --- internal/function_time_parser.go | 38 ++++++++++++++++++++++++++++++-- query_test.go | 10 +++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/internal/function_time_parser.go b/internal/function_time_parser.go index 3802ef4..833918b 100644 --- a/internal/function_time_parser.go +++ b/internal/function_time_parser.go @@ -372,8 +372,8 @@ var formatPatternMap = map[rune]*FormatTimeInfo{ AvailableTypes: []TimeFormatType{ FormatTypeDate, FormatTypeDatetime, FormatTypeTimestamp, }, - Parse: centuryParser, - Format: centuryFormatter, + Parse: yearWithoutCenturyParser, + Format: yearWithoutCenturyFormatter, }, 'Z': &FormatTimeInfo{ AvailableTypes: []TimeFormatType{ @@ -518,6 +518,40 @@ func centuryFormatter(t *time.Time) ([]rune, error) { return []rune(fmt.Sprint(t.Year())[:2]), nil } +func yearWithoutCenturyParser(text []rune, t *time.Time) (int, error) { + const yearLen = 2 + if len(text) > yearLen { + return 0, fmt.Errorf("unexpected year number") + } + year, err := strconv.ParseInt(string(text), 10, 64) + if err != nil { + return 0, fmt.Errorf("unexpected year number") + } + if year < 0 { + return 0, fmt.Errorf("invalid year number %d", year) + } + century := 2000 + if year >= 69 { + century = 1900 + } + *t = time.Date( + century+int(year), + t.Month(), + int(t.Day()), + int(t.Hour()), + int(t.Minute()), + int(t.Second()), + int(t.Nanosecond()), + t.Location(), + ) + return len(text), nil +} + +func yearWithoutCenturyFormatter(t *time.Time) ([]rune, error) { + year := t.Format("2006") + return []rune(year[len(year)-2:]), nil +} + func ansicParser(text []rune, t *time.Time) (int, error) { v, err := time.Parse("Mon Jan 02 15:04:05 2006", string(text)) if err != nil { diff --git a/query_test.go b/query_test.go index 31d13f3..7249b3e 100644 --- a/query_test.go +++ b/query_test.go @@ -3690,6 +3690,11 @@ SELECT date, EXTRACT(ISOYEAR FROM date), EXTRACT(YEAR FROM date), EXTRACT(MONTH query: `SELECT FORMAT_DATE("%x", DATE "2008-12-25")`, expectedRows: [][]interface{}{{"12/25/08"}}, }, + { + name: "format_date with %y", + query: `SELECT FORMAT_DATE("%y", DATE "2008-12-25"), FORMAT_DATE("%y", DATE "2012-12-25")`, + expectedRows: [][]interface{}{{"08", "12"}}, + }, { name: "format_date with %b-%d-%Y", query: `SELECT FORMAT_DATE("%b-%d-%Y", DATE "2008-12-25")`, @@ -3731,6 +3736,11 @@ SELECT date, EXTRACT(ISOYEAR FROM date), EXTRACT(YEAR FROM date), EXTRACT(MONTH query: `SELECT LAST_DAY(DATE '2008-11-10', WEEK(MONDAY)) AS last_day`, expectedRows: [][]interface{}{{"2008-11-16"}}, }, + { + name: "parse_date with %y", + query: `SELECT PARSE_DATE("%y", '1'), PARSE_DATE("%y", '67'), PARSE_DATE("%y", '69')`, + expectedRows: [][]interface{}{{"2001-01-01", "2067-01-01", "1969-01-01"}}, + }, { name: "parse date with %A %b %e %Y", query: `SELECT PARSE_DATE("%A %b %e %Y", "Thursday Dec 25 2008")`,