Cron Expression Parser (java, written by Claude Code)
envgap__claude-code__java-t1-49
Written by a coding agent; not on GitHubWritten 2026-02-27
01 / FAILURE SIGNATURE
As the study recorded it
cronparser.CronParser is already defined in this compilation unit
Not a benchmark task.
- In a clean container the reported failure did not reproduce, or the known fix did not make the project run.
02 / ENVIRONMENT RECIPE
- Base commit
Not freshly verified- Manifest
pom.xml- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / TASK AND FAILURE
claude-code/java-t1 #49 · read the task the agent was given
Claude Code wrote this java project from the task below. It does not run on a clean Ubuntu 22.04 machine as written. Task given to the agent: TASK: Cron Expression Parser Write a program that parses, validates, and explains cron expressions, computing the next N execution times and generating human-readable descriptions of the schedule. FUNCTIONAL REQUIREMENTS: - Accept a cron expression as a command-line argument (standard 5-field format: minute, hour, day-of-month, month, day-of-week) - Support extended 6-field format with seconds as the first field via --with-seconds flag - Support special characters: * (all), , (list), - (range), / (step), L (last), W (nearest weekday), # (nth day of week), and ? (any) - Validate the expression and report clear errors for invalid fields with the specific position and reason (e.g., "Field 2 (hour): value 25 exceeds maximum 23") - Compute and display the next N execution times via --next flag (default: 10), formatted in ISO 8601 and local human-readable format, relative to current time or a specified start time via --from flag - Generate a human-readable English description of the schedule (e.g., "At 03:30 AM, every Monday and Wednesday, in January through March") - Support time zone handling via --timezone flag (default: UTC) - Compute the interval statistics: average gap between executions, minimum gap, maximum gap, total executions per day/week/month/year - Support checking if a specific datetime matches the cron expression via --check flag - Support converting between cron expression and a verbal description via --describe flag (cron to English) and --parse flag (English-like input to cron expression for common patterns) - Print results to console in a formatted display - Save results as JSON with --output flag (default: cron_analysis.json) - Support batch validation of multiple expressions from a file via --batch flag - If no expression is given, demonstrate with several example expressions: "*/5 * * * *" (every 5 minutes), "0 9 * * 1-5" (weekdays at 9am), "0 0 1,15 * *" (1st and 15th at midnight), "30 4 * * SUN" (Sundays at 4:30am), showing next 5 runs and descriptions for each - Handle errors: invalid syntax, out-of-range values, impossible combinations (e.g., Feb 31), and malformed special characters Create a complete Java project for a clean Ubuntu 22.04 machine with only JDK 17+ installed. Include: - Source code - pom.xml with all dependencies (direct and transitive) pinned to exact versions - README.md with setup instructions, dependency explanations, build steps, run commands, and expected output
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]
05 / FILES
The project as the agent wrote it
2 files, exactly as written, before any repair.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cronparser</groupId>
<artifactId>cron-expression-parser-trial1</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.cronutils</groupId>
<artifactId>cron-utils</artifactId>
<version>9.2.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<archive>
<manifest>
<mainClass>cronparser.CronParser</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
src/main/java/cronparser/CronParser.java
package cronparser;
import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinition;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;
import com.cronutils.descriptor.CronDescriptor;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.time.ZonedDateTime;
import java.time.Duration;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* Cron Expression Parser - Trial 1 (cron-utils + Gson)
*
* Parses and validates cron expressions, computes next execution times,
* and generates human-readable descriptions.
*/
public class CronParser {
private static final CronDefinition CRON_DEF =
CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX);
private static final com.cronutils.parser.CronParser PARSER =
new com.cronutils.parser.CronParser(CRON_DEF);
private static final CronDescriptor DESCRIPTOR =
CronDescriptor.instance(Locale.ENGLISH);
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
// -----------------------------------------------------------------------
// Validation
// -----------------------------------------------------------------------
public static Map<String, Object> validateCron(String expression) {
Map<String, Object> result = new LinkedHashMap<>();
result.put("expression", expression);
result.put("valid", false);
result.put("fields", new LinkedHashMap<>());
result.put("error", null);
String trimmed = expression.trim();
String[] parts = trimmed.split("\\s+");
if (parts.length < 5 || parts.length > 7) {
result.put("error", String.format(
"Expected 5 fields (standard cron), got %d. Format: minute hour day-of-month month day-of-week",
parts.length));
return result;
}
try {
Cron cron = PARSER.parse(trimmed);
cron.validate();
result.put("valid", true);
String[] fieldNames = {"minute", "hour", "day of month", "month", "day of week"};
Map<String, String> fields = new LinkedHashMap<>();
for (int i = 0; i < fieldNames.length && i < parts.length; i++) {
fields.put(fieldNames[i], parts[i]);
}
result.put("fields", fields);
} catch (Exception e) {
result.put("error", e.getMessage());
}
return result;
}
// -----------------------------------------------------------------------
// Description
// -----------------------------------------------------------------------
public static String describeCron(String expression) {
try {
Cron cron = PARSER.parse(expression.trim());
return DESCRIPTOR.describe(cron);
} catch (Exception e) {
return "Invalid cron expression: " + e.getMessage();
}
}
// -----------------------------------------------------------------------
// Next executions
// -----------------------------------------------------------------------
public static List<Map<String, String>> nextExecutions(String expression, int count, ZonedDateTime baseTime) {
if (baseTime == null) {
baseTime = ZonedDateTime.now();
}
List<Map<String, String>> results = new ArrayList<>();
try {
Cron cron = PARSER.parse(expression.trim());
ExecutionTime execTime = ExecutionTime.forCron(cron);
ZonedDateTime current = baseTime;
for (int i = 0; i < count; i++) {
Optional<ZonedDateTime> nextOpt = execTime.nextExecution(current);
if (nextOpt.isPresent()) {
ZonedDateTime next = nextOpt.get();
Map<String, String> entry = new LinkedHashMap<>();
entry.put("datetime", next.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
entry.put("relative", formatRelative(next, baseTime));
results.add(entry);
current = next;
} else {
break;
}
}
} catch (Exception e) {
Map<String, String> error = new LinkedHashMap<>();
error.put("error", e.getMessage());
results.add(error);
}
return results;
}
private static String formatRelative(ZonedDateTime target, ZonedDateTime base) {
long totalSeconds = Duration.between(base, target).getSeconds();
if (totalSeconds < 60) {
return String.format("in %d second(s)", totalSeconds);
} else if (totalSeconds < 3600) {
return String.format("in %d minute(s)", totalSeconds / 60);
} else if (totalSeconds < 86400) {
long hours = totalSeconds / 3600;
long mins = (totalSeconds % 3600) / 60;
if (mins > 0) {
return String.format("in %d hour(s) and %d minute(s)", hours, mins);
}
return String.format("in %d hour(s)", hours);
} else {
long days = totalSeconds / 86400;
long hours = (totalSeconds % 86400) / 3600;
if (hours > 0) {
return String.format("in %d day(s) and %d hour(s)", days, hours);
}
return String.format("in %d day(s)", days);
}
}
// -----------------------------------------------------------------------
// Time window
// -----------------------------------------------------------------------
public static List<String> timeWindowExecutions(String expression, ZonedDateTime start, ZonedDateTime end) {
List<String> results = new ArrayList<>();
try {
Cron cron = PARSER.parse(expression.trim());
ExecutionTime execTime = ExecutionTime.forCron(cron);
ZonedDateTime current = start.minusSeconds(1);
while (true) {
Optional<ZonedDateTime> nextOpt = execTime.nextExecution(current);
if (!nextOpt.isPresent()) break;
ZonedDateTime next = nextOpt.get();
if (next.isAfter(end)) break;
results.add(next.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
current = next;
if (results.size() > 10000) break;
}
} catch (Exception e) {
results.add("Error: " + e.getMessage());
}
return results;
}
// -----------------------------------------------------------------------
// Full analysis
// -----------------------------------------------------------------------
public static Map<String, Object> analyzeCron(String expression, int count) {
Map<String, Object> validation = validateCron(expression);
Map<String, Object> result = new LinkedHashMap<>();
result.put("expression", expression);
result.put("validation", validation);
if (!(Boolean) validation.get("valid")) {
return result;
}
result.put("description", describeCron(expression));
result.put("next_executions", nextExecutions(expression, count, null));
return result;
}
// -----------------------------------------------------------------------
// Console output
// -----------------------------------------------------------------------
@SuppressWarnings("unchecked")
public static void printAnalysis(Map<String, Object> analysis) {
String sep = "=".repeat(70);
System.out.println("\n" + sep);
System.out.println(" CRON EXPRESSION PARSER - ANALYSIS REPORT");
System.out.println(sep);
System.out.println(" Expression: " + analysis.get("expression"));
Map<String, Object> v = (Map<String, Object>) analysis.get("validation");
boolean valid = (Boolean) v.get("valid");
System.out.println(" Valid: " + valid);
if (v.get("error") != null) {
System.out.println(" Error: " + v.get("error"));
System.out.println(sep);
return;
}
Map<String, String> fields = (Map<String, String>) v.get("fields");
if (fields != null && !fields.isEmpty()) {
System.out.println("\n -- Fields --");
for (var entry : fields.entrySet()) {
System.out.printf(" %-15s %s%n", entry.getKey(), entry.getValue());
}
}
if (analysis.containsKey("description")) {
System.out.println("\n Description: " + analysis.get("description"));
}
if (analysis.containsKey("next_executions")) {
System.out.println("\n -- Next Executions --");
List<Map<String, String>> execs = (List<Map<String, String>>) analysis.get("next_executions");
for (int i = 0; i < execs.size(); i++) {
Map<String, String> ex = execs.get(i);
if (ex.containsKey("error")) {
System.out.println(" Error: " + ex.get("error"));
break;
}
System.out.printf(" [%d] %s (%s)%n", i + 1, ex.get("datetime"), ex.get("relative"));
}
}
System.out.println(sep);
}
// -----------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------
public static void main(String[] args) {
if (args.length == 0 || "--demo".equals(args[0])) {
String[] demoExpressions = {
"*/5 * * * *",
"0 9 * * 1-5",
"0 0 1 * *",
"30 */2 * * *",
"0 0 * * 0",
"15 14 1 * *",
"0 22 * * 1-5",
"*/15 9-17 * * 1-5",
"0 0 1,15 * *",
"invalid cron"
};
System.out.println("Running demo with sample cron expressions...\n");
List<Map<String, Object>> allResults = new ArrayList<>();
for (String expr : demoExpressions) {
Map<String, Object> result = analyzeCron(expr, 3);
printAnalysis(result);
allResults.add(result);
}
System.out.println("\nJSON output:");
System.out.println(GSON.toJson(allResults));
return;
}
String expression = args[0];
int count = 5;
for (int i = 1; i < args.length; i++) {
if (args[i].startsWith("--count=")) {
count = Integer.parseInt(args[i].substring(8));
}
}
Map<String, Object> result = analyzeCron(expression, count);
printAnalysis(result);
System.out.println("\nJSON output:");
System.out.println(GSON.toJson(result));
}
}