X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=tai64n.go;h=e6dd28e7fd420cc9d3bc7c46b6115823efbe7c39;hb=f8a8a335216a6ec9aa6119d473d2f6aeb43958ca;hp=f2b4791f1a58e7d602e6616b9a20379dbebff447;hpb=6ef14f9de82e4a61532b84b149bde0c953d58a04;p=goredo.git diff --git a/tai64n.go b/tai64n.go index f2b4791..e6dd28e 100644 --- a/tai64n.go +++ b/tai64n.go @@ -1,14 +1,82 @@ +/* +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" ) -type TAI64N [12]byte +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(0x400000000000000a)+uint64(t.Unix())) + 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 +}