Skip to content

Commit

Permalink
standard formatting of time 2a
Browse files Browse the repository at this point in the history
  • Loading branch information
pascaldekloe committed Jul 26, 2024
1 parent a022106 commit f6903ac
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 80 deletions.
68 changes: 68 additions & 0 deletions info/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,71 @@ func (u DataUnit[Orig, Com, Obj]) Format(f fmt.State, verb rune) {
// OK
io.WriteString(f, " .")
}

// Format implements the fmt.Formatter interface. String formatting with "%s"
// gets the incomplete time as ":<MM>:<SS>.<mmm>". Invalid times get the ",IV"
// suffix. Precision "%.1s" includes Reserve1 as suffix ",RES1=<0|1>".
func (t2a CP24Time2a) Format(f fmt.State, verb rune) {
if verb != 's' {
fmt.Fprintf(f, "%%!%c(BADVERB)", verb)
return
}

min, secInMilli := t2a.MinuteAndMillis()
sec := secInMilli / 1000
millis := secInMilli % 1000
fmt.Fprintf(f, ":%02d:%02d.%03d", min, sec, millis)

if t2a.Invalid() {
io.WriteString(f, ",IV")
}

if n, ok := f.Precision(); ok && n != 0 {
if n > 0 {
if t2a.Reserve1() {
io.WriteString(f, ",RES1=1")
} else {
io.WriteString(f, ",RES1=0")
}
}
}
}

// Format implements the fmt.Formatter interface. String formatting with "%s"
// gets the date–time in the ISO extended-format. Invalid times get the ",IV"
// suffix. Precision "%.1s" includes Reserve1 as suffix ",RES1=<0|1>", "%.2s"
// additionally adds Reserve2 as ",RES2=<0|1><0|1>", and "%.3s" additionally
// adds Reserve3 as ",RES3=<0|1><0|1><0|1><0|1>".
func (t2a CP56Time2a) Format(f fmt.State, verb rune) {
if verb != 's' {
fmt.Fprintf(f, "%%!%c(BADVERB)", verb)
return
}

year, month, day := t2a.Calendar()
hour, min, secInMilli := t2a.ClockAndMillis()
sec := secInMilli / 1000
millis := secInMilli % 1000
fmt.Fprintf(f, "%02d-%02d-%02dT%02d:%02d:%02d.%03d",
year, month, day, hour, min, sec, millis)

if t2a.Invalid() {
io.WriteString(f, ",IV")
}

if n, ok := f.Precision(); ok && n != 0 {
if n > 0 {
if t2a.Reserve1() {
io.WriteString(f, ",RES1=1")
} else {
io.WriteString(f, ",RES1=0")
}
}
if n > 1 {
fmt.Fprintf(f, ",RES2=%02b", t2a.Reserve2())
}
if n > 2 {
fmt.Fprintf(f, ",RES3=%04b", t2a.Reserve3())
}
}
}
95 changes: 92 additions & 3 deletions info/format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"fmt"
"strings"
"testing"
"time"
)

var goldenFormats = []struct {
var goldenAddrFormats = []struct {
value any
format string
want string
Expand Down Expand Up @@ -37,8 +38,8 @@ var goldenFormats = []struct {
{ObjAddr24{0xa, 0xb, 0xc}, "%#X", "0C:0B:0A"},
}

func TestGoldenFormats(t *testing.T) {
for _, gold := range goldenFormats {
func TestGoldenAddrFormats(t *testing.T) {
for _, gold := range goldenAddrFormats {
got := fmt.Sprintf(gold.format, gold.value)
if got != gold.want {
t.Errorf("%q of %T got %q, want %q",
Expand Down Expand Up @@ -82,3 +83,91 @@ func FuzzDataUnitFormat(f *testing.F) {
}
})
}

func TestCP24Time2aFormat(t *testing.T) {
// timezone should be ignored
timestamp := time.Date(2006, 01, 02, 15, 04, 05, 987000000, time.Local)

want := func(t *testing.T, t2a CP24Time2a, format, want string) {
t.Helper()
got := fmt.Sprintf(format, t2a)
if got != want {
t.Errorf("got %q, want %q", got, want)
}
}

t.Run("Plain", func(t *testing.T) {
var t2a CP24Time2a
t2a.Set(timestamp)
want(t, t2a, "%s", ":04:05.987")
})

t.Run("Invalid", func(t *testing.T) {
var t2a CP24Time2a
t2a.Set(timestamp)
t2a[2] |= 0x80 // invalid
want(t, t2a, "%s", ":04:05.987,IV")
})

t.Run("NoRES1", func(t *testing.T) {
var t2a CP24Time2a
t2a.Set(timestamp)
want(t, t2a, "%.1s", ":04:05.987,RES1=0")
})

t.Run("InvalidAndRES1", func(t *testing.T) {
var t2a CP24Time2a
t2a.Set(timestamp)
t2a[2] |= 0x80 // invalid
t2a.FlagReserve1()
want(t, t2a, "%.1s", ":04:05.987,IV,RES1=1")
})
}

func TestCP56Time2aFormat(t *testing.T) {
// timezone should be ignored
timestamp := time.Date(2006, 01, 02, 15, 04, 05, 987000000, time.Local)

want := func(t *testing.T, t2a CP56Time2a, format, want string) {
t.Helper()
got := fmt.Sprintf(format, t2a)
if got != want {
t.Errorf("got %q, want %q", got, want)
}
}

t.Run("Plain", func(t *testing.T) {
var t2a CP56Time2a
t2a.Set(timestamp)
want(t, t2a, "%s", "06-01-02T15:04:05.987")
want(t, t2a, "%.0s", "06-01-02T15:04:05.987")
want(t, t2a, "%.0s", "06-01-02T15:04:05.987")
want(t, t2a, "%.0s", "06-01-02T15:04:05.987")
want(t, t2a, "%.1s", "06-01-02T15:04:05.987,RES1=0")
want(t, t2a, "%.2s", "06-01-02T15:04:05.987,RES1=0,RES2=00")
want(t, t2a, "%.3s", "06-01-02T15:04:05.987,RES1=0,RES2=00,RES3=0000")
want(t, t2a, "%.4s", "06-01-02T15:04:05.987,RES1=0,RES2=00,RES3=0000")
})

t.Run("Reserves", func(t *testing.T) {
var t2a CP56Time2a
t2a.Set(timestamp)
t2a.FlagReserve1()
t2a.FlagReserve2(2)
t2a.FlagReserve3(5)
want(t, t2a, "%s", "06-01-02T15:04:05.987")
want(t, t2a, "%.1s", "06-01-02T15:04:05.987,RES1=1")
want(t, t2a, "%.2s", "06-01-02T15:04:05.987,RES1=1,RES2=10")
want(t, t2a, "%.3s", "06-01-02T15:04:05.987,RES1=1,RES2=10,RES3=0101")
})

t.Run("Invalid", func(t *testing.T) {
var t2a CP56Time2a
t2a.Set(timestamp)
t2a.FlagReserve2(1)
t2a.FlagReserve3(10)
t2a[2] |= 0x80 // invalid
want(t, t2a, "%s", "06-01-02T15:04:05.987,IV")
want(t, t2a, "%.3s", "06-01-02T15:04:05.987,IV,RES1=0,RES2=01,RES3=1010")
})
}
119 changes: 42 additions & 77 deletions monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,79 +109,59 @@ func (l logger[Orig, Com, Obj]) SinglePt(u info.DataUnit[Orig, Com, Obj], addr O
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual())
}

func (l logger[Orig, Com, Obj]) SinglePtAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.SinglePtQual, t info.CP24Time2a) {
min, secInMilli := t.MinuteAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s :%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(),
min, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) SinglePtAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.SinglePtQual, tag info.CP24Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) SinglePtAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.SinglePtQual, t info.CP56Time2a) {
y, m, d := t.Calendar()
H, M, secInMilli := t.ClockAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %02d-%02d-%02dT%02d:%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(),
y, m, d, H, M, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) SinglePtAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.SinglePtQual, tag info.CP56Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) DoublePt(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.DoublePtQual) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual())
}

func (l logger[Orig, Com, Obj]) DoublePtAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.DoublePtQual, t info.CP24Time2a) {
min, secInMilli := t.MinuteAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s :%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(),
min, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) DoublePtAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.DoublePtQual, tag info.CP24Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) DoublePtAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.DoublePtQual, t info.CP56Time2a) {
y, m, d := t.Calendar()
H, M, secInMilli := t.ClockAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %02d-%02d-%02dT%02d:%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(),
y, m, d, H, M, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) DoublePtAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.DoublePtQual, tag info.CP56Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) Step(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.StepQual) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual())
}

func (l logger[Orig, Com, Obj]) StepAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.StepQual, t info.CP24Time2a) {
min, secInMilli := t.MinuteAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s :%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(),
min, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) StepAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.StepQual, tag info.CP24Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) StepAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.StepQual, t info.CP56Time2a) {
y, m, d := t.Calendar()
H, M, secInMilli := t.ClockAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %02d-%02d-%02dT%02d:%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(),
y, m, d, H, M, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) StepAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, p info.StepQual, tag info.CP56Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %s %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, p.Value(), p.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) Bits(u info.DataUnit[Orig, Com, Obj], addr Obj, b info.BitsQual) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %#x %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, b.Array(), b.Qual())
}

func (l logger[Orig, Com, Obj]) BitsAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, b info.BitsQual, t info.CP24Time2a) {
min, secInMilli := t.MinuteAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %#x %s :%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, b.Array(), b.Qual(),
min, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) BitsAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, b info.BitsQual, tag info.CP24Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %#x %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, b.Array(), b.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) BitsAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, b info.BitsQual, t info.CP56Time2a) {
y, m, d := t.Calendar()
H, M, secInMilli := t.ClockAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %#x %s %02d-%02d-%02dT%02d:%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, b.Array(), b.Qual(),
y, m, d, H, M, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) BitsAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, b info.BitsQual, tag info.CP56Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %#x %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, b.Array(), b.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) NormUnqual(u info.DataUnit[Orig, Com, Obj], addr Obj, n info.Norm) {
Expand All @@ -194,59 +174,44 @@ func (l logger[Orig, Com, Obj]) Norm(u info.DataUnit[Orig, Com, Obj], addr Obj,
u.Type, u.Cause, u.Orig, u.Addr, addr, n.Link().Float64(), n.Qual())
}

func (l logger[Orig, Com, Obj]) NormAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, n info.NormQual, t info.CP24Time2a) {
min, secInMilli := t.MinuteAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %f %s :%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, n.Link().Float64(), n.Qual(),
min, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) NormAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, n info.NormQual, tag info.CP24Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %f %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, n.Link().Float64(), n.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) NormAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, n info.NormQual, t info.CP56Time2a) {
y, m, d := t.Calendar()
H, M, secInMilli := t.ClockAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %f %s %02d-%02d-%02dT%02d:%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, n.Link().Float64(), n.Qual(),
y, m, d, H, M, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) NormAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, n info.NormQual, tag info.CP56Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %f %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, n.Link().Float64(), n.Qual(), tag)
}

func (l logger[Orig, Com, Obj]) Scaled(u info.DataUnit[Orig, Com, Obj], addr Obj, v int16, q info.Qual) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %d %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, v, q)
}

func (l logger[Orig, Com, Obj]) ScaledAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, v int16, q info.Qual, t info.CP24Time2a) {
min, secInMilli := t.MinuteAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %d %s :%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, v, q,
min, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) ScaledAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, v int16, q info.Qual, tag info.CP24Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %d %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, v, q, tag)
}

func (l logger[Orig, Com, Obj]) ScaledAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, v int16, q info.Qual, t info.CP56Time2a) {
y, m, d := t.Calendar()
H, M, secInMilli := t.ClockAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %d %s %02d-%02d-%02dT%02d:%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, v, q,
y, m, d, H, M, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) ScaledAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, v int16, q info.Qual, tag info.CP56Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %d %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, v, q, tag)
}

func (l logger[Orig, Com, Obj]) Float(u info.DataUnit[Orig, Com, Obj], addr Obj, f float32, q info.Qual) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %g %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, f, q)
}

func (l logger[Orig, Com, Obj]) FloatAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, f float32, q info.Qual, t info.CP24Time2a) {
min, secInMilli := t.MinuteAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %g %s :%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, f, q,
min, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) FloatAtMinute(u info.DataUnit[Orig, Com, Obj], addr Obj, f float32, q info.Qual, tag info.CP24Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %g %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, f, q, tag)
}

func (l logger[Orig, Com, Obj]) FloatAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, f float32, q info.Qual, t info.CP56Time2a) {
y, m, d := t.Calendar()
H, M, secInMilli := t.ClockAndMillis()
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %g %s %02d-%02d-%02dT%02d:%02d:%02d.%03d\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, f, q,
y, m, d, H, M, secInMilli/1000, secInMilli%1000)
func (l logger[Orig, Com, Obj]) FloatAtMoment(u info.DataUnit[Orig, Com, Obj], addr Obj, f float32, q info.Qual, tag info.CP56Time2a) {
fmt.Fprintf(l.W, "%s %s %x %#x/%#x %g %s %s\n",
u.Type, u.Cause, u.Orig, u.Addr, addr, f, q, tag)
}

// ErrNotMonitor rejects an info.DataUnit based on its type identifier.
Expand Down

0 comments on commit f6903ac

Please sign in to comment.