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? |
havocp
left a comment
There was a problem hiding this comment.
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.
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. |
There was a problem hiding this comment.
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.
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.
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.
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.
@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.
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.
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.
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 Periods.
| /** | ||
| * 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. |
There was a problem hiding this comment.
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 |
2m
left a comment
There was a problem hiding this comment.
Looking great! Merging this. For those who are interested in support for more formats, please open a separate issue.
| * "10d" or "5w" as documented in the <a | ||
| * href="https://github.com/typesafehub/config/blob/master/HOCON.md">the | ||
| * spec</a>. This method never returns null. | ||
| * |
| * 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.
Missing the @since 1.3.2 annotation
Add support for getting value as Period
from issue #473
I think
parseDurationandparsePeriodcould probably be re-worked to be a little more dry (something withChronoUnit.isTimeBasedrather thanTimeUnit.toNanos), but didn't feel the need to do that now as this is a pretty superficial feature.