Date formatting.
This commit is contained in:
parent
ef114d19a8
commit
681f5703ca
4 changed files with 84 additions and 25 deletions
|
@ -522,7 +522,7 @@ func lstResult(l []string, err error) {
|
||||||
|
|
||||||
func calResult(d time.Time, err error) {
|
func calResult(d time.Time, err error) {
|
||||||
errResult(err)
|
errResult(err)
|
||||||
os.Stdout.WriteString(d.Format(zenutil.Strftime(zenutil.DateFormat)))
|
os.Stdout.WriteString(zenutil.Strftime(zenutil.DateFormat, d))
|
||||||
os.Stdout.WriteString(zenutil.LineBreak)
|
os.Stdout.WriteString(zenutil.LineBreak)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,5 +27,6 @@ func calendar(text string, opts options) (time.Time, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, err
|
||||||
}
|
}
|
||||||
return time.Parse(zenutil.Strftime(zenutil.DateFormat), str)
|
layout := zenutil.StrftimeLayout(zenutil.DateFormat)
|
||||||
|
return time.Parse(layout, str)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,5 +27,6 @@ func calendar(text string, opts options) (time.Time, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, err
|
||||||
}
|
}
|
||||||
return time.Parse(zenutil.Strftime(zenutil.DateFormat), str)
|
layout := zenutil.StrftimeLayout(zenutil.DateFormat)
|
||||||
|
return time.Parse(layout, str)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,31 @@
|
||||||
package zenutil
|
package zenutil
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// Strftime is internal.
|
// Strftime is internal.
|
||||||
func Strftime(fmt string) string {
|
func Strftime(fmt string, t time.Time) string {
|
||||||
|
var res strings.Builder
|
||||||
|
writeLit := res.WriteByte
|
||||||
|
writeFmt := func(fmt string) (int, error) {
|
||||||
|
return res.WriteString(t.Format(fmt))
|
||||||
|
}
|
||||||
|
strftimeGo(fmt, writeLit, writeFmt)
|
||||||
|
return res.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrftimeLayout is internal.
|
||||||
|
func StrftimeLayout(fmt string) string {
|
||||||
|
var res strings.Builder
|
||||||
|
strftimeGo(fmt, res.WriteByte, res.WriteString)
|
||||||
|
return res.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func strftimeGo(fmt string, writeLit func(byte) error, writeFmt func(string) (int, error)) {
|
||||||
// https://strftime.org/
|
// https://strftime.org/
|
||||||
return strftime(fmt, map[byte]string{
|
fmts := map[byte]string{
|
||||||
'B': "January",
|
'B': "January",
|
||||||
'b': "Jan",
|
'b': "Jan",
|
||||||
'h': "Jan",
|
'h': "Jan",
|
||||||
|
@ -41,19 +61,23 @@ func Strftime(fmt string) string {
|
||||||
'%': "%",
|
'%': "%",
|
||||||
't': "\t",
|
't': "\t",
|
||||||
'n': LineBreak,
|
'n': LineBreak,
|
||||||
}, map[byte]string{
|
}
|
||||||
|
|
||||||
|
unpaded := map[byte]string{
|
||||||
'm': "1",
|
'm': "1",
|
||||||
'd': "2",
|
'd': "2",
|
||||||
'I': "3",
|
'I': "3",
|
||||||
'M': "4",
|
'M': "4",
|
||||||
'S': "5",
|
'S': "5",
|
||||||
})
|
}
|
||||||
|
|
||||||
|
parser(fmt, fmts, unpaded, writeLit, writeFmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StrftimeUTS35 is internal.
|
// StrftimeUTS35 is internal.
|
||||||
func StrftimeUTS35(fmt string) string {
|
func StrftimeUTS35(fmt string) string {
|
||||||
// https://nsdateformatter.com/
|
// https://nsdateformatter.com/
|
||||||
return strftime(fmt, map[byte]string{
|
fmts := map[byte]string{
|
||||||
'B': "MMMM",
|
'B': "MMMM",
|
||||||
'b': "MMM",
|
'b': "MMM",
|
||||||
'h': "MMM",
|
'h': "MMM",
|
||||||
|
@ -91,7 +115,9 @@ func StrftimeUTS35(fmt string) string {
|
||||||
'%': "%",
|
'%': "%",
|
||||||
't': "\t",
|
't': "\t",
|
||||||
'n': LineBreak,
|
'n': LineBreak,
|
||||||
}, map[byte]string{
|
}
|
||||||
|
|
||||||
|
unpaded := map[byte]string{
|
||||||
'm': "M",
|
'm': "M",
|
||||||
'd': "d",
|
'd': "d",
|
||||||
'j': "D",
|
'j': "D",
|
||||||
|
@ -99,12 +125,42 @@ func StrftimeUTS35(fmt string) string {
|
||||||
'I': "h",
|
'I': "h",
|
||||||
'M': "m",
|
'M': "m",
|
||||||
'S': "s",
|
'S': "s",
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func strftime(fmt string, formats, unpadded map[byte]string) string {
|
const quote = '\''
|
||||||
|
var literal bool
|
||||||
var res strings.Builder
|
var res strings.Builder
|
||||||
res.Grow(len(fmt))
|
|
||||||
|
writeLit := func(b byte) error {
|
||||||
|
if b == quote {
|
||||||
|
res.WriteByte(quote)
|
||||||
|
return res.WriteByte(quote)
|
||||||
|
}
|
||||||
|
if !literal && ('a' <= b && b <= 'z' || 'A' <= b && b <= 'Z') {
|
||||||
|
literal = true
|
||||||
|
res.WriteByte(quote)
|
||||||
|
}
|
||||||
|
return res.WriteByte(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFmt := func(s string) (int, error) {
|
||||||
|
if literal {
|
||||||
|
literal = false
|
||||||
|
res.WriteByte(quote)
|
||||||
|
}
|
||||||
|
return res.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
parser(fmt, fmts, unpaded, writeLit, writeFmt)
|
||||||
|
writeFmt("")
|
||||||
|
|
||||||
|
return res.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func parser(
|
||||||
|
fmt string,
|
||||||
|
formats, unpadded map[byte]string,
|
||||||
|
writeLit func(byte) error, writeFmt func(string) (int, error)) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
initial = iota
|
initial = iota
|
||||||
|
@ -119,7 +175,7 @@ func strftime(fmt string, formats, unpadded map[byte]string) string {
|
||||||
if b == '%' {
|
if b == '%' {
|
||||||
state = special
|
state = special
|
||||||
} else {
|
} else {
|
||||||
res.WriteByte(b)
|
writeLit(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
case special:
|
case special:
|
||||||
|
@ -128,21 +184,22 @@ func strftime(fmt string, formats, unpadded map[byte]string) string {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if s, ok := formats[b]; ok {
|
if s, ok := formats[b]; ok {
|
||||||
res.WriteString(s)
|
writeFmt(s)
|
||||||
} else {
|
} else {
|
||||||
res.WriteByte('%')
|
writeLit('%')
|
||||||
res.WriteByte(b)
|
writeLit(b)
|
||||||
}
|
}
|
||||||
state = initial
|
state = initial
|
||||||
|
|
||||||
case padding:
|
case padding:
|
||||||
if s, ok := unpadded[b]; ok {
|
if s, ok := unpadded[b]; ok {
|
||||||
res.WriteString(s)
|
writeFmt(s)
|
||||||
} else if s, ok := formats[b]; ok {
|
} else if s, ok := formats[b]; ok {
|
||||||
res.WriteString(s)
|
writeFmt(s)
|
||||||
} else {
|
} else {
|
||||||
res.WriteString("%-")
|
writeLit('%')
|
||||||
res.WriteByte(b)
|
writeLit('-')
|
||||||
|
writeLit(b)
|
||||||
}
|
}
|
||||||
state = initial
|
state = initial
|
||||||
}
|
}
|
||||||
|
@ -150,9 +207,9 @@ func strftime(fmt string, formats, unpadded map[byte]string) string {
|
||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
case padding:
|
case padding:
|
||||||
res.WriteString("%-")
|
writeLit('%')
|
||||||
|
fallthrough
|
||||||
case special:
|
case special:
|
||||||
res.WriteByte('%')
|
writeLit('-')
|
||||||
}
|
}
|
||||||
return res.String()
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue