Unpadded dates.

This commit is contained in:
Nuno Cruces 2022-03-29 14:09:01 +01:00
parent 198d2504fe
commit ef114d19a8
2 changed files with 128 additions and 113 deletions

View File

@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/ncruces/zenity" "github.com/ncruces/zenity"
"go.uber.org/goleak"
) )
func ExampleCalendar() { func ExampleCalendar() {
@ -17,21 +18,28 @@ func ExampleCalendar() {
} }
func TestCalendarTimeout(t *testing.T) { func TestCalendarTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second/10) defer goleak.VerifyNone(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Second/5)
defer cancel()
_, err := zenity.Calendar("", zenity.Context(ctx)) _, err := zenity.Calendar("", zenity.Context(ctx))
if skip, err := skip(err); skip {
t.Skip("skipping:", err)
}
if !os.IsTimeout(err) { if !os.IsTimeout(err) {
t.Error("did not timeout:", err) t.Error("did not timeout:", err)
} }
cancel()
} }
func TestCalendarCancel(t *testing.T) { func TestCalendarCancel(t *testing.T) {
defer goleak.VerifyNone(t)
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
cancel() cancel()
_, err := zenity.Calendar("", zenity.Context(ctx)) _, err := zenity.Calendar("", zenity.Context(ctx))
if skip, err := skip(err); skip {
t.Skip("skipping:", err)
}
if !errors.Is(err, context.Canceled) { if !errors.Is(err, context.Canceled) {
t.Error("was not canceled:", err) t.Error("was not canceled:", err)
} }

View File

@ -2,8 +2,10 @@ package zenutil
import "strings" import "strings"
// Strftime is internal.
func Strftime(fmt string) string {
// https://strftime.org/ // https://strftime.org/
var strftimeTable = map[byte]string{ return strftime(fmt, map[byte]string{
'B': "January", 'B': "January",
'b': "Jan", 'b': "Jan",
'h': "Jan", 'h': "Jan",
@ -24,8 +26,9 @@ var strftimeTable = map[byte]string{
'z': "-0700", 'z': "-0700",
'L': "000", 'L': "000",
'f': "000000", 'f': "000000",
'N': "000000000",
'+': "Mon Jan _2 03:04:05 PM MST 2006", '+': "Mon Jan _2 15:04:05 MST 2006",
'c': "Mon Jan _2 15:04:05 2006", 'c': "Mon Jan _2 15:04:05 2006",
'F': "2006-01-02", 'F': "2006-01-02",
'D': "01/02/06", 'D': "01/02/06",
@ -38,45 +41,19 @@ var strftimeTable = map[byte]string{
'%': "%", '%': "%",
't': "\t", 't': "\t",
'n': LineBreak, 'n': LineBreak,
}, map[byte]string{
'm': "1",
'd': "2",
'I': "3",
'M': "4",
'S': "5",
})
} }
// Strftime is internal. // StrftimeUTS35 is internal.
func Strftime(fmt string) string { func StrftimeUTS35(fmt string) string {
var res strings.Builder
res.Grow(len(fmt))
const (
initial = iota
special
)
state := initial
for _, b := range []byte(fmt) {
switch state {
case initial:
if b == '%' {
state = special
} else {
res.WriteByte(b)
state = initial
}
case special:
s, ok := strftimeTable[b]
if ok {
res.WriteString(s)
} else {
res.WriteByte(b)
}
state = initial
}
}
return res.String()
}
// https://nsdateformatter.com/ // https://nsdateformatter.com/
var strftimeUTS35Table = map[byte]string{ return strftime(fmt, map[byte]string{
'B': "MMMM", 'B': "MMMM",
'b': "MMM", 'b': "MMM",
'h': "MMM", 'h': "MMM",
@ -99,8 +76,9 @@ var strftimeUTS35Table = map[byte]string{
'z': "Z", 'z': "Z",
'L': "SSS", 'L': "SSS",
'f': "SSSSSS", 'f': "SSSSSS",
'N': "SSSSSSSSS",
'+': "E MMM d hh:mm:ss a zzz yyyy", '+': "E MMM d HH:mm:ss zzz yyyy",
'c': "E MMM d HH:mm:ss yyyy", 'c': "E MMM d HH:mm:ss yyyy",
'F': "yyyy-MM-dd", 'F': "yyyy-MM-dd",
'D': "MM/dd/yy", 'D': "MM/dd/yy",
@ -113,16 +91,25 @@ var strftimeUTS35Table = map[byte]string{
'%': "%", '%': "%",
't': "\t", 't': "\t",
'n': LineBreak, 'n': LineBreak,
}, map[byte]string{
'm': "M",
'd': "d",
'j': "D",
'H': "H",
'I': "h",
'M': "m",
'S': "s",
})
} }
// StrftimeUTS35 is internal. func strftime(fmt string, formats, unpadded map[byte]string) string {
func StrftimeUTS35(fmt string) string {
var res strings.Builder var res strings.Builder
res.Grow(len(fmt)) res.Grow(len(fmt))
const ( const (
initial = iota initial = iota
special special
padding
) )
state := initial state := initial
@ -133,19 +120,39 @@ func StrftimeUTS35(fmt string) string {
state = special state = special
} else { } else {
res.WriteByte(b) res.WriteByte(b)
state = initial
} }
case special: case special:
s, ok := strftimeUTS35Table[b] if b == '-' {
if ok { state = padding
continue
}
if s, ok := formats[b]; ok {
res.WriteString(s) res.WriteString(s)
} else { } else {
res.WriteByte('%')
res.WriteByte(b)
}
state = initial
case padding:
if s, ok := unpadded[b]; ok {
res.WriteString(s)
} else if s, ok := formats[b]; ok {
res.WriteString(s)
} else {
res.WriteString("%-")
res.WriteByte(b) res.WriteByte(b)
} }
state = initial state = initial
} }
} }
switch state {
case padding:
res.WriteString("%-")
case special:
res.WriteByte('%')
}
return res.String() return res.String()
} }