|
@@ -1,34 +1,269 @@
|
|
package timefmt
|
|
package timefmt
|
|
|
|
|
|
-import "strings"
|
|
|
|
|
|
+import (
|
|
|
|
+ "git.swzry.com/zry/YAGTF/yagtf/tfelem"
|
|
|
|
+ "regexp"
|
|
|
|
+ "strconv"
|
|
|
|
+ "strings"
|
|
|
|
+ "time"
|
|
|
|
+)
|
|
|
|
|
|
-func ParseFormatString(tp *TimePrinter, fs string) {
|
|
|
|
|
|
+const parserTokenBufferSize = 128
|
|
|
|
+const regexpTimezoneTag = "^Timezone:([+-][0-9]{4})([A-Z]{3})$"
|
|
|
|
+
|
|
|
|
+type TimeElementFactoryFunc func() TimeElement
|
|
|
|
+type NonDisplayTagFunc func(tp *TimePrinter)
|
|
|
|
+
|
|
|
|
+type FormatParser struct {
|
|
|
|
+ tagList map[string]TimeElementFactoryFunc
|
|
|
|
+ ndTagList map[string]NonDisplayTagFunc
|
|
|
|
+ tzsReg *regexp.Regexp
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func NewFormatParser() *FormatParser {
|
|
|
|
+ f := &FormatParser{
|
|
|
|
+ tagList: make(map[string]TimeElementFactoryFunc),
|
|
|
|
+ ndTagList: make(map[string]NonDisplayTagFunc),
|
|
|
|
+ }
|
|
|
|
+ f.addDefaultElementClasses()
|
|
|
|
+ f.tzsReg, _ = regexp.Compile(regexpTimezoneTag)
|
|
|
|
+ return f
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (this *FormatParser) AddElementClass(tagname string, ff TimeElementFactoryFunc) {
|
|
|
|
+ this.tagList[tagname] = ff
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (this *FormatParser) AddTagAlias(alias string, tagname string) {
|
|
|
|
+ v, ok := this.tagList[tagname]
|
|
|
|
+ if ok {
|
|
|
|
+ this.tagList[alias] = v
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (this *FormatParser) AddNonDisplayTag(tagname string, nf NonDisplayTagFunc) {
|
|
|
|
+ this.ndTagList[tagname] = nf
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (this *FormatParser) ParseFormatString(tp *TimePrinter, fs string) {
|
|
if len(fs) < 1 {
|
|
if len(fs) < 1 {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
if fs[0] == '!' {
|
|
if fs[0] == '!' {
|
|
- parseAdvancedFmt(tp, fs)
|
|
|
|
|
|
+ this.parseAdvancedFmt(tp, fs[1:])
|
|
} else {
|
|
} else {
|
|
- parseBasicFmt(tp, fs)
|
|
|
|
|
|
+ this.parseBasicFmt(tp, fs)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-func parseBasicFmt(tp *TimePrinter, fs string) {
|
|
|
|
|
|
+func (this *FormatParser) parseBasicFmt(tp *TimePrinter, fs string) {
|
|
s := fs
|
|
s := fs
|
|
- s := strings.Replace(s, "!", "<!>", -1)
|
|
|
|
- s := strings.Replace(s, "yyyy", "2006", -1)
|
|
|
|
- s := strings.Replace(s, "yy", "06", -1)
|
|
|
|
- s := strings.Replace(s, "MM", "01", -1)
|
|
|
|
- s := strings.Replace(s, "M", "1", -1)
|
|
|
|
-
|
|
|
|
|
|
+ s = strings.Replace(s, "!", "<#000>", -1)
|
|
|
|
+ s = strings.Replace(s, "yyyy", "<#001>", -1)
|
|
|
|
+ s = strings.Replace(s, "yy", "<#002>", -1)
|
|
|
|
+ s = strings.Replace(s, "MM", "<#003>", -1)
|
|
|
|
+ s = strings.Replace(s, "M3", "<#004>", -1)
|
|
|
|
+ s = strings.Replace(s, "M09", "<#005>", -1)
|
|
|
|
+ s = strings.Replace(s, "M9", "<#006>", -1)
|
|
|
|
+ s = strings.Replace(s, "M", "<#007>", -1)
|
|
|
|
+ s = strings.Replace(s, "dd", "<#008>", -1)
|
|
|
|
+ s = strings.Replace(s, "d", "<#009>", -1)
|
|
|
|
+ s = strings.Replace(s, "HH", "<#010>", -1)
|
|
|
|
+ s = strings.Replace(s, "hh", "<#011>", -1)
|
|
|
|
+ s = strings.Replace(s, "H", "<#012>", -1)
|
|
|
|
+ s = strings.Replace(s, "h", "<#013>", -1)
|
|
|
|
+ s = strings.Replace(s, "mm", "<#014>", -1)
|
|
|
|
+ s = strings.Replace(s, "ss", "<#015>", -1)
|
|
|
|
+ s = strings.Replace(s, "E09", "<#016>", -1)
|
|
|
|
+ s = strings.Replace(s, "E9", "<#017>", -1)
|
|
|
|
+ s = strings.Replace(s, "E3", "<#018>", -1)
|
|
|
|
+ s = strings.Replace(s, "A", "<#019>", -1)
|
|
|
|
+ s = strings.Replace(s, "S1", "<#020>", -1)
|
|
|
|
+ s = strings.Replace(s, "S2", "<#021>", -1)
|
|
|
|
+ s = strings.Replace(s, "S3", "<#022>", -1)
|
|
|
|
+ s = strings.Replace(s, "Z", "<#023>", -1)
|
|
|
|
+ s = strings.Replace(s, "z", "<#024>", -1)
|
|
|
|
+ this.parseAdvancedFmt(tp, s)
|
|
}
|
|
}
|
|
|
|
|
|
-func parseAdvancedFmt(tp *TimePrinter, fs string) {
|
|
|
|
|
|
+func (this *FormatParser) parseAdvancedFmt(tp *TimePrinter, fs string) {
|
|
if len(fs) > 1 {
|
|
if len(fs) > 1 {
|
|
- if fs[1] == '!' {
|
|
|
|
- parseBasicFmt(tp, fs[1:])
|
|
|
|
|
|
+ if fs[0] == '!' {
|
|
|
|
+ this.parseBasicFmt(tp, fs[1:])
|
|
return
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ stat := false
|
|
|
|
+ ba := []byte(fs)
|
|
|
|
+ ptbuf := make([]byte, 0, parserTokenBufferSize)
|
|
|
|
+ for _, v := range ba {
|
|
|
|
+ if stat {
|
|
|
|
+ if v == '>' {
|
|
|
|
+ this.processTag(tp, string(ptbuf))
|
|
|
|
+ ptbuf = make([]byte, 0, parserTokenBufferSize)
|
|
|
|
+ stat = false
|
|
|
|
+ } else {
|
|
|
|
+ ptbuf = append(ptbuf, v)
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if v == '<' {
|
|
|
|
+ tp.AddPureText(string(ptbuf))
|
|
|
|
+ ptbuf = make([]byte, 0, parserTokenBufferSize)
|
|
|
|
+ stat = true
|
|
|
|
+ } else {
|
|
|
|
+ ptbuf = append(ptbuf, v)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (this *FormatParser) processTimezoneTag(tp *TimePrinter, tzs string, tzname string) {
|
|
|
|
+ sg := 0
|
|
|
|
+ if tzs[0] == '+' {
|
|
|
|
+ sg = 1
|
|
|
|
+ } else if tzs[0] == '-' {
|
|
|
|
+ sg = -1
|
|
|
|
+ } else {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if len(tzs) != 5 {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ hs := tzs[1:3]
|
|
|
|
+ ms := tzs[3:5]
|
|
|
|
+ hi, err := strconv.Atoi(hs)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ mi, err := strconv.Atoi(ms)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ ofs := (hi*3600 + mi*60) * sg
|
|
|
|
+ tz := time.FixedZone(tzname, ofs)
|
|
|
|
+ tp.UseTimezone(tz)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (this *FormatParser) processTag(tp *TimePrinter, tag string) {
|
|
|
|
+ rrs := this.tzsReg.FindStringSubmatch(tag)
|
|
|
|
+ if len(rrs) == 3 {
|
|
|
|
+ this.processTimezoneTag(tp, rrs[1], rrs[2])
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ v1, ok := this.ndTagList[tag]
|
|
|
|
+ if ok {
|
|
|
|
+ v1(tp)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ v2, ok := this.tagList[tag]
|
|
|
|
+ if ok {
|
|
|
|
+ tp.AddElement(v2())
|
|
|
|
+ } else {
|
|
|
|
+ tp.AddPureText("<" + tag + ">")
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
|
|
+func (this *FormatParser) addDefaultElementClasses() {
|
|
|
|
+ this.AddNonDisplayTag("UTC", func(tp *TimePrinter) { tp.UseUTC() })
|
|
|
|
+ this.AddNonDisplayTag("Local", func(tp *TimePrinter) { tp.UseLocalTimezone() })
|
|
|
|
+ this.AddElementClass("year", func() TimeElement { return tfelem.NewYearElement(false) })
|
|
|
|
+ this.AddElementClass("shortYear", func() TimeElement { return tfelem.NewYearElement(true) })
|
|
|
|
+ this.AddElementClass("month", func() TimeElement { return tfelem.NewNumbericMonthElement(true) })
|
|
|
|
+ this.AddElementClass("monthNoFill", func() TimeElement { return tfelem.NewNumbericMonthElement(false) })
|
|
|
|
+ this.AddElementClass("monthAbbr", func() TimeElement { return tfelem.NewEnglishMonthElement(true, false) })
|
|
|
|
+ this.AddElementClass("monthName", func() TimeElement { return tfelem.NewEnglishMonthElement(false, true) })
|
|
|
|
+ this.AddElementClass("monthNameNoFill", func() TimeElement { return tfelem.NewEnglishMonthElement(false, false) })
|
|
|
|
+ this.AddElementClass("day", func() TimeElement { return tfelem.NewDayElement(true) })
|
|
|
|
+ this.AddElementClass("dayNoFill", func() TimeElement { return tfelem.NewDayElement(false) })
|
|
|
|
+ this.AddElementClass("hour24", func() TimeElement { return tfelem.NewHour24hElement(true) })
|
|
|
|
+ this.AddElementClass("hour24NoFill", func() TimeElement { return tfelem.NewHour24hElement(false) })
|
|
|
|
+ this.AddElementClass("hour12", func() TimeElement { return tfelem.NewHour12hElement(true) })
|
|
|
|
+ this.AddElementClass("hour12NoFill", func() TimeElement { return tfelem.NewHour12hElement(false) })
|
|
|
|
+ this.AddElementClass("minute", func() TimeElement { return tfelem.NewMinuteElement() })
|
|
|
|
+ this.AddElementClass("second", func() TimeElement { return tfelem.NewSecondElement() })
|
|
|
|
+ this.AddElementClass("ms", func() TimeElement { return tfelem.NewSecondFloatPartElementWithMilliSec() })
|
|
|
|
+ this.AddElementClass("us", func() TimeElement { return tfelem.NewSecondFloatPartElementWithMicroSec() })
|
|
|
|
+ this.AddElementClass("ns", func() TimeElement { return tfelem.NewSecondFloatPartElementWithNanoSec() })
|
|
|
|
+ this.AddElementClass("weekday", func() TimeElement { return tfelem.NewNumbericWeekDayElement() })
|
|
|
|
+ this.AddElementClass("weekdayAbbr", func() TimeElement { return tfelem.NewEnglishWeekDayElement(true, false) })
|
|
|
|
+ this.AddElementClass("weekdayName", func() TimeElement { return tfelem.NewEnglishWeekDayElement(false, true) })
|
|
|
|
+ this.AddElementClass("weekdayNameNoFill", func() TimeElement { return tfelem.NewEnglishWeekDayElement(false, false) })
|
|
|
|
+ this.AddElementClass("ampm", func() TimeElement { return tfelem.NewAMPMElement() })
|
|
|
|
+ this.AddElementClass("yearweek", func() TimeElement { return tfelem.NewWeekElement(true) })
|
|
|
|
+ this.AddElementClass("yearweekNoFill", func() TimeElement { return tfelem.NewWeekElement(false) })
|
|
|
|
+ this.AddElementClass("yearday", func() TimeElement { return tfelem.NewYearDayElement(true) })
|
|
|
|
+ this.AddElementClass("yeardayNoFill", func() TimeElement { return tfelem.NewYearDayElement(false) })
|
|
|
|
+ this.AddElementClass("timezone", func() TimeElement { return tfelem.NewTimeZoneUTCOffsetElement() })
|
|
|
|
+ this.AddElementClass("timezoneAbbr", func() TimeElement { return tfelem.NewTimeZoneAbbrElement() })
|
|
|
|
+ this.AddElementClass("timezoneSec", func() TimeElement { return tfelem.NewTimeZoneNumbericOffsetElement(true) })
|
|
|
|
+ this.AddElementClass("timezoneSecNoFill", func() TimeElement { return tfelem.NewTimeZoneNumbericOffsetElement(false) })
|
|
|
|
+ this.AddElementClass("iso8601date", func() TimeElement { return tfelem.NewISO8601DateElement() })
|
|
|
|
+ this.AddElementClass("iso8601time", func() TimeElement { return tfelem.NewISO8601TimeElement() })
|
|
|
|
+ this.AddElementClass("iso8601full", func() TimeElement { return tfelem.NewISO8601FullElement() })
|
|
|
|
+ this.AddElementClass("common", func() TimeElement { return tfelem.NewCommonDatetimeElement() })
|
|
|
|
+ this.AddElementClass("nginx", func() TimeElement { return tfelem.NewNginxDefaultElement() })
|
|
|
|
+ this.AddElementClass("!", func() TimeElement { return &tfelem.PureTextElement{PureText: "!"} })
|
|
|
|
+ this.AddElementClass("lt", func() TimeElement { return &tfelem.PureTextElement{PureText: "<"} })
|
|
|
|
+ this.AddElementClass("gt", func() TimeElement { return &tfelem.PureTextElement{PureText: ">"} })
|
|
|
|
+ this.AddElementClass("q", func() TimeElement { return &tfelem.PureTextElement{PureText: `"`} })
|
|
|
|
+ this.AddElementClass("sq", func() TimeElement { return &tfelem.PureTextElement{PureText: "'"} })
|
|
|
|
+ this.AddElementClass("tab", func() TimeElement { return &tfelem.PureTextElement{PureText: "\t"} })
|
|
|
|
+ this.AddElementClass("br", func() TimeElement { return &tfelem.PureTextElement{PureText: "\n"} })
|
|
|
|
+ this.AddElementClass("cr", func() TimeElement { return &tfelem.PureTextElement{PureText: "\r"} })
|
|
|
|
+ this.AddElementClass("sp", func() TimeElement { return &tfelem.PureTextElement{PureText: "!"} })
|
|
|
|
+ this.AddTagAlias("y", "year")
|
|
|
|
+ this.AddTagAlias("sy", "shortYear")
|
|
|
|
+ this.AddTagAlias("mon", "month")
|
|
|
|
+ this.AddTagAlias("monNF", "monthNoFill")
|
|
|
|
+ this.AddTagAlias("monA", "monthAbbr")
|
|
|
|
+ this.AddTagAlias("monN", "monthName")
|
|
|
|
+ this.AddTagAlias("monNNF", "monthNameNoFill")
|
|
|
|
+ this.AddTagAlias("d", "day")
|
|
|
|
+ this.AddTagAlias("dNF", "dayNoFill")
|
|
|
|
+ this.AddTagAlias("h24", "hour24")
|
|
|
|
+ this.AddTagAlias("h12", "hour12")
|
|
|
|
+ this.AddTagAlias("h24NF", "hour24NoFill")
|
|
|
|
+ this.AddTagAlias("h12NF", "hour12NoFill")
|
|
|
|
+ this.AddTagAlias("min", "minute")
|
|
|
|
+ this.AddTagAlias("s", "second")
|
|
|
|
+ this.AddTagAlias("wd", "weekday")
|
|
|
|
+ this.AddTagAlias("wdN", "weekdayName")
|
|
|
|
+ this.AddTagAlias("wdNNF", "weekdayNameNoFill")
|
|
|
|
+ this.AddTagAlias("wdA", "weekdayAbbr")
|
|
|
|
+ this.AddTagAlias("yw", "yearweek")
|
|
|
|
+ this.AddTagAlias("ywNF", "yearweekNoFill")
|
|
|
|
+ this.AddTagAlias("yd", "yearday")
|
|
|
|
+ this.AddTagAlias("ydNF", "yeardayNoFill")
|
|
|
|
+ this.AddTagAlias("tz", "timezone")
|
|
|
|
+ this.AddTagAlias("tzA", "timezoneAbbr")
|
|
|
|
+ this.AddTagAlias("tzS", "timezoneSec")
|
|
|
|
+ this.AddTagAlias("tzSNF", "timezoneSecNoFill")
|
|
|
|
+ this.AddTagAlias("i8d", "iso8601date")
|
|
|
|
+ this.AddTagAlias("i8t", "iso8601time")
|
|
|
|
+ this.AddTagAlias("i8f", "iso8601full")
|
|
|
|
+ this.AddTagAlias("#000", "!")
|
|
|
|
+ this.AddTagAlias("#001", "year")
|
|
|
|
+ this.AddTagAlias("#002", "shortYear")
|
|
|
|
+ this.AddTagAlias("#003", "month")
|
|
|
|
+ this.AddTagAlias("#004", "monthAbbr")
|
|
|
|
+ this.AddTagAlias("#005", "monthName")
|
|
|
|
+ this.AddTagAlias("#006", "monthNameNoFill")
|
|
|
|
+ this.AddTagAlias("#007", "monthNoFill")
|
|
|
|
+ this.AddTagAlias("#008", "day")
|
|
|
|
+ this.AddTagAlias("#009", "dayNoFill")
|
|
|
|
+ this.AddTagAlias("#010", "hour24")
|
|
|
|
+ this.AddTagAlias("#011", "hour12")
|
|
|
|
+ this.AddTagAlias("#012", "hour24NoFill")
|
|
|
|
+ this.AddTagAlias("#013", "hour12NoFill")
|
|
|
|
+ this.AddTagAlias("#014", "minute")
|
|
|
|
+ this.AddTagAlias("#015", "second")
|
|
|
|
+ this.AddTagAlias("#016", "weekdayName")
|
|
|
|
+ this.AddTagAlias("#017", "weekdayNameNoFill")
|
|
|
|
+ this.AddTagAlias("#018", "weekdayAbbr")
|
|
|
|
+ this.AddTagAlias("#019", "ampm")
|
|
|
|
+ this.AddTagAlias("#020", "ms")
|
|
|
|
+ this.AddTagAlias("#021", "us")
|
|
|
|
+ this.AddTagAlias("#022", "ns")
|
|
|
|
+ this.AddTagAlias("#023", "timezoneAbbr")
|
|
|
|
+ this.AddTagAlias("#024", "timezone")
|
|
}
|
|
}
|