google/gson · error · IndexOutOfBoundsException
Mismatching time zone indicator: " + timezoneId + " given, r
Error message
Mismatching time zone indicator: " + timezoneId + " given, resolves to " + timezone.getID()
What it means
ISO8601Utils parses a +/- offset and constructs TimeZone.getTimeZone('GMT'+offset). The JDK silently falls back to GMT for unknown/invalid IDs, so Gson compares the returned ID to the requested one and throws IndexOutOfBoundsException when they differ even after stripping colons, indicating the offset was invalid (e.g. '+99:99').
Source
Thrown at gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java:270
// 18-Jun-2015, tatu: Looks like offsets only work from GMT, not UTC...
// not sure why, but that's the way it looks. Further, Javadocs for
// `java.util.TimeZone` specifically instruct use of GMT as base for
// custom timezones... odd.
String timezoneId = "GMT" + timezoneOffset;
// String timezoneId = "UTC" + timezoneOffset;
timezone = TimeZone.getTimeZone(timezoneId);
String act = timezone.getID();
if (!act.equals(timezoneId)) {
/* 22-Jan-2015, tatu: Looks like canonical version has colons, but we may be given
* one without. If so, don't sweat.
* Yes, very inefficient. Hopefully not hit often.
* If it becomes a perf problem, add 'loose' comparison instead.
*/
String cleaned = act.replace(":", "");
if (!cleaned.equals(timezoneId)) {
throw new IndexOutOfBoundsException(
"Mismatching time zone indicator: "
+ timezoneId
+ " given, resolves to "
+ timezone.getID());
}
}
}
} else {
throw new IndexOutOfBoundsException(
"Invalid time zone indicator '" + timezoneIndicator + "'");
}
Calendar calendar = new GregorianCalendar(timezone);
calendar.setLenient(false);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, hour);View on GitHub (pinned to 8b8628c656)
Solutions
- Correct the offset in the source to a valid ±HH:MM in the range -12:00 .. +14:00.
- Pre-validate/normalize the offset before passing to Gson.
- Register a custom date adapter that maps invalid offsets to a default zone.
Example fix
// before
Date d = gson.fromJson("\"2024-01-01T00:00:00+25:00\"", Date.class);
// after
String fixed = source.replaceAll("([+\\-])([0-9]{2}):([0-9]{2})$", m -> /* clamp to +/-14:00 */ "+00:00");
Date d = gson.fromJson('"' + fixed + '"', Date.class); Defensive patterns
Strategy: validation
Validate before calling
boolean isValidOffset(String iso) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile("([+\\-])(\\d{2}):(\\d{2})$").matcher(iso == null ? "" : iso);
if (!m.find()) return true; // not an explicit offset
int hh = Integer.parseInt(m.group(2)), mm = Integer.parseInt(m.group(3));
return hh <= 14 && mm < 60;
} Type guard
static boolean hasPlausibleOffset(String iso) {
return iso != null && iso.matches(".*[+\\-](0[0-9]|1[0-4]):[0-5][0-9]$");
} Try / catch
try {
Date d = gson.fromJson(json, Date.class);
} catch (JsonSyntaxException e) {
// if 'Mismatching time zone indicator', reject or clamp offset and retry
} Prevention
- Validate offset magnitudes (HH 0-14, MM 0-59) before parsing.
- Standardize on UTC ('Z') in producer data when possible.
- Log and quarantine records with non-standard offsets.
When it happens
Trigger: A date string whose numeric offset is out of range such as '+25:00', '-13:00', or '+99:99', causing the JDK to substitute GMT.
Common situations: Corrupt producer data, hand-built strings, timezone offsets with wrong sign or magnitude, or a serialization bug upstream.
Related errors
- No time zone indicator
- Invalid time zone indicator '" + timezoneIndicator + "'
- value
- Invalid number: " + value.substring(beginIndex, endIndex)
- Failed parsing '" + s + "' as SQL Date; at path " + in.getPr
AI-assisted analysis of google/gson@8b8628c656 (2026-08-04).
Data as JSON: /data/errors/d2da281b38e49eff.json.
Report an issue: GitHub.