{"id":"e0f124f343526b33","repo":"google/gson","slug":"value-e0f124","errorCode":null,"errorMessage":"value","messagePattern":"value","errorType":"exception","errorClass":"NumberFormatException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java","lineNumber":335,"sourceCode":"   * @return true if the expected character exist at the given offset\n   */\n  private static boolean checkOffset(String value, int offset, char expected) {\n    return (offset < value.length()) && (value.charAt(offset) == expected);\n  }\n\n  /**\n   * Parse an integer located between 2 given offsets in a string\n   *\n   * @param value the string to parse\n   * @param beginIndex the start index for the integer in the string\n   * @param endIndex the end index for the integer in the string\n   * @return the int\n   * @throws NumberFormatException if the value is not a number\n   */\n  private static int parseInt(String value, int beginIndex, int endIndex)\n      throws NumberFormatException {\n    if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) {\n      throw new NumberFormatException(value);\n    }\n    // use same logic as in Integer.parseInt() but less generic we're not supporting negative values\n    int i = beginIndex;\n    int result = 0;\n    int digit;\n    if (i < endIndex) {\n      digit = Character.digit(value.charAt(i++), 10);\n      if (digit < 0) {\n        throw new NumberFormatException(\"Invalid number: \" + value.substring(beginIndex, endIndex));\n      }\n      result = -digit;\n    }\n    while (i < endIndex) {\n      digit = Character.digit(value.charAt(i++), 10);\n      if (digit < 0) {\n        throw new NumberFormatException(\"Invalid number: \" + value.substring(beginIndex, endIndex));\n      }\n      result *= 10;","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java#L317-L353","documentation":"ISO8601Utils.parseInt throws NumberFormatException(value) when its beginIndex/endIndex arguments fall outside the string bounds or are inverted (beginIndex<0, endIndex>length, or beginIndex>endIndex). This typically means the date string was truncated so that an expected numeric field could not be read at the computed offset.","triggerScenarios":"Parsing a date string that is too short for the expected structure, e.g. '2024-01' when a full date-time was expected, so parseInt runs off the end.","commonSituations":"Truncated payloads, partial field updates, or a producer that emits date-only where date-time is expected.","solutions":["Ensure the source string has all required components (date and time).","Pre-validate the length/format against the expected ISO-8601 shape.","Register a custom adapter tolerant of missing components (defaulting time to 00:00:00)."],"exampleFix":"// before\nDate d = gson.fromJson(\"\\\"2024-01\\\"\", Date.class);\n\n// after\nString s = json.length() == 7 ? json + \"-01T00:00:00Z\" : json;\nDate d = gson.fromJson('\"' + s + '\"', Date.class);","handlingStrategy":"validation","validationCode":"boolean isCompleteIso8601(String iso) {\n  // expect at least yyyy-MM-ddTHH:mm:ss plus timezone\n  return iso != null && iso.length() >= 20 && iso.matches(\"\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}:\\\\d{2}:\\\\d{2}.*\");\n}","typeGuard":"static boolean hasMinimumDateLength(String iso) { return iso != null && iso.length() >= 20; }","tryCatchPattern":"try {\n  Date d = gson.fromJson(json, Date.class);\n} catch (JsonSyntaxException e) {\n  // treat truncated date as null/epoch or reject\n}","preventionTips":["Validate ISO-8601 structural length before parsing.","Refuse partial date payloads at the schema boundary.","Default missing time components when the producer emits date-only."],"tags":["gson","date-parsing","iso8601","json"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}