Skip to content

Commit

Permalink
time parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
rusq committed Mar 26, 2024
1 parent 034f065 commit 6e1b3f6
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 10 deletions.
21 changes: 11 additions & 10 deletions internal/edge/dms.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/rusq/slack"
"github.com/rusq/slackdump/v3/internal/fasttime"
)

type dmsForm struct {
Expand All @@ -31,8 +32,8 @@ type dmsResponse struct {
type DM struct {
ID string `json:"id"`
// Message slack.Message `json:"message,omitempty"`
Channel Channel `json:"channel,omitempty"`
Latest string `json:"latest,omitempty"` // i.e. "1710632873.037269"
Channel Channel `json:"channel,omitempty"`
Latest fasttime.Time `json:"latest,omitempty"` // i.e. "1710632873.037269"
}

type Channel struct {
Expand All @@ -45,8 +46,8 @@ type Channel struct {
ContextTeamID string `json:"context_team_id"`
Updated slack.JSONTime `json:"updated"`
User string `json:"user"`
LastRead string `json:"last_read"`
Latest string `json:"latest"`
LastRead fasttime.Time `json:"last_read"`
Latest fasttime.Time `json:"latest"`
IsOpen bool `json:"is_open"`
}

Expand Down Expand Up @@ -149,12 +150,12 @@ type CountsResponse struct {
}

type ChannelSnapshot struct {
ID string `json:"id"`
LastRead string `json:"last_read"`
Latest string `json:"latest"`
HistoryInvalid string `json:"history_invalid"`
MentionCount int `json:"mention_count"`
HasUnreads bool `json:"has_unreads"`
ID string `json:"id"`
LastRead fasttime.Time `json:"last_read"`
Latest fasttime.Time `json:"latest"`
HistoryInvalid fasttime.Time `json:"history_invalid"`
MentionCount int `json:"mention_count"`
HasUnreads bool `json:"has_unreads"`
}

func (cl *Client) Counts(ctx context.Context) (CountsResponse, error) {
Expand Down
51 changes: 51 additions & 0 deletions internal/fasttime/fasttime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package fasttime

import (
"errors"
"strconv"
"strings"
"time"
)

type Time time.Time

func (t *Time) UnmarshalJSON(data []byte) error {
ts, err := TS2int(strings.Trim(string(data), `"`))
if err != nil {
return err
}
*t = Time(Int2Time(ts))
return nil
}

func (t Time) MarshalJSON() ([]byte, error) {
ts := time.Time(t).UnixMicro()
return []byte(`"` + Int2TS(ts) + `"`), nil
}

// TS2int converts a slack timestamp to an int64 by stripping the dot and
// converting the string to an int64. It is useful for fast comparison.
func TS2int(ts string) (int64, error) {
before, after, found := strings.Cut(ts, ".")
if !found {
return 0, errors.New("not a slack timestamp")
}
return strconv.ParseInt(before+after, 10, 64)
}

// Int2TS converts an int64 to a slack timestamp by inserting a dot in the
// right place.
func Int2TS(ts int64) string {
s := strconv.FormatInt(ts, 10)
if len(s) < 7 {
return ""
}
lo := s[len(s)-6:]
hi := s[:len(s)-6]
return hi + "." + lo
}

// Int2Time converts an int64 to a time.Time.
func Int2Time(ts int64) time.Time {
return time.UnixMicro(ts)
}
114 changes: 114 additions & 0 deletions internal/fasttime/fasttime_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package fasttime

import (
"reflect"
"testing"
"time"
)

func TestTs2int(t *testing.T) {
type args struct {
ts string
}
tests := []struct {
name string
args args
want int64
wantErr bool
}{
{
"valid ts",
args{"1638494510.037400"},
1638494510037400,
false,
},
{
"invalid ts",
args{"x"},
0,
true,
},
{
"real ts",
args{"1674255434.388009"},
1674255434388009,
false,
},
{
"no dot",
args{"1674255434"},
0,
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := TS2int(tt.args.ts)
if (err != nil) != tt.wantErr {
t.Errorf("TS2Int64() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("TS2Int64() = %v, want %v", got, tt.want)
}
})
}
}

func TestInt2ts(t *testing.T) {
type args struct {
ts int64
}
tests := []struct {
name string
args args
want string
}{
{
"valid ts",
args{1638494510037400},
"1638494510.037400",
},
{
"real ts",
args{1674255434388009},
"1674255434.388009",
},
{
"zero",
args{0},
"",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Int2TS(tt.args.ts); got != tt.want {
t.Errorf("Int642TS() = %v, want %v", got, tt.want)
}
})
}
}

func TestInt2Time(t *testing.T) {
type args struct {
ts int64
}
tests := []struct {
name string
args args
want time.Time
}{
{
"valid ts",
args{1645054781942979},
time.Unix(1645054781, 942979000),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Int2Time(tt.args.ts); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Int2Time() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 6e1b3f6

Please sign in to comment.