mirror of https://github.com/jackc/pgx.git
Fix text decoding of dates with 5 digit years
parent
071d1c9467
commit
871f14e43b
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
@ -267,6 +268,8 @@ func (scanPlanBinaryDateToDateScanner) Scan(src []byte, dst any) error {
|
|||
|
||||
type scanPlanTextAnyToDateScanner struct{}
|
||||
|
||||
var dateRegexp = regexp.MustCompile(`^(\d{4,})-(\d\d)-(\d\d)( BC)?$`)
|
||||
|
||||
func (scanPlanTextAnyToDateScanner) Scan(src []byte, dst any) error {
|
||||
scanner := (dst).(DateScanner)
|
||||
|
||||
|
@ -275,35 +278,39 @@ func (scanPlanTextAnyToDateScanner) Scan(src []byte, dst any) error {
|
|||
}
|
||||
|
||||
sbuf := string(src)
|
||||
match := dateRegexp.FindStringSubmatch(sbuf)
|
||||
if match != nil {
|
||||
year, err := strconv.ParseInt(match[1], 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("BUG: cannot parse date that regexp matched (year): %v", err)
|
||||
}
|
||||
|
||||
month, err := strconv.ParseInt(match[2], 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("BUG: cannot parse date that regexp matched (month): %v", err)
|
||||
}
|
||||
|
||||
day, err := strconv.ParseInt(match[3], 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("BUG: cannot parse date that regexp matched (month): %v", err)
|
||||
}
|
||||
|
||||
// BC matched
|
||||
if len(match[4]) > 0 {
|
||||
year = -year + 1
|
||||
}
|
||||
|
||||
t := time.Date(int(year), time.Month(month), int(day), 0, 0, 0, 0, time.UTC)
|
||||
return scanner.ScanDate(Date{Time: t, Valid: true})
|
||||
}
|
||||
|
||||
switch sbuf {
|
||||
case "infinity":
|
||||
return scanner.ScanDate(Date{InfinityModifier: Infinity, Valid: true})
|
||||
case "-infinity":
|
||||
return scanner.ScanDate(Date{InfinityModifier: -Infinity, Valid: true})
|
||||
default:
|
||||
if len(sbuf) >= 10 {
|
||||
year, err := strconv.ParseInt(sbuf[0:4], 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot parse year: %v", err)
|
||||
}
|
||||
month, err := strconv.ParseInt(sbuf[5:7], 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot parse month: %v", err)
|
||||
}
|
||||
day, err := strconv.ParseInt(sbuf[8:10], 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot parse day: %v", err)
|
||||
}
|
||||
|
||||
if len(sbuf) == 13 && sbuf[11:] == "BC" {
|
||||
year = -year + 1
|
||||
}
|
||||
|
||||
t := time.Date(int(year), time.Month(month), int(day), 0, 0, 0, 0, time.UTC)
|
||||
return scanner.ScanDate(Date{Time: t, Valid: true})
|
||||
} else {
|
||||
return fmt.Errorf("date too short")
|
||||
}
|
||||
return fmt.Errorf("date too short")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ func TestDateCodec(t *testing.T) {
|
|||
{time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC))},
|
||||
{time.Date(2000, 1, 2, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(2000, 1, 2, 0, 0, 0, 0, time.UTC))},
|
||||
{time.Date(2200, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(2200, 1, 1, 0, 0, 0, 0, time.UTC))},
|
||||
{time.Date(12200, 1, 2, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(12200, 1, 2, 0, 0, 0, 0, time.UTC))},
|
||||
{pgtype.Date{InfinityModifier: pgtype.Infinity, Valid: true}, new(pgtype.Date), isExpectedEq(pgtype.Date{InfinityModifier: pgtype.Infinity, Valid: true})},
|
||||
{pgtype.Date{InfinityModifier: pgtype.NegativeInfinity, Valid: true}, new(pgtype.Date), isExpectedEq(pgtype.Date{InfinityModifier: pgtype.NegativeInfinity, Valid: true})},
|
||||
{pgtype.Date{}, new(pgtype.Date), isExpectedEq(pgtype.Date{})},
|
||||
|
@ -51,6 +52,7 @@ func TestDateCodecTextEncode(t *testing.T) {
|
|||
{source: pgtype.Date{Time: time.Date(789, 1, 2, 0, 0, 0, 0, time.UTC), Valid: true}, result: "0789-01-02"},
|
||||
{source: pgtype.Date{Time: time.Date(89, 1, 2, 0, 0, 0, 0, time.UTC), Valid: true}, result: "0089-01-02"},
|
||||
{source: pgtype.Date{Time: time.Date(9, 1, 2, 0, 0, 0, 0, time.UTC), Valid: true}, result: "0009-01-02"},
|
||||
{source: pgtype.Date{Time: time.Date(12200, 1, 2, 0, 0, 0, 0, time.UTC), Valid: true}, result: "12200-01-02"},
|
||||
{source: pgtype.Date{InfinityModifier: pgtype.Infinity, Valid: true}, result: "infinity"},
|
||||
{source: pgtype.Date{InfinityModifier: pgtype.NegativeInfinity, Valid: true}, result: "-infinity"},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue