diff --git a/internal/strftime/strftime.go b/internal/strftime/strftime.go index b0ddeb9..6df9c7f 100644 --- a/internal/strftime/strftime.go +++ b/internal/strftime/strftime.go @@ -63,7 +63,11 @@ func Format(fmt string, t time.Time) string { res.WriteString(strconv.Itoa(w)) } case 'k': - res.WriteString(strconv.Itoa(t.Hour())) + h := t.Hour() + if h < 10 { + res.WriteByte(' ') + } + res.WriteString(strconv.Itoa(h)) case 'l': h := t.Hour() if h == 0 { @@ -71,7 +75,12 @@ func Format(fmt string, t time.Time) string { } else if h > 12 { h -= 12 } + if h < 10 { + res.WriteByte(' ') + } res.WriteString(strconv.Itoa(h)) + case 's': + res.WriteString(strconv.FormatInt(t.Unix(), 10)) } return nil } diff --git a/internal/strftime/strftime_test.go b/internal/strftime/strftime_test.go index adde4c3..4dd85e6 100644 --- a/internal/strftime/strftime_test.go +++ b/internal/strftime/strftime_test.go @@ -149,8 +149,8 @@ func TestFormat_ruby(t *testing.T) { } func TestFormat_tebeka(t *testing.T) { - // https://github.com/tebeka/strftime - // https://github.com/hhkbp2/go-strftime + // github.com/tebeka/strftime + // github.com/hhkbp2/go-strftime reference := time.Date(2009, time.November, 10, 23, 1, 2, 3, time.UTC) tests := []struct { format string @@ -201,8 +201,112 @@ func TestFormat_tebeka(t *testing.T) { } } +func TestFormat_fastly(t *testing.T) { + // github.com/fastly/go-utils/strftime + timezone, err := time.LoadLocation("MST") + if err != nil { + t.Skip("could not load timezone:", err) + } + + reference := time.Unix(1136239445, 0).In(timezone) + + tests := []struct { + format string + time string + }{ + {"", ``}, + + // invalid formats + {"%", `%`}, + {"%^", `%^`}, + {"%^ ", `%^ `}, + {"%^ x", `%^ x`}, + {"x%^ x", `x%^ x`}, + + // supported locale-invariant formats + {"%a", `Mon`}, + {"%A", `Monday`}, + {"%b", `Jan`}, + {"%B", `January`}, + {"%C", `20`}, + {"%d", `02`}, + {"%D", `01/02/06`}, + {"%e", ` 2`}, + {"%F", `2006-01-02`}, + {"%G", `2006`}, + {"%g", `06`}, + {"%h", `Jan`}, + {"%H", `15`}, + {"%I", `03`}, + {"%j", `002`}, + {"%k", `15`}, + {"%l", ` 3`}, + {"%m", `01`}, + {"%M", `04`}, + {"%n", "\n"}, + {"%p", `PM`}, + {"%r", `03:04:05 PM`}, + {"%R", `15:04`}, + {"%s", `1136239445`}, + {"%S", `05`}, + {"%t", "\t"}, + {"%T", `15:04:05`}, + {"%u", `1`}, + {"%U", `01`}, + {"%V", `01`}, + {"%w", `1`}, + {"%W", `01`}, + {"%x", `01/02/06`}, + {"%X", `15:04:05`}, + {"%y", `06`}, + {"%Y", `2006`}, + {"%z", `-0700`}, + {"%Z", `MST`}, + {"%%", `%`}, + + // supported locale-varying formats + {"%c", `Mon Jan 2 15:04:05 2006`}, + {"%E", `%E`}, + {"%EF", `%EF`}, + {"%O", `%O`}, + {"%OF", `%OF`}, + {"%P", `pm`}, + {"%+", `Mon Jan 2 15:04:05 MST 2006`}, + { + "%a|%A|%b|%B|%c|%C|%d|%D|%e|%E|%EF|%F|%G|%g|%h|%H|%I|%j|%k|%l|%m|%M|%O|%OF|%p|%P|%r|%R|%s|%S|%t|%T|%u|%U|%V|%w|%W|%x|%X|%y|%Y|%z|%Z|%%", + `Mon|Monday|Jan|January|Mon Jan 2 15:04:05 2006|20|02|01/02/06| 2|%E|%EF|2006-01-02|2006|06|Jan|15|03|002|15| 3|01|04|%O|%OF|PM|pm|03:04:05 PM|15:04|1136239445|05| |15:04:05|1|01|01|1|01|01/02/06|15:04:05|06|2006|-0700|MST|%`, + }, + } + + for _, test := range tests { + if got := Format(test.format, reference); got != test.time { + t.Errorf("Format(%q) = %q, want %q", test.format, got, test.time) + } + } +} + +func TestFormat_jehiah(t *testing.T) { + // github.com/jehiah/go-strftime + reference := time.Unix(1340244776, 0).UTC() + tests := []struct { + format string + time string + }{ + {"%Y-%m-%d %H:%M:%S", "2012-06-21 02:12:56"}, + {"aaabbb0123456789%Y", "aaabbb01234567892012"}, + {"%H:%M:%S.%L", "02:12:56.000"}, // jehiah disagrees with Ruby on this one + {"%0%1%%%2", "%0%1%%2"}, + } + + for _, test := range tests { + if got := Format(test.format, reference); got != test.time { + t.Errorf("Format(%q) = %q, want %q", test.format, got, test.time) + } + } +} + func TestFormat_lestrrat(t *testing.T) { - // https://github.com/lestrrat-go/strftime + // github.com/lestrrat-go/strftime reference := time.Unix(1136239445, 123456789).UTC() tests := []struct { format string