Skip to content

Commit fe2230a

Browse files
authored
stop rounding times (go-sql-driver#1172)
* stop rounding times fixes go-sql-driver#1121 * trim trailing zeros
1 parent 4d5208a commit fe2230a

File tree

2 files changed

+44
-36
lines changed

2 files changed

+44
-36
lines changed

utils.go

+26-17
Original file line numberDiff line numberDiff line change
@@ -277,30 +277,24 @@ func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Va
277277
}
278278

279279
func appendDateTime(buf []byte, t time.Time) ([]byte, error) {
280-
nsec := t.Nanosecond()
281-
// to round under microsecond
282-
if nsec%1000 >= 500 { // save half of time.Time.Add calls
283-
t = t.Add(500 * time.Nanosecond)
284-
nsec = t.Nanosecond()
285-
}
286280
year, month, day := t.Date()
287281
hour, min, sec := t.Clock()
288-
micro := nsec / 1000
282+
nsec := t.Nanosecond()
289283

290284
if year < 1 || year > 9999 {
291285
return buf, errors.New("year is not in the range [1, 9999]: " + strconv.Itoa(year)) // use errors.New instead of fmt.Errorf to avoid year escape to heap
292286
}
293287
year100 := year / 100
294288
year1 := year % 100
295289

296-
var localBuf [26]byte // does not escape
290+
var localBuf [len("2006-01-02T15:04:05.999999999")]byte // does not escape
297291
localBuf[0], localBuf[1], localBuf[2], localBuf[3] = digits10[year100], digits01[year100], digits10[year1], digits01[year1]
298292
localBuf[4] = '-'
299293
localBuf[5], localBuf[6] = digits10[month], digits01[month]
300294
localBuf[7] = '-'
301295
localBuf[8], localBuf[9] = digits10[day], digits01[day]
302296

303-
if hour == 0 && min == 0 && sec == 0 && micro == 0 {
297+
if hour == 0 && min == 0 && sec == 0 && nsec == 0 {
304298
return append(buf, localBuf[:10]...), nil
305299
}
306300

@@ -311,18 +305,33 @@ func appendDateTime(buf []byte, t time.Time) ([]byte, error) {
311305
localBuf[16] = ':'
312306
localBuf[17], localBuf[18] = digits10[sec], digits01[sec]
313307

314-
if micro == 0 {
308+
if nsec == 0 {
315309
return append(buf, localBuf[:19]...), nil
316310
}
317-
318-
micro10000 := micro / 10000
319-
micro100 := (micro / 100) % 100
320-
micro1 := micro % 100
311+
nsec100000000 := nsec / 100000000
312+
nsec1000000 := (nsec / 1000000) % 100
313+
nsec10000 := (nsec / 10000) % 100
314+
nsec100 := (nsec / 100) % 100
315+
nsec1 := nsec % 100
321316
localBuf[19] = '.'
322-
localBuf[20], localBuf[21], localBuf[22], localBuf[23], localBuf[24], localBuf[25] =
323-
digits10[micro10000], digits01[micro10000], digits10[micro100], digits01[micro100], digits10[micro1], digits01[micro1]
324317

325-
return append(buf, localBuf[:]...), nil
318+
// milli second
319+
localBuf[20], localBuf[21], localBuf[22] =
320+
digits01[nsec100000000], digits10[nsec1000000], digits01[nsec1000000]
321+
// micro second
322+
localBuf[23], localBuf[24], localBuf[25] =
323+
digits10[nsec10000], digits01[nsec10000], digits10[nsec100]
324+
// nano second
325+
localBuf[26], localBuf[27], localBuf[28] =
326+
digits01[nsec100], digits10[nsec1], digits01[nsec1]
327+
328+
// trim trailing zeros
329+
n := len(localBuf)
330+
for n > 0 && localBuf[n-1] == '0' {
331+
n--
332+
}
333+
334+
return append(buf, localBuf[:n]...), nil
326335
}
327336

328337
// zeroDateTime is used in formatBinaryDateTime to avoid an allocation

utils_test.go

+18-19
Original file line numberDiff line numberDiff line change
@@ -299,48 +299,47 @@ func TestAppendDateTime(t *testing.T) {
299299
str string
300300
}{
301301
{
302-
t: time.Date(2020, 05, 30, 0, 0, 0, 0, time.UTC),
303-
str: "2020-05-30",
302+
t: time.Date(1234, 5, 6, 0, 0, 0, 0, time.UTC),
303+
str: "1234-05-06",
304304
},
305305
{
306-
t: time.Date(2020, 05, 30, 22, 0, 0, 0, time.UTC),
307-
str: "2020-05-30 22:00:00",
306+
t: time.Date(4567, 12, 31, 12, 0, 0, 0, time.UTC),
307+
str: "4567-12-31 12:00:00",
308308
},
309309
{
310-
t: time.Date(2020, 05, 30, 22, 33, 0, 0, time.UTC),
311-
str: "2020-05-30 22:33:00",
310+
t: time.Date(2020, 5, 30, 12, 34, 0, 0, time.UTC),
311+
str: "2020-05-30 12:34:00",
312312
},
313313
{
314-
t: time.Date(2020, 05, 30, 22, 33, 44, 0, time.UTC),
315-
str: "2020-05-30 22:33:44",
314+
t: time.Date(2020, 5, 30, 12, 34, 56, 0, time.UTC),
315+
str: "2020-05-30 12:34:56",
316316
},
317317
{
318-
t: time.Date(2020, 05, 30, 22, 33, 44, 550000000, time.UTC),
319-
str: "2020-05-30 22:33:44.550000",
318+
t: time.Date(2020, 5, 30, 22, 33, 44, 123000000, time.UTC),
319+
str: "2020-05-30 22:33:44.123",
320320
},
321321
{
322-
t: time.Date(2020, 05, 30, 22, 33, 44, 550000499, time.UTC),
323-
str: "2020-05-30 22:33:44.550000",
322+
t: time.Date(2020, 5, 30, 22, 33, 44, 123456000, time.UTC),
323+
str: "2020-05-30 22:33:44.123456",
324324
},
325325
{
326-
t: time.Date(2020, 05, 30, 22, 33, 44, 550000500, time.UTC),
327-
str: "2020-05-30 22:33:44.550001",
326+
t: time.Date(2020, 5, 30, 22, 33, 44, 123456789, time.UTC),
327+
str: "2020-05-30 22:33:44.123456789",
328328
},
329329
{
330-
t: time.Date(2020, 05, 30, 22, 33, 44, 550000567, time.UTC),
331-
str: "2020-05-30 22:33:44.550001",
330+
t: time.Date(9999, 12, 31, 23, 59, 59, 999999999, time.UTC),
331+
str: "9999-12-31 23:59:59.999999999",
332332
},
333333
{
334-
t: time.Date(2020, 05, 30, 22, 33, 44, 999999567, time.UTC),
335-
str: "2020-05-30 22:33:45",
334+
t: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC),
335+
str: "0001-01-01",
336336
},
337337
}
338338
for _, v := range tests {
339339
buf := make([]byte, 0, 32)
340340
buf, _ = appendDateTime(buf, v.t)
341341
if str := string(buf); str != v.str {
342342
t.Errorf("appendDateTime(%v), have: %s, want: %s", v.t, str, v.str)
343-
return
344343
}
345344
}
346345

0 commit comments

Comments
 (0)