mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-29 17:15:31 +00:00
Further XSD-Date functions
This commit is contained in:
@@ -1,66 +1,55 @@
|
|||||||
package functions
|
package functions
|
||||||
|
|
||||||
import (
|
type Month struct {
|
||||||
"time"
|
Full string
|
||||||
)
|
Short string
|
||||||
|
Number string
|
||||||
const TLAYOUT = "2006-01-02"
|
No int
|
||||||
|
|
||||||
var TRANSLM = [][]string{
|
|
||||||
{"Januar", "Jan", "1"},
|
|
||||||
{"Februar", "Feb", "2"},
|
|
||||||
{"März", "Mär", "3"},
|
|
||||||
{"April", "Apr", "4"},
|
|
||||||
{"Mai", "Mai", "5"},
|
|
||||||
{"Juni", "Jun", "6"},
|
|
||||||
{"Juli", "Jul", "7"},
|
|
||||||
{"August", "Aug", "8"},
|
|
||||||
{"September", "Sep", "9"},
|
|
||||||
{"Oktober", "Okt", "10"},
|
|
||||||
{"November", "Nov", "11"},
|
|
||||||
{"Dezember", "Dez", "12"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var TRANSLD = [][]string{
|
type Weekday struct {
|
||||||
{"Montag", "Mo"},
|
Full string
|
||||||
{"Dienstag", "Di"},
|
Short string
|
||||||
{"Mittwoch", "Mi"},
|
No int
|
||||||
{"Donnerstag", "Do"},
|
|
||||||
{"Freitag", "Fr"},
|
|
||||||
{"Samstag", "Sa"},
|
|
||||||
{"Sonntag", "So"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Date struct {
|
var TRANSLM = []Month{
|
||||||
Month string
|
{"NotAvailable", "NA", "0", 0},
|
||||||
Mon string
|
{"Januar", "Jan", "1", 1},
|
||||||
MonthNo string
|
{"Februar", "Feb", "2", 2},
|
||||||
DayNo int
|
{"März", "Mär", "3", 3},
|
||||||
Weekday string
|
{"April", "Apr", "4", 4},
|
||||||
Wd string
|
{"Mai", "Mai", "5", 5},
|
||||||
|
{"Juni", "Jun", "6", 6},
|
||||||
|
{"Juli", "Jul", "7", 7},
|
||||||
|
{"August", "Aug", "8", 8},
|
||||||
|
{"September", "Sep", "9", 9},
|
||||||
|
{"Oktober", "Okt", "10", 10},
|
||||||
|
{"November", "Nov", "11", 11},
|
||||||
|
{"Dezember", "Dez", "12", 12},
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDate(d string) Date {
|
var TRANSLD = []Weekday{
|
||||||
t, err := time.Parse(TLAYOUT, d)
|
{"NotAvailable", "NA", 0},
|
||||||
if err != nil {
|
{"Montag", "Mo", 1},
|
||||||
return Date{}
|
{"Dienstag", "Di", 2},
|
||||||
|
{"Mittwoch", "Mi", 3},
|
||||||
|
{"Donnerstag", "Do", 4},
|
||||||
|
{"Freitag", "Fr", 5},
|
||||||
|
{"Samstag", "Sa", 6},
|
||||||
|
{"Sonntag", "So", 7},
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonthName(i int) Month {
|
||||||
|
if i > 12 || i < 1 {
|
||||||
|
return TRANSLM[0]
|
||||||
}
|
}
|
||||||
m := int(t.Month()) - 1
|
return TRANSLM[i]
|
||||||
wd := int(t.Weekday()) - 1
|
}
|
||||||
return Date{
|
|
||||||
Month: TRANSLM[m][0],
|
func WeekdayName(i int) Weekday {
|
||||||
Mon: TRANSLM[m][1],
|
if i > 7 || i < 1 {
|
||||||
MonthNo: TRANSLM[m][2],
|
return TRANSLD[0]
|
||||||
DayNo: t.Day(),
|
|
||||||
Weekday: TRANSLD[wd][0],
|
|
||||||
Wd: TRANSLD[wd][1],
|
|
||||||
}
|
}
|
||||||
}
|
return TRANSLD[i]
|
||||||
|
|
||||||
func MonthName(m int) string {
|
|
||||||
return TRANSLM[m-1][0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonthNameShort(m int) string {
|
|
||||||
return TRANSLM[m-1][1]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package xsdtime
|
package xsdtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// An implementation of the xsd 1.1 datatypes:
|
// An implementation of the xsd 1.1 datatypes:
|
||||||
@@ -29,7 +29,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Date XSDDatetype = iota
|
Unknown XSDDatetype = iota
|
||||||
|
Invalid
|
||||||
|
Date
|
||||||
GDay
|
GDay
|
||||||
GMonth
|
GMonth
|
||||||
GYear
|
GYear
|
||||||
@@ -38,15 +40,27 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type XSDDate struct {
|
type XSDDate struct {
|
||||||
Year int
|
base string
|
||||||
Month int
|
|
||||||
Day int
|
|
||||||
Timezone int
|
|
||||||
|
|
||||||
Type XSDDatetype
|
Year int
|
||||||
HasTimezone bool
|
Month int
|
||||||
|
Day int
|
||||||
|
|
||||||
Time time.Time
|
hasTimezone bool
|
||||||
|
hasYear bool
|
||||||
|
hasMonth bool
|
||||||
|
hasDay bool
|
||||||
|
|
||||||
|
TZH int
|
||||||
|
TZM int
|
||||||
|
|
||||||
|
state XSDDatetype
|
||||||
|
error bool
|
||||||
|
|
||||||
|
// INFO: XSD Date Datatypes typically describe a duration in the value space.
|
||||||
|
// TimeError bool
|
||||||
|
// BaseTime time.Time
|
||||||
|
// BaseDuration time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check:
|
// Sanity check:
|
||||||
@@ -64,6 +78,12 @@ type XSDDate struct {
|
|||||||
// - no 0000 Year
|
// - no 0000 Year
|
||||||
//
|
//
|
||||||
|
|
||||||
|
func New(s string) (XSDDate, error) {
|
||||||
|
dt := XSDDate{base: s}
|
||||||
|
err := dt.Parse(s)
|
||||||
|
return dt, err
|
||||||
|
}
|
||||||
|
|
||||||
func (d XSDDate) String() string {
|
func (d XSDDate) String() string {
|
||||||
var s string
|
var s string
|
||||||
if d.Year != 0 {
|
if d.Year != 0 {
|
||||||
@@ -84,24 +104,19 @@ func (d XSDDate) String() string {
|
|||||||
s += fmt.Sprintf("-%02d", d.Day)
|
s += fmt.Sprintf("-%02d", d.Day)
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.HasTimezone {
|
if d.hasTimezone {
|
||||||
if d.Timezone == 0 {
|
if d.TZH == 0 && d.TZM == 0 {
|
||||||
s += "Z"
|
s += "Z"
|
||||||
} else {
|
} else {
|
||||||
m := d.Timezone % 60
|
|
||||||
if m < 0 {
|
|
||||||
m *= -1
|
|
||||||
}
|
|
||||||
|
|
||||||
hint := d.Timezone / 60
|
|
||||||
sep := "+"
|
sep := "+"
|
||||||
|
hint := d.TZH
|
||||||
if hint < 0 {
|
if hint < 0 {
|
||||||
sep = "-"
|
sep = "-"
|
||||||
hint *= -1
|
hint *= -1
|
||||||
}
|
}
|
||||||
h := fmt.Sprintf("%02d", hint)
|
h := fmt.Sprintf("%02d", hint)
|
||||||
|
|
||||||
s += fmt.Sprintf("%v%v:%02d", sep, h, m)
|
s += fmt.Sprintf("%v%v:%02d", sep, h, d.TZM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,48 +124,29 @@ func (d XSDDate) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *XSDDate) UnmarshalText(text []byte) error {
|
func (d *XSDDate) UnmarshalText(text []byte) error {
|
||||||
dt, err := Parse(string(text))
|
return d.Parse(string(text))
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.Year = dt.Year
|
|
||||||
d.Month = dt.Month
|
|
||||||
d.Day = dt.Day
|
|
||||||
d.Timezone = dt.Timezone
|
|
||||||
d.Type = dt.Type
|
|
||||||
d.HasTimezone = dt.HasTimezone
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d XSDDate) MarshalText() ([]byte, error) {
|
func (d XSDDate) MarshalText() ([]byte, error) {
|
||||||
return []byte(d.String()), nil
|
return []byte(d.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(s string) (XSDDate, error) {
|
func (xsdd *XSDDate) Parse(s string) error {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
|
xsdd.base = s
|
||||||
|
|
||||||
// The smallest possible date is 4 chars long
|
// The smallest possible date is 4 chars long
|
||||||
if len(s) < 4 {
|
if len(s) < 4 {
|
||||||
return XSDDate{}, fmt.Errorf("Invalid date")
|
return xsdd.parseError("Date too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
y := 0
|
// Check for Z, then check for timezone
|
||||||
m := 0
|
|
||||||
d := 0
|
|
||||||
|
|
||||||
hastz := false
|
|
||||||
tz := 0
|
|
||||||
|
|
||||||
if len(s) >= 5 && s[len(s)-1] == TIMEZONE {
|
if len(s) >= 5 && s[len(s)-1] == TIMEZONE {
|
||||||
hastz = true
|
xsdd.hasTimezone = true
|
||||||
tz = 0
|
|
||||||
s = s[:len(s)-1]
|
s = s[:len(s)-1]
|
||||||
} else if len(s) >= 10 {
|
} else if len(s) >= 10 {
|
||||||
t, err := parseTimezone(s[len(s)-6:])
|
err := xsdd.parseTimezone(s[len(s)-6:])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
hastz = true
|
|
||||||
tz = t
|
|
||||||
s = s[:len(s)-6]
|
s = s[:len(s)-6]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,23 +155,20 @@ func Parse(s string) (XSDDate, error) {
|
|||||||
if s[1] != SEPERATOR {
|
if s[1] != SEPERATOR {
|
||||||
i := 3
|
i := 3
|
||||||
for ; i < len(s); i++ {
|
for ; i < len(s); i++ {
|
||||||
if !isAllowed(s[i]) {
|
if s[i] < MIN_ALLOWED_NUMBER || s[i] > MAX_ALLOWED_NUMBER {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yint, err := strconv.Atoi(s[:i])
|
yint, err := strconv.Atoi(s[:i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return XSDDate{}, fmt.Errorf("Invalid year: %v", s[:i])
|
return xsdd.parseError(fmt.Sprintf("Invalid year: %v", s[:i]))
|
||||||
} else if yint == 0 {
|
|
||||||
return XSDDate{}, fmt.Errorf("Zero is an invalid year")
|
|
||||||
}
|
}
|
||||||
y = yint
|
xsdd.Year = yint
|
||||||
|
xsdd.hasYear = true
|
||||||
|
|
||||||
if i == len(s) {
|
if i == len(s) {
|
||||||
return XSDDate{Year: y, Type: GYear, Timezone: tz, HasTimezone: hastz}, nil
|
return nil
|
||||||
} else if i >= len(s)-1 || s[i] != SEPERATOR {
|
|
||||||
return XSDDate{}, fmt.Errorf("Invalid date ending")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s = s[i+1:]
|
s = s[i+1:]
|
||||||
@@ -188,23 +181,16 @@ func Parse(s string) (XSDDate, error) {
|
|||||||
mstr := s[:2]
|
mstr := s[:2]
|
||||||
mint, err := strconv.Atoi(mstr)
|
mint, err := strconv.Atoi(mstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return XSDDate{}, fmt.Errorf("Invalid month")
|
return xsdd.parseError(fmt.Sprintf("Invalid month: %v", mstr))
|
||||||
}
|
}
|
||||||
|
|
||||||
if mint < 1 || mint > 12 {
|
xsdd.Month = mint
|
||||||
return XSDDate{}, fmt.Errorf("Invalid month value")
|
xsdd.hasMonth = true
|
||||||
}
|
|
||||||
|
|
||||||
m = mint
|
|
||||||
s = s[2:]
|
s = s[2:]
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
if y == 0 {
|
return nil
|
||||||
return XSDDate{Month: m, Type: GMonth, HasTimezone: hastz, Timezone: tz}, nil
|
|
||||||
} else {
|
|
||||||
return XSDDate{Year: y, Month: m, Type: GYearMonth, HasTimezone: hastz, Timezone: tz}, nil
|
|
||||||
}
|
|
||||||
} else if len(s) != 3 || s[0] != SEPERATOR {
|
} else if len(s) != 3 || s[0] != SEPERATOR {
|
||||||
return XSDDate{}, fmt.Errorf("Invalid date ending: %v", s)
|
return xsdd.parseError(fmt.Sprintf("Invalid date ending: %v", s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,59 +199,173 @@ func Parse(s string) (XSDDate, error) {
|
|||||||
// Left is 02 Day
|
// Left is 02 Day
|
||||||
dint, err := strconv.Atoi(s)
|
dint, err := strconv.Atoi(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return XSDDate{}, fmt.Errorf("Invalid day: %v", s)
|
return xsdd.parseError(fmt.Sprintf("Invalid day: %v", s))
|
||||||
}
|
}
|
||||||
|
|
||||||
if dint < 1 || dint > 31 {
|
// INFO: We do not check len here, it is handled above
|
||||||
return XSDDate{}, fmt.Errorf("Invalid day value: %v", dint)
|
xsdd.Day = dint
|
||||||
}
|
xsdd.hasDay = true
|
||||||
|
|
||||||
d = dint
|
return nil
|
||||||
if y == 0 {
|
|
||||||
if m == 0 {
|
|
||||||
return XSDDate{Day: d, Type: GDay, HasTimezone: hastz, Timezone: tz}, nil
|
|
||||||
} else {
|
|
||||||
return XSDDate{Month: m, Day: d, Type: GMonthDay, HasTimezone: hastz, Timezone: tz}, nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return XSDDate{Year: y, Month: m, Day: d, Type: Date, HasTimezone: hastz, Timezone: tz}, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTimezone(s string) (int, error) {
|
var WD_CALC_MATRIX = []int{0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}
|
||||||
|
|
||||||
|
func (xsdd XSDDate) Weekday() int {
|
||||||
|
y := xsdd.Year
|
||||||
|
if xsdd.Month < 3 {
|
||||||
|
y--
|
||||||
|
}
|
||||||
|
return (y + y/4 - y/100 + y/400 + WD_CALC_MATRIX[xsdd.Month-1] + xsdd.Day) % 7
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xsdd XSDDate) Base() string {
|
||||||
|
return xsdd.base
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xsdd XSDDate) Type() XSDDatetype {
|
||||||
|
if xsdd.state == Unknown {
|
||||||
|
_ = xsdd.Validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
return xsdd.state
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xsdd *XSDDate) Validate() bool {
|
||||||
|
if xsdd.error {
|
||||||
|
xsdd.state = Invalid
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
xsdd.state = xsdd.inferState()
|
||||||
|
if xsdd.state != Invalid {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xsdd *XSDDate) parseError(s string) error {
|
||||||
|
xsdd.error = true
|
||||||
|
xsdd.state = Invalid
|
||||||
|
return errors.New(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xsdd *XSDDate) parseTimezone(s string) error {
|
||||||
// INFO: We assume the check for 'Z' has already been done
|
// INFO: We assume the check for 'Z' has already been done
|
||||||
if len(s) != 6 || s[3] != COLON || (s[0] != PLUS && s[0] != SIGN) {
|
if len(s) != 6 || s[3] != COLON || (s[0] != PLUS && s[0] != SIGN) {
|
||||||
return 0, fmt.Errorf("Invalid timezone")
|
return fmt.Errorf("Invalid timezone")
|
||||||
}
|
}
|
||||||
|
|
||||||
h, err := strconv.Atoi(s[:3])
|
h, err := strconv.Atoi(s[:3])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("Invalid hour: %v", s[:3])
|
return fmt.Errorf("Invalid hour: %v", s[:3])
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := strconv.Atoi(s[4:])
|
m, err := strconv.Atoi(s[4:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("Invalid minute: %v", s[4:])
|
return fmt.Errorf("Invalid minute: %v", s[4:])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h < -13 || h > 13) && ((h == -14 || h == 14) && m != 0) {
|
xsdd.hasTimezone = true
|
||||||
return 0, fmt.Errorf("Invalid timezone: hour: %v minute: %v", h, m)
|
xsdd.TZH = h
|
||||||
}
|
xsdd.TZM = m
|
||||||
|
|
||||||
if m < 0 || m > 59 {
|
return nil
|
||||||
return 0, fmt.Errorf("Invalid timezone: minute: %v", m)
|
|
||||||
}
|
|
||||||
|
|
||||||
h *= 60
|
|
||||||
if h < 0 {
|
|
||||||
h -= m
|
|
||||||
} else {
|
|
||||||
h += m
|
|
||||||
}
|
|
||||||
|
|
||||||
return h, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAllowed(c byte) bool {
|
func (xsdd XSDDate) inferState() XSDDatetype {
|
||||||
return c >= MIN_ALLOWED_NUMBER && c <= MAX_ALLOWED_NUMBER
|
if xsdd.hasYear && xsdd.hasMonth && xsdd.hasDay {
|
||||||
|
if !validDayMonthYear(xsdd.Year, xsdd.Month, xsdd.Day) {
|
||||||
|
return Invalid
|
||||||
|
}
|
||||||
|
return Date
|
||||||
|
} else if xsdd.hasYear && xsdd.hasMonth {
|
||||||
|
if !validMonth(xsdd.Month) || !validYear(xsdd.Year) {
|
||||||
|
return Invalid
|
||||||
|
}
|
||||||
|
return GYearMonth
|
||||||
|
} else if xsdd.hasMonth && xsdd.hasDay {
|
||||||
|
if !validDayMonth(xsdd.Day, xsdd.Month) {
|
||||||
|
return Invalid
|
||||||
|
}
|
||||||
|
return GMonthDay
|
||||||
|
} else if xsdd.hasYear {
|
||||||
|
if !validYear(xsdd.Year) {
|
||||||
|
return Invalid
|
||||||
|
}
|
||||||
|
return GYear
|
||||||
|
} else if xsdd.hasMonth {
|
||||||
|
if !validMonth(xsdd.Month) {
|
||||||
|
return Invalid
|
||||||
|
}
|
||||||
|
return GMonth
|
||||||
|
} else if xsdd.hasDay {
|
||||||
|
if !validDay(xsdd.Day) {
|
||||||
|
return Invalid
|
||||||
|
}
|
||||||
|
return GDay
|
||||||
|
}
|
||||||
|
|
||||||
|
return Invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
func validDay(i int) bool {
|
||||||
|
if i < 1 || i > 31 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func validMonth(i int) bool {
|
||||||
|
if i < 1 || i > 12 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func validYear(i int) bool {
|
||||||
|
if i == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func validDayMonth(d int, m int) bool {
|
||||||
|
if !validDay(d) || !validMonth(m) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if m == 2 {
|
||||||
|
if d > 29 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else if m == 4 || m == 6 || m == 9 || m == 11 {
|
||||||
|
if d > 30 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func validDayMonthYear(y int, m int, d int) bool {
|
||||||
|
if !validDay(d) || !validMonth(m) || !validYear(y) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if m == 2 {
|
||||||
|
if d == 29 {
|
||||||
|
if y%4 == 0 && (y%100 != 0 || y%400 == 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,55 +5,63 @@ import "testing"
|
|||||||
type Test struct {
|
type Test struct {
|
||||||
Input string
|
Input string
|
||||||
Output XSDDate
|
Output XSDDate
|
||||||
|
Type XSDDatetype
|
||||||
}
|
}
|
||||||
|
|
||||||
var tests = []Test{
|
var tests = []Test{
|
||||||
{"2006-01-02", XSDDate{Year: 2006, Month: 1, Day: 2, Type: Date}},
|
{"2006-01-02", XSDDate{Year: 2006, Month: 1, Day: 2}, GYear},
|
||||||
{"-1222-01-02", XSDDate{Year: -1222, Month: 1, Day: 2, Type: Date}},
|
{"-1222-01-02", XSDDate{Year: -1222, Month: 1, Day: 2}, Date},
|
||||||
{"-2777", XSDDate{Year: -2777, Type: GYear}},
|
{"-2777", XSDDate{Year: -2777}, GYear},
|
||||||
{"1988-12:30", XSDDate{Year: 1988, Type: GYear, HasTimezone: true, Timezone: (60*12 + 30) * -1}},
|
{"1988-12:30", XSDDate{Year: 1988, hasTimezone: true, TZH: -12, TZM: 30}, GYear},
|
||||||
{"--03+05:00", XSDDate{Month: 3, Type: GMonth, HasTimezone: true, Timezone: 300}},
|
{"--03+05:00", XSDDate{Month: 3, hasTimezone: true, TZH: 5, TZM: 0}, GMonth},
|
||||||
{"---29", XSDDate{Day: 29, Type: GDay}},
|
{"---29", XSDDate{Day: 29}, GDay},
|
||||||
{"-1234567-12Z", XSDDate{Year: -1234567, Month: 12, Type: GYearMonth, HasTimezone: true, Timezone: 0}},
|
{"-1234567-12Z", XSDDate{Year: -1234567, Month: 12, hasTimezone: true, TZH: 0, TZM: 0}, GYearMonth},
|
||||||
{"-1234567-12+05:00", XSDDate{Year: -1234567, Month: 12, Type: GYearMonth, HasTimezone: true, Timezone: 300}},
|
{"-1234567-12+05:00", XSDDate{Year: -1234567, Month: 12, hasTimezone: true, TZH: 5, TZM: 0}, GYearMonth},
|
||||||
{"--12-31", XSDDate{Month: 12, Day: 31, Type: GMonthDay}},
|
{"--12-31", XSDDate{Month: 12, Day: 31}, GMonthDay},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParse(t *testing.T) {
|
func TestParse(t *testing.T) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
dt, err := Parse(test.Input)
|
dt, err := New(test.Input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error parsing %v: %v", test.Input, err)
|
t.Errorf("Error parsing %v: %v", test.Input, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if dt.Type != test.Output.Type {
|
|
||||||
t.Errorf("Type mismatch for %v: expected %v, got %v", test.Input, test.Output.Type, dt.Type)
|
|
||||||
}
|
|
||||||
if dt.Year != test.Output.Year {
|
if dt.Year != test.Output.Year {
|
||||||
t.Errorf("Year mismatch for %v: expected %v, got %v", test.Input, test.Output.Year, dt.Year)
|
t.Errorf("Year mismatch for %v: expected %v, got %v", test.Input, test.Output.Year, dt.Year)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dt.Month != test.Output.Month {
|
if dt.Month != test.Output.Month {
|
||||||
t.Errorf("Month mismatch for %v: expected %v, got %v", test.Input, test.Output.Month, dt.Month)
|
t.Errorf("Month mismatch for %v: expected %v, got %v", test.Input, test.Output.Month, dt.Month)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dt.Day != test.Output.Day {
|
if dt.Day != test.Output.Day {
|
||||||
t.Errorf("Day mismatch for %v: expected %v, got %v", test.Input, test.Output.Day, dt.Day)
|
t.Errorf("Day mismatch for %v: expected %v, got %v", test.Input, test.Output.Day, dt.Day)
|
||||||
}
|
}
|
||||||
if dt.HasTimezone != test.Output.HasTimezone {
|
|
||||||
t.Errorf("Timezone mismatch for %v: expected %v, got %v", test.Input, test.Output.HasTimezone, dt.HasTimezone)
|
if dt.hasTimezone != test.Output.hasTimezone {
|
||||||
|
t.Errorf("Timezone mismatch for %v: expected %v, got %v", test.Input, test.Output.hasTimezone, dt.hasTimezone)
|
||||||
}
|
}
|
||||||
if dt.Timezone != test.Output.Timezone {
|
|
||||||
t.Errorf("Timezone mismatch for %v: expected %v, got %v", test.Input, test.Output.Timezone, dt.Timezone)
|
if dt.TZH != test.Output.TZH {
|
||||||
|
t.Errorf("Timezone mismatch for %v: expected %v, got %v", test.Input, test.Output.TZH, dt.TZH)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dt.TZM != test.Output.TZM {
|
||||||
|
t.Errorf("Timezone mismatch for %v: expected %v, got %v", test.Input, test.Output.TZM, dt.TZM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestString(t *testing.T) {
|
func TestString(t *testing.T) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
dt, err := Parse(test.Input)
|
dt, err := New(test.Input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error parsing %v: %v", test.Input, err)
|
t.Errorf("Error parsing %v: %v", test.Input, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if dt.String() != test.Input {
|
if dt.String() != test.Input {
|
||||||
t.Errorf("String mismatch for %v: expected %v, got %v", test.Input, test.Input, dt.String())
|
t.Errorf("String mismatch for %v: expected %v, got %v", test.Input, test.Input, dt.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,8 @@ func (e *Engine) Funcs(app *app.KGPZ) error {
|
|||||||
e.FuncMap = make(map[string]interface{})
|
e.FuncMap = make(map[string]interface{})
|
||||||
e.mu.Unlock()
|
e.mu.Unlock()
|
||||||
|
|
||||||
e.AddFunc("GetDate", functions.GetDate)
|
|
||||||
e.AddFunc("MonthName", functions.MonthName)
|
e.AddFunc("MonthName", functions.MonthName)
|
||||||
e.AddFunc("MonthNameShort", functions.MonthNameShort)
|
e.AddFunc("WeekdayName", functions.WeekdayName)
|
||||||
|
|
||||||
e.AddFunc("GetAgent", app.Library.Agents.Item)
|
e.AddFunc("GetAgent", app.Library.Agents.Item)
|
||||||
e.AddFunc("GetPlace", app.Library.Places.Item)
|
e.AddFunc("GetPlace", app.Library.Places.Item)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<!-- Issues -->
|
<!-- Issues -->
|
||||||
{{ range $issue := $month }}
|
{{ range $issue := $month }}
|
||||||
{{ $date := GetDate $issue.Datum.When }}
|
{{ $date := GetDate $issue.Datum.When.String }}
|
||||||
<a href="/{{ $y }}/{{ $issue.Number.No }}">
|
<a href="/{{ $y }}/{{ $issue.Number.No }}">
|
||||||
<div>
|
<div>
|
||||||
{{ $issue.Number.No }}
|
{{ $issue.Number.No }}
|
||||||
|
|||||||
Reference in New Issue
Block a user