kataras/iris · error
ISO8601: invalid timezone format: %s
Error message
ISO8601: invalid timezone format: %s
What it means
ParseISO8601 throws "ISO8601: invalid timezone format: <suffix>" when the string has an offset-looking sign after position 18, but the offset substring is structurally unusable: parseSignedOffset returned an inconsistent/zero length (idx+1 > idx+length) or the string ends before a complete offset could exist (len(s) <= idx+length+1). The offending suffix (everything from the +/- sign onward) is included verbatim in the message.
Source
Thrown at x/jsonx/iso8601.go:132
length := parseSignedOffset(s[idx:])
// Check if the offset is unconventional, e.g., -04:01:19
if offset := s[idx:]; isUnconventionalOffset(offset) {
mainPart := s[:idx]
tt, err = time.Parse("2006-01-02T15:04:05.000000", mainPart)
if err != nil {
return ISO8601{}, fmt.Errorf("ISO8601: %w", err)
}
adjustedTime, parseErr := adjustForUnconventionalOffset(tt, offset)
if parseErr != nil {
return ISO8601{}, fmt.Errorf("ISO8601: %w", parseErr)
}
return ISO8601(adjustedTime), nil
}
if idx+1 > idx+length || len(s) <= idx+length+1 {
return ISO8601{}, fmt.Errorf("ISO8601: invalid timezone format: %s", s[idx:])
}
offsetText := s[idx+1 : idx+length]
offset, parseErr := strconv.Atoi(offsetText)
if parseErr != nil {
return ISO8601{}, fmt.Errorf("ISO8601: %w", parseErr)
}
// E.g. offset of +0300 is returned as 10800 which is - (3 * 60 * 60).
secondsEastUTC := offset * 60 * 60
// fmt.Printf("parsing %s with offset %s, secondsEastUTC: %d, using time layout: %s\n", s, offsetText, secondsEastUTC, ISO8601ZUTCOffsetLayoutWithMicroseconds)
if loc, ok := fixedEastUTCLocations[secondsEastUTC]; ok { // Specific (fixed) zone.
if strings.Contains(s, ".") {
tt, err = time.ParseInLocation(ISO8601ZUTCOffsetLayoutWithMicroseconds, s, loc)
} else {
tt, err = time.ParseInLocation(ISO8601ZUTCOffsetLayoutWithoutMicroseconds, s, loc)
}View on GitHub (pinned to 7bedaf55a0)
Solutions
- Log/inspect the suffix printed in the error and re-emit the complete timestamp including the full offset (e.g. +03:00 not +).
- If the timestamp should be UTC, replace the broken suffix with "Z" or "+00:00" before parsing.
- Strip the incomplete offset entirely so the string matches the plain ISO8601Layout ("2024-01-02T15:04:05") when the offset is unknowable.
- Pre-validate the trailing offset with a regexp such as [+-]\d{2}(:\d{2})?$ before calling ParseISO8601.
Example fix
// before
t, err := jsonx.ParseISO8601("2024-01-02T15:04:05+") // ISO8601: invalid timezone format: +
// after
t, err := jsonx.ParseISO8601("2024-01-02T15:04:05+03:00") Defensive patterns
Strategy: validation
Validate before calling
var completeOffsetRe = regexp.MustCompile(`[+-]\d{2}(:\d{2})?$`)
func hasCompleteOffset(s string) bool {
i := strings.LastIndexAny(s, "+-")
return i >= 0 && completeOffsetRe.MatchString(s[i:])
}
// usage
if !hasCompleteOffset(raw) {
return fmt.Errorf("timestamp %q has truncated timezone offset", raw)
} Type guard
func isTruncatedOffset(s string) bool {
i := strings.LastIndexAny(s, "+-")
return i >= 0 && i == len(s)-1 || (i >= 0 && !regexp.MustCompile(`[+-]\d{2}(:\d{2})?$`).MatchString(s[i:]))
} Try / catch
t, err := jsonx.ParseISO8601(raw)
if err != nil {
if strings.Contains(err.Error(), "invalid timezone format") {
// recover: treat as UTC or re-fetch the full timestamp from source
return jsonx.ParseISO8601(strings.TrimRight(raw, "+-") + "Z")
}
return err
} Prevention
- Never truncate timestamps to fixed widths when reading logs or DB columns
- Quote timestamp values in shells/configs to avoid '+' being interpreted
- Validate trailing offset completeness before parsing
- Standardize on one full format (e.g. RFC3339) at every API boundary
When it happens
Trigger: Calling ParseISO8601 (or UnmarshalJSON/Scan) with strings like "2024-01-02T15:04:05+" (bare sign), "2024-01-02T15:04:05+2" (truncated offset), "2024-01-02T15:04:05xyz+03" (offset truncated by a trailing char), or any input where the trailing +/- region is not a complete +hh / +hh:mm style offset.
Common situations: Truncated timestamps from log tailing or fixed-width column reads; JSON payloads cut off mid-string; query parameters or config values where the offset was accidentally stripped (e.g. shell splitting on '+'); spreadsheet/CSV exports that mangle '+' characters.
Related errors
- invalid offset format: %s
- ISO8601: %w
- ISO8601: invalid timezone offset length: %s
- ISO8601: invalid timezone offset sign: %c
- error parsing offset hours: %s: %w
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/2c2bc49620b3659e.
Report an issue: GitHub.