github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/timeutil/pgdate/pgdate_test.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package pgdate 12 13 import ( 14 "fmt" 15 "math" 16 "strings" 17 "testing" 18 "time" 19 ) 20 21 func TestParseDate(t *testing.T) { 22 for _, tc := range []struct { 23 s string 24 err string 25 pgdays int32 26 }{ 27 { 28 s: "2000-01-01", 29 pgdays: 0, 30 }, 31 { 32 s: "1999-12-31", 33 pgdays: -1, 34 }, 35 { 36 s: "2000-01-02", 37 pgdays: 1, 38 }, 39 { 40 s: "0001-01-01", 41 pgdays: -730119, 42 }, 43 { 44 s: "0001-12-31 BC", 45 pgdays: -730120, 46 }, 47 { 48 s: "0002-01-01 BC", 49 pgdays: -730850, 50 }, 51 { 52 s: "5874897-12-31", 53 pgdays: highDays, 54 }, 55 { 56 s: "4714-11-24 BC", 57 pgdays: lowDays, 58 }, 59 { 60 s: "4714-11-23 BC", 61 err: "date is out of range", 62 }, 63 { 64 s: "5874898-01-01", 65 err: "date is out of range", 66 }, 67 { 68 s: "0000-01-01", 69 err: "year value 0 is out of range", 70 }, 71 } { 72 t.Run(tc.s, func(t *testing.T) { 73 d, err := ParseDate(time.Time{}, ParseModeYMD, tc.s) 74 if tc.err != "" { 75 if err == nil || !strings.Contains(err.Error(), tc.err) { 76 t.Fatalf("got %v, expected %v", err, tc.err) 77 } 78 return 79 } 80 pg := d.PGEpochDays() 81 if pg != tc.pgdays { 82 t.Fatalf("%d != %d", pg, tc.pgdays) 83 } 84 s := d.String() 85 if s != tc.s { 86 t.Fatalf("%s != %s", s, tc.s) 87 } 88 }) 89 } 90 } 91 92 func TestMakeCompatibleDateFromDisk(t *testing.T) { 93 for _, tc := range []struct { 94 in, out int64 95 }{ 96 {0, 0}, 97 {1, 1}, 98 {-1, -1}, 99 {math.MaxInt64, math.MaxInt64}, 100 {math.MinInt64, math.MinInt64}, 101 {math.MaxInt32, math.MaxInt64}, 102 {math.MinInt32, math.MinInt64}, 103 } { 104 t.Run(fmt.Sprint(tc.in), func(t *testing.T) { 105 date := MakeCompatibleDateFromDisk(tc.in) 106 orig := date.UnixEpochDaysWithOrig() 107 if orig != tc.in { 108 t.Fatalf("%d != %d", orig, tc.in) 109 } 110 days := date.UnixEpochDays() 111 if days != tc.out { 112 t.Fatalf("%d != %d", days, tc.out) 113 } 114 }) 115 } 116 } 117 118 func TestMakeDateFromTime(t *testing.T) { 119 pgEpoch := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC) 120 pgEpochWithHourOffset := time.Date(2000, 1, 1, 1, 0, 0, 0, time.UTC) 121 // These dates are negative, which makes rounding a little different. 122 dayBeforeUnixEpoch := time.Date(1969, 12, 31, 0, 0, 0, 0, time.UTC) 123 dayBeforeUnixEpochWithHourOffset := time.Date(1969, 12, 31, 1, 0, 0, 0, time.UTC) 124 twoDaysBeforeUnixEpoch := time.Date(1969, 12, 30, 0, 0, 0, 0, time.UTC) 125 twoDaysBeforeUnixEpochWithHourOffset := time.Date(1969, 12, 30, 1, 0, 0, 0, time.UTC) 126 127 for _, tc := range []struct { 128 in time.Time 129 out string 130 }{ 131 {pgEpoch.In(time.FixedZone("secsPerDay", secondsPerDay)), "2000-01-02"}, 132 {pgEpoch.In(time.FixedZone("secsPerDay-1", secondsPerDay-1)), "2000-01-01"}, 133 {pgEpoch.In(time.FixedZone("1", 1)), "2000-01-01"}, 134 {pgEpoch, "2000-01-01"}, 135 {pgEpoch.In(time.FixedZone("-1", -1)), "1999-12-31"}, 136 {pgEpoch.In(time.FixedZone("-secsPerDay", -secondsPerDay)), "1999-12-31"}, 137 {pgEpochWithHourOffset, "2000-01-01"}, 138 139 {dayBeforeUnixEpoch, "1969-12-31"}, 140 {dayBeforeUnixEpochWithHourOffset, "1969-12-31"}, 141 {twoDaysBeforeUnixEpoch, "1969-12-30"}, 142 {twoDaysBeforeUnixEpochWithHourOffset, "1969-12-30"}, 143 } { 144 t.Run(tc.in.Format(time.RFC3339), func(t *testing.T) { 145 d, err := MakeDateFromTime(tc.in) 146 if err != nil { 147 t.Fatal(err) 148 } 149 exp := tc.in.Format("2006-01-02") 150 // Sanity check our tests. 151 if exp != tc.out { 152 t.Fatalf("got %s, expected %s", exp, tc.out) 153 } 154 s := d.String() 155 if exp != s { 156 t.Fatalf("got %s, expected %s", s, exp) 157 } 158 }) 159 } 160 }