Add marshalling for dateTime.tz type.
This commit is contained in:
parent
de724897db
commit
ecf830777a
265
soap/types.go
265
soap/types.go
@ -57,6 +57,133 @@ func UnmarshalChar(s string) (rune, error) {
|
|||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseInt(s string, err *error) int {
|
||||||
|
v, parseErr := strconv.ParseInt(s, 10, 64)
|
||||||
|
if parseErr != nil {
|
||||||
|
*err = parseErr
|
||||||
|
}
|
||||||
|
return int(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var dateRegexps = []*regexp.Regexp{
|
||||||
|
// yyyy[-mm[-dd]]
|
||||||
|
regexp.MustCompile(`^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$`),
|
||||||
|
// yyyy[mm[dd]]
|
||||||
|
regexp.MustCompile(`^(\d{4})(?:(\d{2})(?:(\d{2}))?)?$`),
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDateParts(s string) (year, month, day int, err error) {
|
||||||
|
var parts []string
|
||||||
|
for _, re := range dateRegexps {
|
||||||
|
parts = re.FindStringSubmatch(s)
|
||||||
|
if parts != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if parts == nil {
|
||||||
|
err = fmt.Errorf("soap date: value %q is not in a recognized ISO8601 date format", s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
year = parseInt(parts[1], &err)
|
||||||
|
month = 1
|
||||||
|
day = 1
|
||||||
|
if len(parts[2]) != 0 {
|
||||||
|
month = parseInt(parts[2], &err)
|
||||||
|
if len(parts[3]) != 0 {
|
||||||
|
day = parseInt(parts[3], &err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("soap date: %q: %v", s, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeRegexps = []*regexp.Regexp{
|
||||||
|
// hh[:mm[:ss]]
|
||||||
|
regexp.MustCompile(`^(\d{2})(?::(\d{2})(?::(\d{2}))?)?$`),
|
||||||
|
// hh[mm[ss]]
|
||||||
|
regexp.MustCompile(`^(\d{2})(?:(\d{2})(?:(\d{2}))?)?$`),
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTimeParts(s string) (hour, minute, second int, err error) {
|
||||||
|
var parts []string
|
||||||
|
for _, re := range timeRegexps {
|
||||||
|
parts = re.FindStringSubmatch(s)
|
||||||
|
if parts != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if parts == nil {
|
||||||
|
err = fmt.Errorf("soap time: value %q is not in ISO8601 time format", s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hour = parseInt(parts[1], &err)
|
||||||
|
if len(parts[2]) != 0 {
|
||||||
|
minute = parseInt(parts[2], &err)
|
||||||
|
if len(parts[3]) != 0 {
|
||||||
|
second = parseInt(parts[3], &err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("soap time: %q: %v", s, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// (+|-)hh[[:]mm]
|
||||||
|
var timezoneRegexp = regexp.MustCompile(`^([+-])(\d{2})(?::?(\d{2}))?$`)
|
||||||
|
|
||||||
|
func parseTimezone(s string) (offset int, err error) {
|
||||||
|
if s == "Z" {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
parts := timezoneRegexp.FindStringSubmatch(s)
|
||||||
|
if parts == nil {
|
||||||
|
err = fmt.Errorf("soap timezone: value %q is not in ISO8601 timezone format", s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = parseInt(parts[2], &err) * 3600
|
||||||
|
if len(parts[3]) != 0 {
|
||||||
|
offset += parseInt(parts[3], &err) * 60
|
||||||
|
}
|
||||||
|
if parts[1] == "-" {
|
||||||
|
offset = -offset
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("soap timezone: %q: %v", s, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var completeDateTimeZoneRegexp = regexp.MustCompile(`^([^T]+)(?:T([^-+Z]+)(.+)?)?$`)
|
||||||
|
|
||||||
|
// splitCompleteDateTimeZone splits date, time and timezone apart from an
|
||||||
|
// ISO8601 string. It does not ensure that the contents of each part are
|
||||||
|
// correct, it merely splits on certain delimiters.
|
||||||
|
// e.g "2010-09-08T12:15:10+0700" => "2010-09-08", "12:15:10", "+0700".
|
||||||
|
// Timezone can only be present if time is also present.
|
||||||
|
func splitCompleteDateTimeZone(s string) (dateStr, timeStr, zoneStr string, err error) {
|
||||||
|
parts := completeDateTimeZoneRegexp.FindStringSubmatch(s)
|
||||||
|
if parts == nil {
|
||||||
|
err = fmt.Errorf("soap date/time/zone: value %q is not in ISO8601 datetime format", s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dateStr = parts[1]
|
||||||
|
timeStr = parts[2]
|
||||||
|
zoneStr = parts[3]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalDate marshals time.Time to SOAP "date" type. Note that this converts
|
// MarshalDate marshals time.Time to SOAP "date" type. Note that this converts
|
||||||
// to local time, and discards the time-of-day components.
|
// to local time, and discards the time-of-day components.
|
||||||
func MarshalDate(v time.Time) (string, error) {
|
func MarshalDate(v time.Time) (string, error) {
|
||||||
@ -68,12 +195,11 @@ var dateFmts = []string{"2006-01-02", "20060102"}
|
|||||||
// UnmarshalDate unmarshals time.Time from SOAP "date" type. This outputs the
|
// UnmarshalDate unmarshals time.Time from SOAP "date" type. This outputs the
|
||||||
// date as midnight in the local time zone.
|
// date as midnight in the local time zone.
|
||||||
func UnmarshalDate(s string) (time.Time, error) {
|
func UnmarshalDate(s string) (time.Time, error) {
|
||||||
for _, f := range dateFmts {
|
year, month, day, err := parseDateParts(s)
|
||||||
if t, err := time.ParseInLocation(f, s, localLoc); err == nil {
|
if err != nil {
|
||||||
return t, nil
|
return time.Time{}, err
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return time.Time{}, fmt.Errorf("soap date: value %q is not in a recognized date format", s)
|
return time.Date(year, time.Month(month), day, 0, 0, 0, 0, localLoc), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimeOfDay is used in cases where SOAP "time" or "time.tz" is used.
|
// TimeOfDay is used in cases where SOAP "time" or "time.tz" is used.
|
||||||
@ -88,7 +214,7 @@ type TimeOfDay struct {
|
|||||||
// Offset is non-zero only if time.tz is used. It is otherwise ignored. If
|
// Offset is non-zero only if time.tz is used. It is otherwise ignored. If
|
||||||
// non-zero, then it is regarded as a UTC offset in seconds. Note that the
|
// non-zero, then it is regarded as a UTC offset in seconds. Note that the
|
||||||
// sub-minutes is ignored by the marshal function.
|
// sub-minutes is ignored by the marshal function.
|
||||||
Offset int16
|
Offset int
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalTimeOfDay marshals TimeOfDay to the "time" type.
|
// MarshalTimeOfDay marshals TimeOfDay to the "time" type.
|
||||||
@ -139,24 +265,27 @@ func MarshalTimeOfDayTz(v TimeOfDay) (string, error) {
|
|||||||
return fmt.Sprintf("%02d:%02d:%02d%s", hour, minute, second, tz), nil
|
return fmt.Sprintf("%02d:%02d:%02d%s", hour, minute, second, tz), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeRegexp = regexp.MustCompile(
|
|
||||||
`^(\d\d)(?::?(\d\d)(?::?(\d\d))?)?` + // hh[:mm[:ss]]
|
|
||||||
`(?:(Z)|([+-])(\d\d)(?::?(\d\d))?)?$`) // Z | ±hh[:mm]
|
|
||||||
|
|
||||||
// UnmarshalTimeOfDayTz unmarshals TimeOfDay from the "time.tz" type.
|
// UnmarshalTimeOfDayTz unmarshals TimeOfDay from the "time.tz" type.
|
||||||
func UnmarshalTimeOfDayTz(s string) (TimeOfDay, error) {
|
func UnmarshalTimeOfDayTz(s string) (tod TimeOfDay, err error) {
|
||||||
parts := timeRegexp.FindStringSubmatch(s)
|
zoneIndex := strings.IndexAny(s, "Z+-")
|
||||||
if parts == nil {
|
var timePart string
|
||||||
return TimeOfDay{}, fmt.Errorf("soap time.tz: value %q is not in ISO8601 time format", s)
|
var hasOffset bool
|
||||||
|
var offset int
|
||||||
|
if zoneIndex == -1 {
|
||||||
|
hasOffset = false
|
||||||
|
timePart = s
|
||||||
|
} else {
|
||||||
|
hasOffset = true
|
||||||
|
timePart = s[:zoneIndex]
|
||||||
|
if offset, err = parseTimezone(s[zoneIndex:]); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HH:MM:SS parsing.
|
hour, minute, second, err := parseTimeParts(timePart)
|
||||||
parts = parts[1:]
|
if err != nil {
|
||||||
var iParts [3]int64
|
return
|
||||||
for i, pStr := range parts[:3] {
|
|
||||||
iParts[i], _ = strconv.ParseInt(pStr, 10, 64)
|
|
||||||
}
|
}
|
||||||
hour, minute, second := iParts[0], iParts[1], iParts[2]
|
|
||||||
|
|
||||||
fromMidnight := time.Duration(hour*3600+minute*60+second) * time.Second
|
fromMidnight := time.Duration(hour*3600+minute*60+second) * time.Second
|
||||||
|
|
||||||
@ -166,51 +295,85 @@ func UnmarshalTimeOfDayTz(s string) (TimeOfDay, error) {
|
|||||||
return TimeOfDay{}, fmt.Errorf("soap time.tz: value %q has value(s) out of range", s)
|
return TimeOfDay{}, fmt.Errorf("soap time.tz: value %q has value(s) out of range", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timezone offset parsing.
|
|
||||||
hasOffset := false
|
|
||||||
var offset int64
|
|
||||||
if parts[3] == "Z" {
|
|
||||||
hasOffset = true
|
|
||||||
offset = 0
|
|
||||||
} else if parts[4] != "" {
|
|
||||||
hasOffset = true
|
|
||||||
hours, _ := strconv.ParseInt(parts[5], 10, 64)
|
|
||||||
var mins int64
|
|
||||||
if parts[6] != "" {
|
|
||||||
mins, _ = strconv.ParseInt(parts[6], 10, 64)
|
|
||||||
}
|
|
||||||
offset = hours*3600 + mins*60
|
|
||||||
if parts[4] == "-" {
|
|
||||||
offset = -offset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TimeOfDay{
|
return TimeOfDay{
|
||||||
FromMidnight: time.Duration(hour*3600+minute*60+second) * time.Second,
|
FromMidnight: time.Duration(hour*3600+minute*60+second) * time.Second,
|
||||||
HasOffset: hasOffset,
|
HasOffset: hasOffset,
|
||||||
Offset: int16(offset),
|
Offset: offset,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalDatetime marshals time.Time to SOAP "date" type. Note that this
|
// MarshalDateTime marshals time.Time to SOAP "dateTime" type. Note that this
|
||||||
// converts to local time.
|
// converts to local time.
|
||||||
func MarshalDatetime(v time.Time) (string, error) {
|
func MarshalDateTime(v time.Time) (string, error) {
|
||||||
return v.In(localLoc).Format("2006-01-02T15:04:05"), nil
|
return v.In(localLoc).Format("2006-01-02T15:04:05"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalDatetime unmarshals time.Time from the SOAP "dateTime" type. This
|
// UnmarshalDateTime unmarshals time.Time from the SOAP "dateTime" type. This
|
||||||
// returns a value in the local timezone.
|
// returns a value in the local timezone.
|
||||||
func UnmarshalDatetime(s string) (time.Time, error) {
|
func UnmarshalDateTime(s string) (result time.Time, err error) {
|
||||||
parts := strings.SplitN(s, "T", 2)
|
dateStr, timeStr, zoneStr, err := splitCompleteDateTimeZone(s)
|
||||||
datePart, err := UnmarshalDate(parts[0])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
return
|
||||||
}
|
}
|
||||||
if len(parts) == 2 {
|
|
||||||
timePart, err := UnmarshalTimeOfDay(parts[1])
|
if len(zoneStr) != 0 {
|
||||||
|
err = fmt.Errorf("soap datetime: unexpected timezone in %q", s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
year, month, day, err := parseDateParts(dateStr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var hour, minute, second int
|
||||||
|
if len(timeStr) != 0 {
|
||||||
|
hour, minute, second, err = parseTimeParts(timeStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
return
|
||||||
}
|
}
|
||||||
datePart = datePart.Add(timePart.FromMidnight)
|
|
||||||
}
|
}
|
||||||
return datePart, nil
|
|
||||||
|
result = time.Date(year, time.Month(month), day, hour, minute, second, 0, localLoc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalDateTimeTz marshals time.Time to SOAP "dateTime.tz" type.
|
||||||
|
func MarshalDateTimeTz(v time.Time) (string, error) {
|
||||||
|
return v.Format("2006-01-02T15:04:05-07:00"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalDateTimeTz unmarshals time.Time from the SOAP "dateTime.tz" type.
|
||||||
|
// This returns a value in the local timezone when the timezone is unspecified.
|
||||||
|
func UnmarshalDateTimeTz(s string) (result time.Time, err error) {
|
||||||
|
dateStr, timeStr, zoneStr, err := splitCompleteDateTimeZone(s)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
year, month, day, err := parseDateParts(dateStr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var hour, minute, second int
|
||||||
|
var location *time.Location = localLoc
|
||||||
|
if len(timeStr) != 0 {
|
||||||
|
hour, minute, second, err = parseTimeParts(timeStr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(zoneStr) != 0 {
|
||||||
|
var offset int
|
||||||
|
offset, err = parseTimezone(zoneStr)
|
||||||
|
if offset == 0 {
|
||||||
|
location = time.UTC
|
||||||
|
} else {
|
||||||
|
location = time.FixedZone("", offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = time.Date(year, time.Month(month), day, hour, minute, second, 0, location)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ func (v DateTest) Equal(result interface{}) bool {
|
|||||||
}
|
}
|
||||||
func (v DateTest) Dupe(tag string) convTest {
|
func (v DateTest) Dupe(tag string) convTest {
|
||||||
if tag != "no:dateTime" {
|
if tag != "no:dateTime" {
|
||||||
return DatetimeTest{v.Time}
|
return DateTimeTest{v.Time}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -104,15 +104,33 @@ func (v TimeOfDayTzTest) Equal(result interface{}) bool {
|
|||||||
return v.TimeOfDay == result.(TimeOfDay)
|
return v.TimeOfDay == result.(TimeOfDay)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DatetimeTest struct{ time.Time }
|
type DateTimeTest struct{ time.Time }
|
||||||
|
|
||||||
func (v DatetimeTest) Marshal() (string, error) {
|
func (v DateTimeTest) Marshal() (string, error) {
|
||||||
return MarshalDatetime(time.Time(v.Time))
|
return MarshalDateTime(time.Time(v.Time))
|
||||||
}
|
}
|
||||||
func (v DatetimeTest) Unmarshal(s string) (interface{}, error) {
|
func (v DateTimeTest) Unmarshal(s string) (interface{}, error) {
|
||||||
return UnmarshalDatetime(s)
|
return UnmarshalDateTime(s)
|
||||||
}
|
}
|
||||||
func (v DatetimeTest) Equal(result interface{}) bool {
|
func (v DateTimeTest) Equal(result interface{}) bool {
|
||||||
|
return v.Time.Equal(result.(time.Time))
|
||||||
|
}
|
||||||
|
func (v DateTimeTest) Dupe(tag string) convTest {
|
||||||
|
if tag != "no:dateTime.tz" {
|
||||||
|
return DateTimeTzTest{v.Time}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DateTimeTzTest struct{ time.Time }
|
||||||
|
|
||||||
|
func (v DateTimeTzTest) Marshal() (string, error) {
|
||||||
|
return MarshalDateTimeTz(time.Time(v.Time))
|
||||||
|
}
|
||||||
|
func (v DateTimeTzTest) Unmarshal(s string) (interface{}, error) {
|
||||||
|
return UnmarshalDateTimeTz(s)
|
||||||
|
}
|
||||||
|
func (v DateTimeTzTest) Equal(result interface{}) bool {
|
||||||
return v.Time.Equal(result.(time.Time))
|
return v.Time.Equal(result.(time.Time))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,11 +213,26 @@ func Test(t *testing.T) {
|
|||||||
{str: "01:02:03-01:23", value: TimeOfDayTzTest{TimeOfDay{time010203, true, -(3600 + 23*60)}}},
|
{str: "01:02:03-01:23", value: TimeOfDayTzTest{TimeOfDay{time010203, true, -(3600 + 23*60)}}},
|
||||||
{str: "01:02:03-0123", value: TimeOfDayTzTest{TimeOfDay{time010203, true, -(3600 + 23*60)}}, noMarshal: true},
|
{str: "01:02:03-0123", value: TimeOfDayTzTest{TimeOfDay{time010203, true, -(3600 + 23*60)}}, noMarshal: true},
|
||||||
|
|
||||||
// datetime
|
// dateTime
|
||||||
{str: "2013-10-08T00:00:00", value: DatetimeTest{time.Date(2013, 10, 8, 0, 0, 0, 0, localLoc)}},
|
{str: "2013-10-08T00:00:00", value: DateTimeTest{time.Date(2013, 10, 8, 0, 0, 0, 0, localLoc)}, tag: "no:dateTime.tz"},
|
||||||
{str: "20131008", value: DatetimeTest{time.Date(2013, 10, 8, 0, 0, 0, 0, localLoc)}, noMarshal: true},
|
{str: "20131008", value: DateTimeTest{time.Date(2013, 10, 8, 0, 0, 0, 0, localLoc)}, noMarshal: true},
|
||||||
{str: "2013-10-08T10:30:50", value: DatetimeTest{time.Date(2013, 10, 8, 10, 30, 50, 0, localLoc)}},
|
{str: "2013-10-08T10:30:50", value: DateTimeTest{time.Date(2013, 10, 8, 10, 30, 50, 0, localLoc)}, tag: "no:dateTime.tz"},
|
||||||
{str: "2013-10-08T10:30:50T", value: DatetimeTest{}, wantUnmarshalErr: true, noMarshal: true},
|
{str: "2013-10-08T10:30:50T", value: DateTimeTest{}, wantUnmarshalErr: true, noMarshal: true},
|
||||||
|
{str: "2013-10-08T10:30:50+01", value: DateTimeTest{}, wantUnmarshalErr: true, noMarshal: true, tag: "no:dateTime.tz"},
|
||||||
|
{str: "2013-10-08T10:30:50+01:23", value: DateTimeTest{}, wantUnmarshalErr: true, noMarshal: true, tag: "no:dateTime.tz"},
|
||||||
|
{str: "2013-10-08T10:30:50+0123", value: DateTimeTest{}, wantUnmarshalErr: true, noMarshal: true, tag: "no:dateTime.tz"},
|
||||||
|
{str: "2013-10-08T10:30:50-01", value: DateTimeTest{}, wantUnmarshalErr: true, noMarshal: true, tag: "no:dateTime.tz"},
|
||||||
|
{str: "2013-10-08T10:30:50-01:23", value: DateTimeTest{}, wantUnmarshalErr: true, noMarshal: true, tag: "no:dateTime.tz"},
|
||||||
|
{str: "2013-10-08T10:30:50-0123", value: DateTimeTest{}, wantUnmarshalErr: true, noMarshal: true, tag: "no:dateTime.tz"},
|
||||||
|
|
||||||
|
// dateTime.tz
|
||||||
|
{str: "2013-10-08T10:30:50", value: DateTimeTzTest{time.Date(2013, 10, 8, 10, 30, 50, 0, localLoc)}, noMarshal: true},
|
||||||
|
{str: "2013-10-08T10:30:50+01", value: DateTimeTzTest{time.Date(2013, 10, 8, 10, 30, 50, 0, time.FixedZone("+01:00", 3600))}, noMarshal: true},
|
||||||
|
{str: "2013-10-08T10:30:50+01:23", value: DateTimeTzTest{time.Date(2013, 10, 8, 10, 30, 50, 0, time.FixedZone("+01:23", 3600+23*60))}},
|
||||||
|
{str: "2013-10-08T10:30:50+0123", value: DateTimeTzTest{time.Date(2013, 10, 8, 10, 30, 50, 0, time.FixedZone("+01:23", 3600+23*60))}, noMarshal: true},
|
||||||
|
{str: "2013-10-08T10:30:50-01", value: DateTimeTzTest{time.Date(2013, 10, 8, 10, 30, 50, 0, time.FixedZone("-01:00", -3600))}, noMarshal: true},
|
||||||
|
{str: "2013-10-08T10:30:50-01:23", value: DateTimeTzTest{time.Date(2013, 10, 8, 10, 30, 50, 0, time.FixedZone("-01:23", -(3600+23*60)))}},
|
||||||
|
{str: "2013-10-08T10:30:50-0123", value: DateTimeTzTest{time.Date(2013, 10, 8, 10, 30, 50, 0, time.FixedZone("-01:23", -(3600+23*60)))}, noMarshal: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate extra test cases from convTests that implement duper.
|
// Generate extra test cases from convTests that implement duper.
|
||||||
|
Loading…
Reference in New Issue
Block a user