]> Cypherpunks.ru repositories - gotai64n.git/commitdiff
Initial commit v0.1.0
authorSergey Matveev <stargrave@stargrave.org>
Thu, 10 Dec 2020 13:42:45 +0000 (16:42 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Thu, 10 Dec 2020 13:50:27 +0000 (16:50 +0300)
go.mod [new file with mode: 0644]
tai64n.go [new file with mode: 0644]

diff --git a/go.mod b/go.mod
new file mode 100644 (file)
index 0000000..79a8308
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module go.cypherpunks.ru/tai64n
+
+go 1.14
diff --git a/tai64n.go b/tai64n.go
new file mode 100644 (file)
index 0000000..34a63d1
--- /dev/null
+++ b/tai64n.go
@@ -0,0 +1,63 @@
+/*
+go.cypherpunks.ru/tai64n -- Pure Go TAI64N implementation
+Copyright (C) 2020 Sergey Matveev <stargrave@stargrave.org>
+
+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 <http://www.gnu.org/licenses/>.
+*/
+
+package tai64n
+
+import (
+       "encoding/binary"
+       "encoding/hex"
+       "errors"
+       "strings"
+       "time"
+)
+
+const (
+       Size     = 12
+       Base     = 0x400000000000000a
+       LocalFmt = "2006-01-02 15:04:05.000000000"
+)
+
+type TAI64N [Size]byte
+
+func FromTime(t time.Time, tai *TAI64N) {
+       binary.BigEndian.PutUint64(tai[:], uint64(Base)+uint64(t.Unix()))
+       binary.BigEndian.PutUint32(tai[8:], uint32(t.Nanosecond()))
+}
+
+func ToTime(tai []byte) time.Time {
+       if len(tai) != Size {
+               panic("invalid size")
+       }
+       secs := int64(binary.BigEndian.Uint64(tai[:8]))
+       nano := int64(binary.BigEndian.Uint32(tai[8:]))
+       return time.Unix(secs-Base, nano)
+}
+
+func (tai TAI64N) Encode() string {
+       return "@" + hex.EncodeToString(tai[:])
+}
+
+func Decode(s string) (time.Time, error) {
+       tai, err := hex.DecodeString(strings.TrimPrefix(s, "@"))
+       if len(tai) != Size {
+               return time.Time{}, errors.New("invalid ts length")
+       }
+       if err != nil {
+               return time.Time{}, err
+       }
+       return ToTime(tai), nil
+}