/* goredo -- redo implementation on pure Go Copyright (C) 2020 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package main import ( "bufio" "encoding/binary" "encoding/hex" "errors" "io" "strings" "time" ) const ( TAI64NSize = 12 TAI64NBase = 0x400000000000000a TAI64NLocalFmt = "2006-01-02 15:04:05.000000000" ) type TAI64N [TAI64NSize]byte func tai64nNow(ts *TAI64N) { t := time.Now() binary.BigEndian.PutUint64(ts[:], uint64(TAI64NBase)+uint64(t.Unix())) binary.BigEndian.PutUint32(ts[8:], uint32(t.Nanosecond())) } func tai64nLocal(dst io.StringWriter, src io.Reader) error { scanner := bufio.NewScanner(src) var err error var s string var sep int var ts []byte var secs int64 var nano int64 var t time.Time for { if !scanner.Scan() { if err = scanner.Err(); err != nil { return err } break } s = scanner.Text() if s[0] != '@' { dst.WriteString(s + "\n") } sep = strings.IndexByte(s, byte(' ')) if sep == -1 { dst.WriteString(s + "\n") } ts, err = hex.DecodeString(s[1:sep]) if err != nil { return err } if len(ts) != TAI64NSize { return errors.New("invalid ts length") } secs = int64(binary.BigEndian.Uint64(ts[:8])) nano = int64(binary.BigEndian.Uint32(ts[8:])) t = time.Unix(secs-TAI64NBase, nano) dst.WriteString(t.Format(TAI64NLocalFmt) + s[sep:] + "\n") } return nil }