Re: [PHP-DEV] [RFC] Duration class
[email protected] ("Marc B.")
| Newsgroups | php.internals |
|---|---|
| Message-ID | <[email protected]> |
On 24.06.26 13:03, Tim Düsterhus wrote: > Hi > > Am 2026-06-23 08:19, schrieb [email protected]: >> What you feel unintuitive is just addition of two numbers in >> different units "$seconds + $nanoseconds * 1_000_000_000", which for >> me feels very natural. > > No, what I feel is unintuitive is that the magnitude of the Duration > will because *smaller* when the magnitude of the nanosecond value > becomes *larger*. You could phrase it as “the representation of a > single value as two values with different signs is unintuitive”. The > different units are not the issue, the different sign is. > >> With the negative flag it's more complicated "($negative ? -1 : 1) * >> $seconds + $nanoseconds * 1_000_000_000" to obtain the correct meaning. > > This example snippet is incorrect. The correct version would be: > `($negative ? -1 : 1) * ($seconds + $nanoseconds * 1_000_000_000)` > (with parentheses). In fact this snippet includes the snippet you > consider to be “very natural”, it just makes the application of the > sign explicit and effectively applies it to both components (instead > of one component like Java does), which means that the magnitude of > `$seconds` is a correct lower bound for the magnitude of the entire > Duration. > > To give a specific example in Java > (https://www.programiz.com/online-compiler/1Iilpy8ncbwRS): > > import java.time.Duration; > > class Main { > public static void main(String[] args) { > Duration d = Duration.parse("PT-59.5S"); > System.out.println(d.getSeconds()); > System.out.println(d); > } > } > > This will print: > > -60 > PT-59.5S > > Just by looking at the “seconds” component it looks like the Duration > is at least 1 minute long. But it isn't, because if the second > component is negative, the larger the value of the nanosecond > component is, the shorter the duration will be. An alternative would be to use the same sign for nanoseconds as for seconds (while 0 seconds is neither positive or negative) 1.5s = 1 second + 500_000_000 nanoseconds -1.5s = -1 seconds + -500_000_000 nanoseconds -0.5s = 0 seconds + -500_000_000 nanoseconds No negative flag needed to be handled separately. > >> In the RFC you say >>> Negative durations are represented by an explicit $negative >>> property. This makes it easy to deal with absolute values by just >>> ignoring the value of $negative. >> >> That's just not true - you can't simply ignore the sign you have to >> deal with it no matter what. it's changing your calculations, it'g >> getting rejected on passing it to other functions. >> On the same time the current API makes it harder to deal with >> negative durations as they can not be constructed directly and are >> not allowed as operator arguments. > > The statement is correct, if you are interested in absolute values, > you have the magnitude right there and can ignore the `$negative` > flag. But to make it even easier, we added the `->absolute()` method > that just clears the sign. Simply replacing seconds by abs(seconds) in > Java's representation would *not* be correct. In fact the OpenJDK > implementation defers to a BigDecimal calculation to flip the sign, > which is not an option for PHP, because the minimal PHP build doesn't > include either GMP or bcmath. "... if you are interested in absolute values, you have the magnitude right there and can ignore the `$negative` flag." No I can't * adding two durations does NOT guaranties a value greater than the two * passing a negative duration as timeout might throw * ... Thanks for adding `absolute()` - that's very helpful > >> Java does not have property hooks (as far as I know) but PHP now has. >> That's very powerful and makes it possible to hide implementation >> details without exposing everything as getters. >> >> $duration->seconds // 0-59 >> $duration->totalSeconds >> $duration->nanoseconds // 0 - 999_999_999 >> $duration->totalNanoseconds >> $duration->milliseconds // 0 - 999 >> $duration->totalMilliseconds >> // maybe later >> $duration->picoseconds // 0 - 999_999_999_999 >> $duration->totalPicosecond >> >> As a user you don't need to care that much of the internal >> representation. > > The currently proposed properties are intended to be used by the user > directly. That's why they are public. This does not answer the meaning difference of `seconds` vs. `nanoseconds` - it's confusing naming that `seconds` is the total amount of seconds in this duration but `nanoseconds` is the number of fractions of a second. > > Best regards > Tim Düsterhus