{"id":"259e4b186f2efdf8","repo":"google/gson","slug":"no-time-zone-indicator-259e4b","errorCode":null,"errorMessage":"No time zone indicator","messagePattern":"No time zone indicator","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java","lineNumber":231,"sourceCode":"              switch (parseEndOffset - offset) { // number of digits parsed\n                case 2:\n                  milliseconds = fraction * 10;\n                  break;\n                case 1:\n                  milliseconds = fraction * 100;\n                  break;\n                default:\n                  milliseconds = fraction;\n              }\n              offset = endOffset;\n            }\n          }\n        }\n      }\n\n      // extract timezone\n      if (date.length() <= offset) {\n        throw new IllegalArgumentException(\"No time zone indicator\");\n      }\n\n      TimeZone timezone = null;\n      char timezoneIndicator = date.charAt(offset);\n\n      if (timezoneIndicator == 'Z') {\n        timezone = TIMEZONE_UTC;\n        offset += 1;\n      } else if (timezoneIndicator == '+' || timezoneIndicator == '-') {\n        String timezoneOffset = date.substring(offset);\n\n        // When timezone has no minutes, we should append it, valid timezones are, for example:\n        // +00:00, +0000 and +00\n        timezoneOffset = timezoneOffset.length() >= 5 ? timezoneOffset : timezoneOffset + \"00\";\n\n        offset += timezoneOffset.length();\n        // 18-Jun-2015, tatu: Minor simplification, skip offset of \"+0000\"/\"+00:00\"\n        if (timezoneOffset.equals(\"+0000\") || timezoneOffset.equals(\"+00:00\")) {","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java#L213-L249","documentation":"ISO8601Utils.parse reaches the timezone-extraction step but the input string ends before any timezone character is present (offset >= length). ISO 8601 requires a trailing 'Z' or +/- offset for a complete date-time, so the parser throws IllegalArgumentException 'No time zone indicator'. The exception is later wrapped into a ParseException.","triggerScenarios":"Parsing a date string such as '2024-01-01T00:00:00' that has no trailing 'Z' or '+00:00' offset, used by Gson's Date/old date adapters that rely on ISO8601Utils.","commonSituations":"Producer emits ISO-8601 'local' date-times without timezone, a producer that historically included 'Z' is changed, or a field is shared between systems with different tz conventions.","solutions":["Ensure the source string includes an explicit timezone (append 'Z' for UTC, or '+HH:mm').","Pre-process the string to append a default timezone before parsing.","Register a custom TypeAdapter<Date> that uses a SimpleDateFormat lenient with no timezone, or java.time with a fixed ZoneId."],"exampleFix":"// before\nDate d = gson.fromJson(\"\\\"2024-01-01T00:00:00\\\"\", Date.class);\n\n// after: normalize missing tz to UTC\nString s = json;\nif (!s.endsWith(\"Z\") && !s.matches(\".*[+\\\\-][0-9]{2}:?[0-9]{2}$\")) s += \"Z\";\nDate d = gson.fromJson('\"' + s + '\"', Date.class);","handlingStrategy":"validation","validationCode":"String ensureTimezone(String iso) {\n  if (iso == null || iso.isEmpty()) return iso;\n  if (iso.endsWith(\"Z\")) return iso;\n  if (iso.matches(\".*[+\\\\-][0-9]{2}:?[0-9]{2}$\")) return iso;\n  return iso + \"Z\";\n}","typeGuard":"static boolean hasTimezoneIndicator(String iso) {\n  return iso != null && (iso.endsWith(\"Z\") || iso.matches(\".*[+\\\\-][0-9]{2}:?[0-9]{2}$\"));\n}","tryCatchPattern":"try {\n  Date d = gson.fromJson(json, Date.class);\n} catch (JsonSyntaxException e) {\n  // append a default zone, retry once\n}","preventionTips":["Mandate timezone-suffixed ISO-8601 strings at the producer boundary.","Prefer java.time.Instant which enforces an offset/zone.","Register a Date adapter that defaults to UTC when the zone is missing."],"tags":["gson","date-parsing","iso8601","timezone","json"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}