Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with Duration Parsing #1963

Closed
RapidTransit opened this issue Nov 11, 2023 · 4 comments · Fixed by #2424
Closed

Issue with Duration Parsing #1963

RapidTransit opened this issue Nov 11, 2023 · 4 comments · Fixed by #2424
Milestone

Comments

@RapidTransit
Copy link

RapidTransit commented Nov 11, 2023

I was working on something unrelated and needed to parse a string like 10s or 10ms, I did a quick search in my project and came up with:

private enum TimeUnit {
NANOS("ns,nano,nanos,nanosecond,nanoseconds", ChronoUnit.NANOS),
MICROS("us,micro,micros,microsecond,microseconds", ChronoUnit.MICROS),
MILLIS("ms,milli,millis,millsecond,milliseconds", ChronoUnit.MILLIS),
SECONDS("s,second,seconds", ChronoUnit.SECONDS),
MINUTES("m,minute,minutes", ChronoUnit.MINUTES),
HOURS("h,hour,hours", ChronoUnit.HOURS),
DAYS("d,day,days", ChronoUnit.DAYS);
private final String[] descriptions;
private final ChronoUnit timeUnit;
TimeUnit(final String descriptions, final ChronoUnit timeUnit) {
this.descriptions = descriptions.split(",");
this.timeUnit = timeUnit;
}
ChronoUnit getTimeUnit() {
return this.timeUnit;
}
static Duration getDuration(final String time) {
final String value = time.trim();
TemporalUnit temporalUnit = ChronoUnit.MILLIS;
long timeVal = 0;
for (TimeUnit timeUnit : values()) {
for (String suffix : timeUnit.descriptions) {
if (value.endsWith(suffix)) {
temporalUnit = timeUnit.timeUnit;
timeVal = Long.parseLong(value.substring(0, value.length() - suffix.length()));
}
}
}
return Duration.of(timeVal, temporalUnit);
}
}

I'm not sure if it is a bug, but when it finds the first matching suffix it should immediately return, other wise it always falls through to SECONDS for most of the covered cases and the order is slightly messed up as the SECONDS could produce an early match for MINUTES, HOURS, and DAYS.

@ppkarwasz
Copy link
Contributor

@RapidTransit,

Thank you for catching this bug. As far as I can see, most invocations of this code (especially if the unit ends in s) ends up with an uncaught NumberFormatException.

@rgoers, this is only used in the Kubernetes plugin. Can we replace the entire logic with Duration.parse?

@ppkarwasz ppkarwasz added this to the 2.x milestone Nov 13, 2023
@ppkarwasz ppkarwasz modified the milestones: 2.x, 2.24.0 Mar 27, 2024
@ppkarwasz
Copy link
Contributor

Since the only users of PropertiesUtil#getDurationProperty has been removed in #2218, I propose to replace the implementation of the method with a simple Duration#parse.

@vy
Copy link
Member

vy commented Mar 28, 2024

@ppkarwasz, if there are no other system properties that need a TypeConverter<Duration>, but the Kubernetes module, which is planned to be removed, remove this TypeConverter<Duration> along with it too, please. Note that this implies no TypeConverter<Duration>, not even one using Duration.parse(String).

@ppkarwasz
Copy link
Contributor

@vy,

In Log4j Core there is no java.time.Duration converter, there is however an o.a.l.l.c.a.rolling.action.Duration converter created in the well-known spirit of bringing to Java 7 users Java 8 features today!

I can deprecate it and replace its usages with java.time.Duration, but I'd rather do it in a separate PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants