-
Notifications
You must be signed in to change notification settings - Fork 966
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
Add support for getting value as Period #478
Conversation
Signed cla |
Thanks! Looking pretty good. We might consider a unit test in UnitParserTest.scala covering some of the weird corner cases (especially error handling), and maybe update HOCON.md to describe how periods are parsed differently from durations? there's a section in there for durations already. |
@havocp how's that looking? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is mergeable now; any thoughts from anyone else? Thanks so much!
return parsePeriod((String) v.unwrapped(), v.origin(), path); | ||
} | ||
|
||
public TemporalAmount getTemporal(String path){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this one need @OverRide?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, let me add that
* Gets a value as a java.time.temporal.TemporalAmount. | ||
* This method will first try get get the value as a java.time.Duration, and if unsuccessful, | ||
* then as a java.time.Period. | ||
* This means that values like "5m" will be parsed as 5 minutes rather than 5 months |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the ambiguous values here ("m" and no units?) are fairly dangerous perhaps ... an option would be to outright prohibit them... though that could be confusing also. I'm OK with what you have here but do wonder if there's an option that doesn't leave a pitfall for whoever is writing the config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had that thought as well. I think it it can be confusing, but most applications will use either getPeriod
or getDuration
and will not need to worry. For me it's just balancing how many people will be confused by m
being unavailable vs how many will use getTemporal
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TemporalAmount
is not really meant to be used in application code. According to the javadoc:
This interface is a framework-level interface that should not be widely used in application code. Instead, applications should create and pass around instances of concrete types, such as Period and Duration.
If you're going to force users to decide how to handle the TemporalAmount
returned from this method, you might as well let them implement the relatively simple logic in getTemporal
themselves, so they can decide how to handle the ambiguity of minutes/months.
In a practical sense, I think it would be more useful to have getDuration
support weeks, months, and years as units using standard lengths for those units. In most cases the underlying API I'm using (e.g. max-age for a cookie) expects a precise number of nanoseconds, so a Period
is usually not what I want anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had assumed that the config library would be used by framework creators as well as directly by applications. Is there a convenient way we can surface the ability to get a TemporalAmount
without putting it directly on the Config
interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kag0 can you describe a use case for a framework creator?
Is there a convenient way we can surface the ability to get a TemporalAmount without putting it directly on the Config interface?
What does it mean to "get a TemporalAmount" to you? What kind of temporal amounts should we support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case "get a TemporalAmount" to me just means getting either a Duration
or Period
but not knowing which.
I could imagine a framework creator might have some setting where they might want to do OffsetDateTime.now().plus(maintenanceReminderInterval)
and wouldn't want to constrain the user to a period or duration, but do want to prevent taking a TemporalAmount
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I feel like in that case you're adding the possibility to return Duration
as a hack because Period
doesn't support units smaller than days. Ideally you want to be able to return a type that supports both, such as PeriodDuration from threeten-extra.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also expect to be able to write
foo = P1Y2M3D
using the ISO-8601 period format.
It seems like the current implementation does not support multiple temporal units, so that format would be an unambiguous way to provide support for all possible Period
s.
* Gets a value as a java.time.temporal.TemporalAmount. | ||
* This method will first try get get the value as a java.time.Duration, and if unsuccessful, | ||
* then as a java.time.Period. | ||
* This means that values like "5m" will be parsed as 5 minutes rather than 5 months |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TemporalAmount
is not really meant to be used in application code. According to the javadoc:
This interface is a framework-level interface that should not be widely used in application code. Instead, applications should create and pass around instances of concrete types, such as Period and Duration.
If you're going to force users to decide how to handle the TemporalAmount
returned from this method, you might as well let them implement the relatively simple logic in getTemporal
themselves, so they can decide how to handle the ambiguity of minutes/months.
In a practical sense, I think it would be more useful to have getDuration
support weeks, months, and years as units using standard lengths for those units. In most cases the underlying API I'm using (e.g. max-age for a cookie) expects a precise number of nanoseconds, so a Period
is usually not what I want anyway.
Is there support currently for doing this with durations? If so then I think there is an argument for adding it. But if not, can we make it a separate issue? Presumably users would use the smallest applicable unit to describe the period they needed. |
No, but that's not a problem because Durations are not based on the ISO-8601 calendar. That said, If the goal is simply to support a number with unit it would be far easier to use, and more semantically correct, if we returned a class representing a pair of |
A very good point. With that in mind, parsing ISO periods should definitely be supported. |
Expanding on my earlier proposal, we could have a general method to parse a numeric value with a chronological unit. We could have a type like this: public final class ConfigChronoAmount {
private final long amount; // maybe should be BigDecimal/double?
private final ChronoUnit unit;
// ... constructor, getters ...
} and add a method Note that it is trivial to convert this to a duration using the estimated values of the units ( The only thing I'm not sure about is whether we should support fractional units like Perhaps all that is outside the intended goal of this PR. Just mentioning the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great! Merging this. For those who are interested in support for more formats, please open a separate issue.
* href="https://github.com/typesafehub/config/blob/master/HOCON.md">the | ||
* spec</a>. This method never returns null. | ||
* | ||
* @since 1.3.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be @since 1.3.2
* This method will first try get get the value as a java.time.Duration, and if unsuccessful, | ||
* then as a java.time.Period. | ||
* This means that values like "5m" will be parsed as 5 minutes rather than 5 months | ||
* @param path path expression |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing the @since 1.3.2
annotation
Add support for getting value as Period
from issue #473
I think
parseDuration
andparsePeriod
could probably be re-worked to be a little more dry (something withChronoUnit.isTimeBased
rather thanTimeUnit.toNanos
), but didn't feel the need to do that now as this is a pretty superficial feature.