@@ -14,6 +14,7 @@ import (
1414 "encoding/binary"
1515 "fmt"
1616 "io"
17+ "strconv"
1718 "strings"
1819 "sync"
1920 "sync/atomic"
@@ -227,141 +228,156 @@ var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
227228const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
228229const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
229230
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
238234 }
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 :]
322235 if len (src ) == 0 {
323- return append (dst , zeroDateTime [ 19 : zOffs + length ]... ), nil
236+ return append (dst , ".000000" [: decimals + 1 ]... )
324237 }
238+
325239 microsecs := binary .LittleEndian .Uint32 (src [:4 ])
326- p1 = byte (microsecs / 10000 )
240+ p1 : = byte (microsecs / 10000 )
327241 microsecs -= 10000 * uint32 (p1 )
328- p2 = byte (microsecs / 100 )
242+ p2 : = byte (microsecs / 100 )
329243 microsecs -= 100 * uint32 (p2 )
330- p3 = byte (microsecs )
331- switch decimals := zOffs + length - 20 ; decimals {
244+ p3 := byte (microsecs )
245+
246+ switch decimals {
332247 default :
333248 return append (dst , '.' ,
334249 digits10 [p1 ], digits01 [p1 ],
335250 digits10 [p2 ], digits01 [p2 ],
336251 digits10 [p3 ], digits01 [p3 ],
337- ), nil
252+ )
338253 case 1 :
339254 return append (dst , '.' ,
340255 digits10 [p1 ],
341- ), nil
256+ )
342257 case 2 :
343258 return append (dst , '.' ,
344259 digits10 [p1 ], digits01 [p1 ],
345- ), nil
260+ )
346261 case 3 :
347262 return append (dst , '.' ,
348263 digits10 [p1 ], digits01 [p1 ],
349264 digits10 [p2 ],
350- ), nil
265+ )
351266 case 4 :
352267 return append (dst , '.' ,
353268 digits10 [p1 ], digits01 [p1 ],
354269 digits10 [p2 ], digits01 [p2 ],
355- ), nil
270+ )
356271 case 5 :
357272 return append (dst , '.' ,
358273 digits10 [p1 ], digits01 [p1 ],
359274 digits10 [p2 ], digits01 [p2 ],
360275 digits10 [p3 ],
361- ), nil
276+ )
362277 }
363278}
364279
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+
365381/******************************************************************************
366382* Convert from and to bytes *
367383******************************************************************************/
0 commit comments