rewrite-migrate-java
rewrite-migrate-java copied to clipboard
JSR-310 - Migrate from joda-time to java.time
From the https://www.joda.org/joda-time/ website
The standard date and time classes prior to Java SE 8 are poor. By tackling this problem head-on, Joda-Time became the de facto standard date and time library for Java prior to Java SE 8. Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
I will be running this migrational manually internally soon, and I will add some examples as I find them
Would it make sense to create individual issues for them?
Appreciate you reporting those proposals for recipes here! I think we can start with a GitHub task list initially, as I imagine some will the too small to really warrant a separate pull request. Hope it's easy enough to maybe even tackle a few, as I imagine you'll be looking for a mix of manual and automated changes to complete this migration.
I'm currently trying to implement a first recipe for this. It works so far, but removing the old import fails.
Seems as if the following line does not work:
maybeRemoveImport("org.joda.time.format.DateTimeFormatterBuilder");
Full recipe class:
public class ReplaceJodaAppendSecondofDayRecipe extends Recipe {
private static final MethodMatcher APPEND_SECOND_OF_DAY_INT =
new MethodMatcher("org.joda.time.format.DateTimeFormatterBuilder appendSecondOfDay(int)");
@Override
public String getDisplayName() {
return "Replace Joda 'DateTimeFormatterBuilder.appendSecondOfDay(int)'";
}
@Override
public String getDescription() {
return "Replaces the method call 'org.joda.time.format.DateTimeFormatterBuilder#appendSecondOfDay(int)' with "
+ "'java.time.format.DateTimeFormatterBuilder#appendValue(ChronoField, int)'.";
}
@Override
public Set<String> getTags() {
return Collections.singleton("JODA");
}
@Override
public Duration getEstimatedEffortPerOccurrence() {
return Duration.ofMinutes(5);
}
@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(new NoMissingTypes(), new JavaIsoVisitor<ExecutionContext>() {
private final JavaTemplate newAppendValue =
JavaTemplate.builder("#{any()}.appendValue(ChronoField.SECOND_OF_DAY, #{any(int)})")
.imports("java.time.temporal.ChronoField").build();
@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method,
ExecutionContext executionContext) {
if (APPEND_SECOND_OF_DAY_INT.matches(method)) {
method = newAppendValue.apply(getCursor(), method.getCoordinates().replace(), method.getSelect(),
method.getArguments().get(0));
maybeRemoveImport("org.joda.time.format.DateTimeFormatterBuilder");
maybeAddImport("java.time.format.DateTimeFormatterBuilder", false);
maybeAddImport("java.time.temporal.ChronoField");
return method;
}
return super.visitMethodInvocation(method, executionContext);
}
});
}
}
Any idea what's wrong?
Great to see you got started on this @michael-schnell ! Much appreciated; I don't immediately see a what's wrong yet, but feel free to open up a draft pull request, as that's a little easier to checkout locally and provide feedback and fixes on.
I think doing the whole Joda part will be >100 recipes as there are many things to migrate for Joda to Java Time.
I think I will open a bug issue with code & test - Then this can be figured out separately.
I think doing the whole Joda part will be >100 recipes as there are many things to migrate for Joda to Java Time.
I think I will open a bug issue with code & test - Then this can be figured out separately.
Looking forward to it, thanks!
OK, here it is: https://github.com/openrewrite/rewrite-migrate-java/issues/262 - I created a demo project that is linked in the issue. Should be easy to check out and run the tests.
Great! Linking the recipe back here so we know where to pick off from next: https://github.com/michael-schnell/openrewrite-issue/pull/1
@michael-schnell Did you end up developing more recipes to aid the migration away from Joda time? If there's anything you can share that would be much appreciated!
Unfortunately not. We ended up in a big manual migration for the ~20 projects. Especially tricky topics were:
- Different "null" handling in several functions between Joda and Java Time
- 6 digit milliseconds in Java Time vs 3 digits in Joda (Could also be a problem for JPQL/SQL queries that try to find old data in the DB that were written with Joda and now read by Java Time).
- Converter configuration for JAX-B in XML config files
- Code generator configuration in Maven pom.xml files (plugins)
- Some silly functions in Joda that accept values that are no longer valid in Java Time (like calculating a diff with "begin"/"end" and Joda accepts "null" for one of the values interpreted as "now" where Java Time does not)
- Missing functions in Java Time that were available in Joda (see https://www.threeten.org/threeten-extra/)
- Handling (calculation) of the time zone, which is quite different in Joda and Java Time
- Choosing the right replacement for Joda "DateTime" (OffsetDateTime, ZonedDateTime or sometines even LocalDateTime in Java Time)
Thanks for the detailed report! Really helps to have as list of things to look out for. Clearly not an easy one to one replacement. :/
With the addition of a first batch of Joda time related recipes I propose we close this catch all issue, and then potentially open new individual issues (or PRs) for cases not yet covered, such that it's easier to track demand and progress.
- https://github.com/openrewrite/rewrite-migrate-java/pull/567
Thanks all!