@@ -14,6 +14,7 @@ import (
14
14
"encoding/binary"
15
15
"fmt"
16
16
"io"
17
+ "strconv"
17
18
"strings"
18
19
"sync"
19
20
"sync/atomic"
@@ -227,141 +228,156 @@ var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
227
228
const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
228
229
const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
229
230
230
- func formatBinaryDateTime (src []byte , length uint8 , justTime bool ) (driver.Value , error ) {
231
- // length expects the deterministic length of the zero value,
232
- // negative time and 100+ hours are automatically added if needed
233
- if len (src ) == 0 {
234
- if justTime {
235
- return zeroDateTime [11 : 11 + length ], nil
236
- }
237
- return zeroDateTime [:length ], nil
231
+ func appendMicrosecs (dst , src []byte , decimals int ) []byte {
232
+ if decimals <= 0 {
233
+ return dst
238
234
}
239
- var dst []byte // return value
240
- var pt , p1 , p2 , p3 byte // current digit pair
241
- var zOffs byte // offset of value in zeroDateTime
242
- if justTime {
243
- switch length {
244
- case
245
- 8 , // time (can be up to 10 when negative and 100+ hours)
246
- 10 , 11 , 12 , 13 , 14 , 15 : // time with fractional seconds
247
- default :
248
- return nil , fmt .Errorf ("illegal TIME length %d" , length )
249
- }
250
- switch len (src ) {
251
- case 8 , 12 :
252
- default :
253
- return nil , fmt .Errorf ("invalid TIME packet length %d" , len (src ))
254
- }
255
- // +2 to enable negative time and 100+ hours
256
- dst = make ([]byte , 0 , length + 2 )
257
- if src [0 ] == 1 {
258
- dst = append (dst , '-' )
259
- }
260
- if src [1 ] != 0 {
261
- hour := uint16 (src [1 ])* 24 + uint16 (src [5 ])
262
- pt = byte (hour / 100 )
263
- p1 = byte (hour - 100 * uint16 (pt ))
264
- dst = append (dst , digits01 [pt ])
265
- } else {
266
- p1 = src [5 ]
267
- }
268
- zOffs = 11
269
- src = src [6 :]
270
- } else {
271
- switch length {
272
- case 10 , 19 , 21 , 22 , 23 , 24 , 25 , 26 :
273
- default :
274
- t := "DATE"
275
- if length > 10 {
276
- t += "TIME"
277
- }
278
- return nil , fmt .Errorf ("illegal %s length %d" , t , length )
279
- }
280
- switch len (src ) {
281
- case 4 , 7 , 11 :
282
- default :
283
- t := "DATE"
284
- if length > 10 {
285
- t += "TIME"
286
- }
287
- return nil , fmt .Errorf ("illegal %s packet length %d" , t , len (src ))
288
- }
289
- dst = make ([]byte , 0 , length )
290
- // start with the date
291
- year := binary .LittleEndian .Uint16 (src [:2 ])
292
- pt = byte (year / 100 )
293
- p1 = byte (year - 100 * uint16 (pt ))
294
- p2 , p3 = src [2 ], src [3 ]
295
- dst = append (dst ,
296
- digits10 [pt ], digits01 [pt ],
297
- digits10 [p1 ], digits01 [p1 ], '-' ,
298
- digits10 [p2 ], digits01 [p2 ], '-' ,
299
- digits10 [p3 ], digits01 [p3 ],
300
- )
301
- if length == 10 {
302
- return dst , nil
303
- }
304
- if len (src ) == 4 {
305
- return append (dst , zeroDateTime [10 :length ]... ), nil
306
- }
307
- dst = append (dst , ' ' )
308
- p1 = src [4 ] // hour
309
- src = src [5 :]
310
- }
311
- // p1 is 2-digit hour, src is after hour
312
- p2 , p3 = src [0 ], src [1 ]
313
- dst = append (dst ,
314
- digits10 [p1 ], digits01 [p1 ], ':' ,
315
- digits10 [p2 ], digits01 [p2 ], ':' ,
316
- digits10 [p3 ], digits01 [p3 ],
317
- )
318
- if length <= byte (len (dst )) {
319
- return dst , nil
320
- }
321
- src = src [2 :]
322
235
if len (src ) == 0 {
323
- return append (dst , zeroDateTime [ 19 : zOffs + length ]... ), nil
236
+ return append (dst , ".000000" [: decimals + 1 ]... )
324
237
}
238
+
325
239
microsecs := binary .LittleEndian .Uint32 (src [:4 ])
326
- p1 = byte (microsecs / 10000 )
240
+ p1 : = byte (microsecs / 10000 )
327
241
microsecs -= 10000 * uint32 (p1 )
328
- p2 = byte (microsecs / 100 )
242
+ p2 : = byte (microsecs / 100 )
329
243
microsecs -= 100 * uint32 (p2 )
330
- p3 = byte (microsecs )
331
- switch decimals := zOffs + length - 20 ; decimals {
244
+ p3 := byte (microsecs )
245
+
246
+ switch decimals {
332
247
default :
333
248
return append (dst , '.' ,
334
249
digits10 [p1 ], digits01 [p1 ],
335
250
digits10 [p2 ], digits01 [p2 ],
336
251
digits10 [p3 ], digits01 [p3 ],
337
- ), nil
252
+ )
338
253
case 1 :
339
254
return append (dst , '.' ,
340
255
digits10 [p1 ],
341
- ), nil
256
+ )
342
257
case 2 :
343
258
return append (dst , '.' ,
344
259
digits10 [p1 ], digits01 [p1 ],
345
- ), nil
260
+ )
346
261
case 3 :
347
262
return append (dst , '.' ,
348
263
digits10 [p1 ], digits01 [p1 ],
349
264
digits10 [p2 ],
350
- ), nil
265
+ )
351
266
case 4 :
352
267
return append (dst , '.' ,
353
268
digits10 [p1 ], digits01 [p1 ],
354
269
digits10 [p2 ], digits01 [p2 ],
355
- ), nil
270
+ )
356
271
case 5 :
357
272
return append (dst , '.' ,
358
273
digits10 [p1 ], digits01 [p1 ],
359
274
digits10 [p2 ], digits01 [p2 ],
360
275
digits10 [p3 ],
361
- ), nil
276
+ )
362
277
}
363
278
}
364
279
280
+ func formatBinaryDateTime (src []byte , length uint8 ) (driver.Value , error ) {
281
+ // length expects the deterministic length of the zero value,
282
+ // negative time and 100+ hours are automatically added if needed
283
+ if len (src ) == 0 {
284
+ return zeroDateTime [:length ], nil
285
+ }
286
+ var dst []byte // return value
287
+ var p1 , p2 , p3 byte // current digit pair
288
+
289
+ switch length {
290
+ case 10 , 19 , 21 , 22 , 23 , 24 , 25 , 26 :
291
+ default :
292
+ t := "DATE"
293
+ if length > 10 {
294
+ t += "TIME"
295
+ }
296
+ return nil , fmt .Errorf ("illegal %s length %d" , t , length )
297
+ }
298
+ switch len (src ) {
299
+ case 4 , 7 , 11 :
300
+ default :
301
+ t := "DATE"
302
+ if length > 10 {
303
+ t += "TIME"
304
+ }
305
+ return nil , fmt .Errorf ("illegal %s packet length %d" , t , len (src ))
306
+ }
307
+ dst = make ([]byte , 0 , length )
308
+ // start with the date
309
+ year := binary .LittleEndian .Uint16 (src [:2 ])
310
+ pt := year / 100
311
+ p1 = byte (year - 100 * uint16 (pt ))
312
+ p2 , p3 = src [2 ], src [3 ]
313
+ dst = append (dst ,
314
+ digits10 [pt ], digits01 [pt ],
315
+ digits10 [p1 ], digits01 [p1 ], '-' ,
316
+ digits10 [p2 ], digits01 [p2 ], '-' ,
317
+ digits10 [p3 ], digits01 [p3 ],
318
+ )
319
+ if length == 10 {
320
+ return dst , nil
321
+ }
322
+ if len (src ) == 4 {
323
+ return append (dst , zeroDateTime [10 :length ]... ), nil
324
+ }
325
+ dst = append (dst , ' ' )
326
+ p1 = src [4 ] // hour
327
+ src = src [5 :]
328
+
329
+ // p1 is 2-digit hour, src is after hour
330
+ p2 , p3 = src [0 ], src [1 ]
331
+ dst = append (dst ,
332
+ digits10 [p1 ], digits01 [p1 ], ':' ,
333
+ digits10 [p2 ], digits01 [p2 ], ':' ,
334
+ digits10 [p3 ], digits01 [p3 ],
335
+ )
336
+ return appendMicrosecs (dst , src [2 :], int (length )- 20 ), nil
337
+ }
338
+
339
+ func formatBinaryTime (src []byte , length uint8 ) (driver.Value , error ) {
340
+ // length expects the deterministic length of the zero value,
341
+ // negative time and 100+ hours are automatically added if needed
342
+ if len (src ) == 0 {
343
+ return zeroDateTime [11 : 11 + length ], nil
344
+ }
345
+ var dst []byte // return value
346
+
347
+ switch length {
348
+ case
349
+ 8 , // time (can be up to 10 when negative and 100+ hours)
350
+ 10 , 11 , 12 , 13 , 14 , 15 : // time with fractional seconds
351
+ default :
352
+ return nil , fmt .Errorf ("illegal TIME length %d" , length )
353
+ }
354
+ switch len (src ) {
355
+ case 8 , 12 :
356
+ default :
357
+ return nil , fmt .Errorf ("invalid TIME packet length %d" , len (src ))
358
+ }
359
+ // +2 to enable negative time and 100+ hours
360
+ dst = make ([]byte , 0 , length + 2 )
361
+ if src [0 ] == 1 {
362
+ dst = append (dst , '-' )
363
+ }
364
+ days := binary .LittleEndian .Uint32 (src [1 :5 ])
365
+ hours := int64 (days )* 24 + int64 (src [5 ])
366
+
367
+ if hours >= 100 {
368
+ dst = strconv .AppendInt (dst , hours , 10 )
369
+ } else {
370
+ dst = append (dst , digits10 [hours ], digits01 [hours ])
371
+ }
372
+
373
+ min , sec := src [6 ], src [7 ]
374
+ dst = append (dst , ':' ,
375
+ digits10 [min ], digits01 [min ], ':' ,
376
+ digits10 [sec ], digits01 [sec ],
377
+ )
378
+ return appendMicrosecs (dst , src [8 :], int (length )- 9 ), nil
379
+ }
380
+
365
381
/******************************************************************************
366
382
* Convert from and to bytes *
367
383
******************************************************************************/
0 commit comments