85 lines
1.8 KiB
Go
85 lines
1.8 KiB
Go
package logfile
|
|
|
|
// parseRFC3339Nano parses an RFC3339 stamp with optional fractional seconds
|
|
// into unix nanoseconds. Hand-rolled to keep the index pass allocation-free.
|
|
func parseRFC3339Nano(b []byte) (int64, bool) {
|
|
if len(b) < 19 {
|
|
return 0, false
|
|
}
|
|
if b[4] != '-' || b[7] != '-' || (b[10] != 'T' && b[10] != 't') || b[13] != ':' || b[16] != ':' {
|
|
return 0, false
|
|
}
|
|
y, ok1 := numField(b[0:4])
|
|
mo, ok2 := numField(b[5:7])
|
|
d, ok3 := numField(b[8:10])
|
|
h, ok4 := numField(b[11:13])
|
|
mi, ok5 := numField(b[14:16])
|
|
s, ok6 := numField(b[17:19])
|
|
if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 {
|
|
return 0, false
|
|
}
|
|
|
|
i := 19
|
|
var frac int64
|
|
if i < len(b) && b[i] == '.' {
|
|
scale := int64(100000000)
|
|
for i++; i < len(b) && b[i] >= '0' && b[i] <= '9'; i++ {
|
|
if scale > 0 {
|
|
frac += int64(b[i]-'0') * scale
|
|
scale /= 10
|
|
}
|
|
}
|
|
}
|
|
|
|
var offSec int64
|
|
if i < len(b) {
|
|
switch b[i] {
|
|
case 'Z', 'z':
|
|
case '+', '-':
|
|
if i+6 > len(b) || b[i+3] != ':' {
|
|
return 0, false
|
|
}
|
|
oh, okh := numField(b[i+1 : i+3])
|
|
om, okm := numField(b[i+4 : i+6])
|
|
if !okh || !okm {
|
|
return 0, false
|
|
}
|
|
offSec = int64(oh)*3600 + int64(om)*60
|
|
if b[i] == '-' {
|
|
offSec = -offSec
|
|
}
|
|
}
|
|
}
|
|
|
|
sec := daysFromCivil(y, mo, d)*86400 + int64(h)*3600 + int64(mi)*60 + int64(s) - offSec
|
|
return sec*1e9 + frac, true
|
|
}
|
|
|
|
func numField(b []byte) (int, bool) {
|
|
v := 0
|
|
for _, c := range b {
|
|
if c < '0' || c > '9' {
|
|
return 0, false
|
|
}
|
|
v = v*10 + int(c-'0')
|
|
}
|
|
return v, true
|
|
}
|
|
|
|
// daysFromCivil returns days since 1970-01-01 (Hinnant's civil-date algorithm).
|
|
func daysFromCivil(y, m, d int) int64 {
|
|
if m <= 2 {
|
|
y--
|
|
}
|
|
era := y
|
|
if era < 0 {
|
|
era -= 399
|
|
}
|
|
era /= 400
|
|
yoe := y - era*400
|
|
mp := (m + 9) % 12
|
|
doy := (153*mp+2)/5 + d - 1
|
|
doe := yoe*365 + yoe/4 - yoe/100 + doy
|
|
return int64(era)*146097 + int64(doe) - 719468
|
|
}
|