Date formatting.
This commit is contained in:
parent
f21574baa6
commit
0086cdcbf0
11 changed files with 337 additions and 228 deletions
|
@ -18,7 +18,7 @@ go run github.com/randall77/makefat zenity zenity_macos_x64 zenity_macos_arm &&
|
||||||
zip -9 zenity_macos.zip zenity
|
zip -9 zenity_macos.zip zenity
|
||||||
|
|
||||||
zip -9 zenity_brew.zip zenity zenity.exe
|
zip -9 zenity_brew.zip zenity zenity.exe
|
||||||
|
|
||||||
rm zenity zenity_macos_* zenity.exe
|
rm zenity zenity_macos_* zenity.exe
|
||||||
|
|
||||||
|
GOOS=linux go build -tags dev
|
||||||
go build -tags dev
|
go build -tags dev
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ncruces/zenity"
|
"github.com/ncruces/zenity"
|
||||||
|
"github.com/ncruces/zenity/internal/strftime"
|
||||||
"github.com/ncruces/zenity/internal/zenutil"
|
"github.com/ncruces/zenity/internal/zenutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -522,7 +523,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(zenutil.Strftime(zenutil.DateFormat, d))
|
os.Stdout.WriteString(strftime.Format(zenutil.DateFormat, d))
|
||||||
os.Stdout.WriteString(zenutil.LineBreak)
|
os.Stdout.WriteString(zenutil.LineBreak)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,21 @@ package zenity
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ncruces/zenity/internal/strftime"
|
||||||
"github.com/ncruces/zenity/internal/zenutil"
|
"github.com/ncruces/zenity/internal/zenutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func calendar(text string, opts options) (time.Time, error) {
|
func calendar(text string, opts options) (t time.Time, err error) {
|
||||||
var date zenutil.Date
|
var date zenutil.Date
|
||||||
|
|
||||||
date.OK, date.Cancel, date.Extra = getAlertButtons(opts)
|
date.OK, date.Cancel, date.Extra = getAlertButtons(opts)
|
||||||
date.Format = zenutil.StrftimeUTS35(zenutil.DateFormat)
|
date.Format, err = strftime.UTS35(zenutil.DateFormat)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if opts.time != nil {
|
if opts.time != nil {
|
||||||
date.Date = opts.time.Unix()
|
unix := opts.time.Unix()
|
||||||
|
date.Date = &unix
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.title != nil {
|
if opts.title != nil {
|
||||||
|
@ -25,8 +30,7 @@ func calendar(text string, opts options) (time.Time, error) {
|
||||||
out, err := zenutil.Run(opts.ctx, "date", date)
|
out, err := zenutil.Run(opts.ctx, "date", date)
|
||||||
str, err := strResult(opts, out, err)
|
str, err := strResult(opts, out, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
return
|
||||||
}
|
}
|
||||||
layout := zenutil.StrftimeLayout(zenutil.DateFormat)
|
return strftime.Parse(zenutil.DateFormat, str)
|
||||||
return time.Parse(layout, str)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ncruces/zenity/internal/strftime"
|
||||||
"github.com/ncruces/zenity/internal/zenutil"
|
"github.com/ncruces/zenity/internal/zenutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +28,5 @@ func calendar(text string, opts options) (time.Time, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, err
|
||||||
}
|
}
|
||||||
layout := zenutil.StrftimeLayout(zenutil.DateFormat)
|
return strftime.Parse(zenutil.DateFormat, str)
|
||||||
return time.Parse(layout, str)
|
|
||||||
}
|
}
|
||||||
|
|
65
internal/strftime/parser.go
Normal file
65
internal/strftime/parser.go
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package strftime
|
||||||
|
|
||||||
|
type parser struct {
|
||||||
|
fmt string
|
||||||
|
specs map[byte]string
|
||||||
|
unpadded map[byte]string
|
||||||
|
writeLit func(byte) error
|
||||||
|
writeFmt func(string) error
|
||||||
|
fallback func(spec byte, pad bool) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) parse() error {
|
||||||
|
const (
|
||||||
|
initial = iota
|
||||||
|
specifier
|
||||||
|
nopadding
|
||||||
|
)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
state := initial
|
||||||
|
for _, b := range []byte(p.fmt) {
|
||||||
|
switch state {
|
||||||
|
default:
|
||||||
|
if b == '%' {
|
||||||
|
state = specifier
|
||||||
|
} else {
|
||||||
|
err = p.writeLit(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
case specifier:
|
||||||
|
if b == '-' {
|
||||||
|
state = nopadding
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if s, ok := p.specs[b]; ok {
|
||||||
|
err = p.writeFmt(s)
|
||||||
|
} else {
|
||||||
|
err = p.fallback(b, true)
|
||||||
|
}
|
||||||
|
state = initial
|
||||||
|
|
||||||
|
case nopadding:
|
||||||
|
if s, ok := p.unpadded[b]; ok {
|
||||||
|
err = p.writeFmt(s)
|
||||||
|
} else if s, ok := p.specs[b]; ok {
|
||||||
|
err = p.writeFmt(s)
|
||||||
|
} else {
|
||||||
|
err = p.fallback(b, false)
|
||||||
|
}
|
||||||
|
state = initial
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch state {
|
||||||
|
case specifier:
|
||||||
|
return p.writeLit('%')
|
||||||
|
case nopadding:
|
||||||
|
return p.writeLit('-')
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
102
internal/strftime/specifiers.go
Normal file
102
internal/strftime/specifiers.go
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
package strftime
|
||||||
|
|
||||||
|
func (p *parser) goSpecifiers() {
|
||||||
|
// https://strftime.org/
|
||||||
|
p.specs = map[byte]string{
|
||||||
|
'B': "January",
|
||||||
|
'b': "Jan",
|
||||||
|
'h': "Jan",
|
||||||
|
'm': "01",
|
||||||
|
'A': "Monday",
|
||||||
|
'a': "Mon",
|
||||||
|
'e': "_2",
|
||||||
|
'd': "02",
|
||||||
|
'j': "002",
|
||||||
|
'H': "15",
|
||||||
|
'I': "03",
|
||||||
|
'M': "04",
|
||||||
|
'S': "05",
|
||||||
|
'Y': "2006",
|
||||||
|
'y': "06",
|
||||||
|
'p': "PM",
|
||||||
|
'Z': "MST",
|
||||||
|
'z': "-0700",
|
||||||
|
'L': "000",
|
||||||
|
'f': "000000",
|
||||||
|
'N': "000000000",
|
||||||
|
|
||||||
|
'+': "Mon Jan _2 15:04:05 MST 2006",
|
||||||
|
'c': "Mon Jan _2 15:04:05 2006",
|
||||||
|
'F': "2006-01-02",
|
||||||
|
'D': "01/02/06",
|
||||||
|
'x': "01/02/06",
|
||||||
|
'r': "03:04:05 PM",
|
||||||
|
'T': "15:04:05",
|
||||||
|
'X': "15:04:05",
|
||||||
|
'R': "15:04",
|
||||||
|
|
||||||
|
'%': "%",
|
||||||
|
't': "\t",
|
||||||
|
'n': "\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
p.unpadded = map[byte]string{
|
||||||
|
'm': "1",
|
||||||
|
'd': "2",
|
||||||
|
'I': "3",
|
||||||
|
'M': "4",
|
||||||
|
'S': "5",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) uts35Specifiers() { // https://nsdateformatter.com/
|
||||||
|
p.specs = map[byte]string{
|
||||||
|
'B': "MMMM",
|
||||||
|
'b': "MMM",
|
||||||
|
'h': "MMM",
|
||||||
|
'm': "MM",
|
||||||
|
'A': "EEEE",
|
||||||
|
'a': "E",
|
||||||
|
'd': "dd",
|
||||||
|
'j': "DDD",
|
||||||
|
'H': "HH",
|
||||||
|
'I': "hh",
|
||||||
|
'M': "mm",
|
||||||
|
'S': "ss",
|
||||||
|
'Y': "yyyy",
|
||||||
|
'y': "yy",
|
||||||
|
'G': "YYYY",
|
||||||
|
'g': "YY",
|
||||||
|
'V': "ww",
|
||||||
|
'p': "a",
|
||||||
|
'Z': "zzz",
|
||||||
|
'z': "Z",
|
||||||
|
'L': "SSS",
|
||||||
|
'f': "SSSSSS",
|
||||||
|
'N': "SSSSSSSSS",
|
||||||
|
|
||||||
|
'+': "E MMM d HH:mm:ss zzz yyyy",
|
||||||
|
'c': "E MMM d HH:mm:ss yyyy",
|
||||||
|
'F': "yyyy-MM-dd",
|
||||||
|
'D': "MM/dd/yy",
|
||||||
|
'x': "MM/dd/yy",
|
||||||
|
'r': "hh:mm:ss a",
|
||||||
|
'T': "HH:mm:ss",
|
||||||
|
'X': "HH:mm:ss",
|
||||||
|
'R': "HH:mm",
|
||||||
|
|
||||||
|
'%': "%",
|
||||||
|
't': "\t",
|
||||||
|
'n': "\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
p.unpadded = map[byte]string{
|
||||||
|
'm': "M",
|
||||||
|
'd': "d",
|
||||||
|
'j': "D",
|
||||||
|
'H': "H",
|
||||||
|
'I': "h",
|
||||||
|
'M': "m",
|
||||||
|
'S': "s",
|
||||||
|
}
|
||||||
|
}
|
148
internal/strftime/strftime.go
Normal file
148
internal/strftime/strftime.go
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
package strftime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Format(fmt string, t time.Time) string {
|
||||||
|
var res strings.Builder
|
||||||
|
|
||||||
|
var parser parser
|
||||||
|
parser.fmt = fmt
|
||||||
|
parser.goSpecifiers()
|
||||||
|
|
||||||
|
parser.writeLit = res.WriteByte
|
||||||
|
|
||||||
|
parser.writeFmt = func(fmt string) error {
|
||||||
|
switch fmt {
|
||||||
|
default:
|
||||||
|
res.WriteString(t.Format(fmt))
|
||||||
|
case "000", "000000", "000000000":
|
||||||
|
res.WriteString(t.Format("." + fmt)[1:])
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.fallback = func(spec byte, pad bool) error {
|
||||||
|
switch spec {
|
||||||
|
default:
|
||||||
|
return errors.New("strftime: unsupported specifier: %" + string(spec))
|
||||||
|
case 'C':
|
||||||
|
s := t.Format("2006")
|
||||||
|
res.WriteString(s[:len(s)-2])
|
||||||
|
case 'g':
|
||||||
|
y, _ := t.ISOWeek()
|
||||||
|
res.WriteString(time.Date(y, 1, 1, 0, 0, 0, 0, time.UTC).Format("06"))
|
||||||
|
case 'G':
|
||||||
|
y, _ := t.ISOWeek()
|
||||||
|
res.WriteString(time.Date(y, 1, 1, 0, 0, 0, 0, time.UTC).Format("2006"))
|
||||||
|
case 'V':
|
||||||
|
_, w := t.ISOWeek()
|
||||||
|
if w < 10 && pad {
|
||||||
|
res.WriteByte('0')
|
||||||
|
}
|
||||||
|
res.WriteString(strconv.Itoa(w))
|
||||||
|
case 'w':
|
||||||
|
w := int(t.Weekday())
|
||||||
|
res.WriteString(strconv.Itoa(w))
|
||||||
|
case 'u':
|
||||||
|
if w := int(t.Weekday()); w == 0 {
|
||||||
|
res.WriteByte('7')
|
||||||
|
} else {
|
||||||
|
res.WriteString(strconv.Itoa(w))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.parse()
|
||||||
|
return res.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(fmt, value string) (time.Time, error) {
|
||||||
|
layout, err := Layout(fmt)
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
return time.Parse(layout, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Layout(fmt string) (string, error) {
|
||||||
|
var res strings.Builder
|
||||||
|
|
||||||
|
var parser parser
|
||||||
|
parser.fmt = fmt
|
||||||
|
parser.goSpecifiers()
|
||||||
|
|
||||||
|
parser.writeLit = func(b byte) error {
|
||||||
|
if bytes.IndexByte([]byte("MonJan_0123456789"), b) >= 0 {
|
||||||
|
return errors.New("strftime: unsupported literal: " + string(b))
|
||||||
|
}
|
||||||
|
res.WriteByte(b)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.writeFmt = func(s string) error {
|
||||||
|
res.WriteString(s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.fallback = func(spec byte, pad bool) error {
|
||||||
|
return errors.New("strftime: unsupported specifier: %" + string(spec))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := parser.parse(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.writeFmt("")
|
||||||
|
return res.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UTS35(fmt string) (string, error) {
|
||||||
|
var parser parser
|
||||||
|
parser.fmt = fmt
|
||||||
|
parser.uts35Specifiers()
|
||||||
|
|
||||||
|
const quote = '\''
|
||||||
|
var literal bool
|
||||||
|
var res strings.Builder
|
||||||
|
|
||||||
|
parser.writeLit = func(b byte) error {
|
||||||
|
if b == quote {
|
||||||
|
res.WriteByte(quote)
|
||||||
|
res.WriteByte(quote)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !literal && ('a' <= b && b <= 'z' || 'A' <= b && b <= 'Z') {
|
||||||
|
literal = true
|
||||||
|
res.WriteByte(quote)
|
||||||
|
}
|
||||||
|
res.WriteByte(b)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.writeFmt = func(s string) error {
|
||||||
|
if literal {
|
||||||
|
literal = false
|
||||||
|
res.WriteByte(quote)
|
||||||
|
}
|
||||||
|
res.WriteString(s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.fallback = func(spec byte, pad bool) error {
|
||||||
|
return errors.New("strftime: unsupported specifier: %" + string(spec))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := parser.parse(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.writeFmt("")
|
||||||
|
return res.String(), nil
|
||||||
|
}
|
|
@ -1,215 +0,0 @@
|
||||||
package zenutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Strftime is internal.
|
|
||||||
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/
|
|
||||||
fmts := map[byte]string{
|
|
||||||
'B': "January",
|
|
||||||
'b': "Jan",
|
|
||||||
'h': "Jan",
|
|
||||||
'm': "01",
|
|
||||||
'A': "Monday",
|
|
||||||
'a': "Mon",
|
|
||||||
'e': "_2",
|
|
||||||
'd': "02",
|
|
||||||
'j': "002",
|
|
||||||
'H': "15",
|
|
||||||
'I': "03",
|
|
||||||
'M': "04",
|
|
||||||
'S': "05",
|
|
||||||
'Y': "2006",
|
|
||||||
'y': "06",
|
|
||||||
'p': "PM",
|
|
||||||
'Z': "MST",
|
|
||||||
'z': "-0700",
|
|
||||||
'L': "000",
|
|
||||||
'f': "000000",
|
|
||||||
'N': "000000000",
|
|
||||||
|
|
||||||
'+': "Mon Jan _2 15:04:05 MST 2006",
|
|
||||||
'c': "Mon Jan _2 15:04:05 2006",
|
|
||||||
'F': "2006-01-02",
|
|
||||||
'D': "01/02/06",
|
|
||||||
'x': "01/02/06",
|
|
||||||
'r': "03:04:05 PM",
|
|
||||||
'T': "15:04:05",
|
|
||||||
'X': "15:04:05",
|
|
||||||
'R': "15:04",
|
|
||||||
|
|
||||||
'%': "%",
|
|
||||||
't': "\t",
|
|
||||||
'n': LineBreak,
|
|
||||||
}
|
|
||||||
|
|
||||||
unpaded := map[byte]string{
|
|
||||||
'm': "1",
|
|
||||||
'd': "2",
|
|
||||||
'I': "3",
|
|
||||||
'M': "4",
|
|
||||||
'S': "5",
|
|
||||||
}
|
|
||||||
|
|
||||||
parser(fmt, fmts, unpaded, writeLit, writeFmt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrftimeUTS35 is internal.
|
|
||||||
func StrftimeUTS35(fmt string) string {
|
|
||||||
// https://nsdateformatter.com/
|
|
||||||
fmts := map[byte]string{
|
|
||||||
'B': "MMMM",
|
|
||||||
'b': "MMM",
|
|
||||||
'h': "MMM",
|
|
||||||
'm': "MM",
|
|
||||||
'A': "EEEE",
|
|
||||||
'a': "E",
|
|
||||||
'd': "dd",
|
|
||||||
'j': "DDD",
|
|
||||||
'H': "HH",
|
|
||||||
'I': "hh",
|
|
||||||
'M': "mm",
|
|
||||||
'S': "ss",
|
|
||||||
'Y': "yyyy",
|
|
||||||
'y': "yy",
|
|
||||||
'G': "YYYY",
|
|
||||||
'g': "YY",
|
|
||||||
'V': "ww",
|
|
||||||
'p': "a",
|
|
||||||
'Z': "zzz",
|
|
||||||
'z': "Z",
|
|
||||||
'L': "SSS",
|
|
||||||
'f': "SSSSSS",
|
|
||||||
'N': "SSSSSSSSS",
|
|
||||||
|
|
||||||
'+': "E MMM d HH:mm:ss zzz yyyy",
|
|
||||||
'c': "E MMM d HH:mm:ss yyyy",
|
|
||||||
'F': "yyyy-MM-dd",
|
|
||||||
'D': "MM/dd/yy",
|
|
||||||
'x': "MM/dd/yy",
|
|
||||||
'r': "hh:mm:ss a",
|
|
||||||
'T': "HH:mm:ss",
|
|
||||||
'X': "HH:mm:ss",
|
|
||||||
'R': "HH:mm",
|
|
||||||
|
|
||||||
'%': "%",
|
|
||||||
't': "\t",
|
|
||||||
'n': LineBreak,
|
|
||||||
}
|
|
||||||
|
|
||||||
unpaded := map[byte]string{
|
|
||||||
'm': "M",
|
|
||||||
'd': "d",
|
|
||||||
'j': "D",
|
|
||||||
'H': "H",
|
|
||||||
'I': "h",
|
|
||||||
'M': "m",
|
|
||||||
'S': "s",
|
|
||||||
}
|
|
||||||
|
|
||||||
const quote = '\''
|
|
||||||
var literal bool
|
|
||||||
var res strings.Builder
|
|
||||||
|
|
||||||
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 (
|
|
||||||
initial = iota
|
|
||||||
special
|
|
||||||
padding
|
|
||||||
)
|
|
||||||
|
|
||||||
state := initial
|
|
||||||
for _, b := range []byte(fmt) {
|
|
||||||
switch state {
|
|
||||||
case initial:
|
|
||||||
if b == '%' {
|
|
||||||
state = special
|
|
||||||
} else {
|
|
||||||
writeLit(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
case special:
|
|
||||||
if b == '-' {
|
|
||||||
state = padding
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if s, ok := formats[b]; ok {
|
|
||||||
writeFmt(s)
|
|
||||||
} else {
|
|
||||||
writeLit('%')
|
|
||||||
writeLit(b)
|
|
||||||
}
|
|
||||||
state = initial
|
|
||||||
|
|
||||||
case padding:
|
|
||||||
if s, ok := unpadded[b]; ok {
|
|
||||||
writeFmt(s)
|
|
||||||
} else if s, ok := formats[b]; ok {
|
|
||||||
writeFmt(s)
|
|
||||||
} else {
|
|
||||||
writeLit('%')
|
|
||||||
writeLit('-')
|
|
||||||
writeLit(b)
|
|
||||||
}
|
|
||||||
state = initial
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch state {
|
|
||||||
case padding:
|
|
||||||
writeLit('%')
|
|
||||||
fallthrough
|
|
||||||
case special:
|
|
||||||
writeLit('-')
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,8 +29,10 @@ ObjC.import('stdlib')
|
||||||
var date=$.NSDatePicker.alloc.init
|
var date=$.NSDatePicker.alloc.init
|
||||||
date.setDatePickerStyle($.NSDatePickerStyleClockAndCalendar)
|
date.setDatePickerStyle($.NSDatePickerStyleClockAndCalendar)
|
||||||
date.setDatePickerElements($.NSDatePickerElementFlagYearMonthDay)
|
date.setDatePickerElements($.NSDatePickerElementFlagYearMonthDay)
|
||||||
date.setDateValue($.NSDate.dateWithTimeIntervalSince1970({{.Date}}))
|
|
||||||
date.setFrameSize(date.fittingSize)
|
date.setFrameSize(date.fittingSize)
|
||||||
|
{{- if .Date}}
|
||||||
|
date.setDateValue($.NSDate.dateWithTimeIntervalSince1970({{.Date}}))
|
||||||
|
{{- end}}
|
||||||
var alert=$.NSAlert.alloc.init
|
var alert=$.NSAlert.alloc.init
|
||||||
alert.setAccessoryView(date)
|
alert.setAccessoryView(date)
|
||||||
alert.setMessageText({{json .Text}})
|
alert.setMessageText({{json .Text}})
|
||||||
|
|
|
@ -9,8 +9,10 @@ ObjC.import('stdlib')
|
||||||
var date = $.NSDatePicker.alloc.init
|
var date = $.NSDatePicker.alloc.init
|
||||||
date.setDatePickerStyle($.NSDatePickerStyleClockAndCalendar)
|
date.setDatePickerStyle($.NSDatePickerStyleClockAndCalendar)
|
||||||
date.setDatePickerElements($.NSDatePickerElementFlagYearMonthDay)
|
date.setDatePickerElements($.NSDatePickerElementFlagYearMonthDay)
|
||||||
date.setDateValue($.NSDate.dateWithTimeIntervalSince1970({{.Date}}))
|
|
||||||
date.setFrameSize(date.fittingSize)
|
date.setFrameSize(date.fittingSize)
|
||||||
|
{{- if .Date}}
|
||||||
|
date.setDateValue($.NSDate.dateWithTimeIntervalSince1970({{.Date}}))
|
||||||
|
{{- end}}
|
||||||
|
|
||||||
var alert = $.NSAlert.alloc.init
|
var alert = $.NSAlert.alloc.init
|
||||||
alert.setAccessoryView(date)
|
alert.setAccessoryView(date)
|
||||||
|
|
|
@ -220,7 +220,7 @@ type Progress struct {
|
||||||
|
|
||||||
// Date is internal.
|
// Date is internal.
|
||||||
type Date struct {
|
type Date struct {
|
||||||
Date int64
|
Date *int64
|
||||||
Text string
|
Text string
|
||||||
Info string
|
Info string
|
||||||
Format string
|
Format string
|
||||||
|
|
Loading…
Reference in a new issue