{"record":{"id":"377c69d1066a3254","repo":"stanfordnlp/CoreNLP","slug":"error-creating-datetimeformatter","errorCode":null,"errorMessage":"Error creating DateTimeFormatter","messagePattern":"Error creating DateTimeFormatter","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/time/TimeFormatter.java","lineNumber":165,"sourceCode":"      String localeString = Expressions.asObject(env, attributes.get(\"locale\"));\n      r.pattern = expr;\n      if (formatter == null) {\n        if (r.annotationField == null) { r.annotationField = EnvLookup.getDefaultTextAnnotationKey(env);  }\n        /* Parse pattern and figure out what the result should be.... */\n        CustomDateFormatExtractor formatExtractor = new CustomDateFormatExtractor(expr, localeString);\n        //SequenceMatchRules.Expression result = (SequenceMatchRules.Expression) attributes.get(\"result\");\n        updateExtractRule(r, env, formatExtractor.getTextPattern(), new ApplyActionWrapper<>(env, formatExtractor, action));\n      } else if (\"org.joda.time.format.DateTimeFormat\".equals(formatter)) {\n        if (r.annotationField == null) { r.annotationField = r.tokensAnnotationField;  }\n        updateExtractRule(r, env, new ApplyActionWrapper<>(env, new JodaDateTimeFormatExtractor(expr), action));\n      } else if (\"org.joda.time.format.ISODateTimeFormat\".equals(formatter)) {\n        if (r.annotationField == null) { r.annotationField = r.tokensAnnotationField;  }\n        try {\n          Method m = ISODateTimeFormat.class.getMethod(expr);\n          DateTimeFormatter dtf = (DateTimeFormatter) m.invoke(null);\n          updateExtractRule(r, env, new ApplyActionWrapper<>(env, new JodaDateTimeFormatExtractor(expr), action));\n        } catch (Exception ex) {\n          throw new RuntimeException(\"Error creating DateTimeFormatter\", ex);\n        }\n      } else if (\"java.text.SimpleDateFormat\".equals(formatter)) {\n        if (r.annotationField == null) { r.annotationField = r.tokensAnnotationField;  }\n        updateExtractRule(r, env, new ApplyActionWrapper<>(env, new JavaDateFormatExtractor(expr), action));\n      } else {\n        throw new IllegalArgumentException(\"Unsupported formatter: \" + formatter);\n      }\n      return r;\n    }\n  }\n\n  /*\n   * Rules for parsing time specific patterns.\n   * Patterns are similar to time patterns used by JodaTime combined with a simplified regex expression\n   *\n   # y       year                         year          1996                         y\n   # M       month of year                month         July; Jul; 07                M\n   # d       day of month                 number        10                           d","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/time/TimeFormatter.java#L147-L183","documentation":"Thrown while building an extractor rule whose formatter is \"org.joda.time.format.ISODateTimeFormat\": reflection failed to find or invoke a no-arg static method named by the formatter expr on ISODateTimeFormat, or the returned object was not a DateTimeFormatter. Indicates the rule file names a non-existent ISO formatter.","triggerScenarios":"In a SUTime rules file (e.g. defs.sutime.txt), specifying formatter=org.joda.time.format.ISODateTimeFormat with expr set to a method name that does not exist on ISODateTimeFormat (typo, wrong casing, or a method from a different Joda class).","commonSituations":"Hand-editing .sutime.txt rule files, upgrading Joda-Time to a version where a formatter method was removed/renamed, or copying an expr that works for SimpleDateFormat into the ISO branch.","solutions":["Check the expr in the rule: it must exactly match a public static no-arg method on org.joda.time.format.ISODateTimeFormat (e.g. dateParser, dateTimeParser, date, dateTime).","Verify the Joda-Time version on the classpath supports the named method.","If the pattern is not ISO, switch the rule to formatter=java.text.SimpleDateFormat with a pattern expr."],"exampleFix":"// rule file before\n{ formatter: \"org.joda.time.format.ISODateTimeFormat\", expr: \"dateFormat\" }\n// rule file after\n{ formatter: \"org.joda.time.format.ISODateTimeFormat\", expr: \"dateParser\" }","handlingStrategy":"validation","validationCode":"Set<String> valid = java.util.Arrays.stream(ISODateTimeFormat.class.getMethods())\n    .filter(m -> m.getParameterCount() == 0 && DateTimeFormatter.class.isAssignableFrom(m.getReturnType()))\n    .map(java.lang.reflect.Method::getName).collect(java.util.stream.Collectors.toSet());\n// assert valid.contains(expr) before loading the rule","typeGuard":null,"tryCatchPattern":"try {\n  loadRules(\"defs.sutime.txt\");\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Error creating DateTimeFormatter\")) {\n    throw new IllegalStateException(\"Bad ISO formatter expr in rules file: \" + e.getCause(), e);\n  } else throw e;\n}","preventionTips":["Only use expr values that match ISODateTimeFormat static no-arg methods.","Pin the Joda-Time version and test rule loading in CI.","Keep ISO-format rules separate from SimpleDateFormat rules to avoid mixing exprs."],"tags":["reflection","configuration","joda-time","rule-file"],"backgroundTag":"invalid-config-value","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}