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

Duration Infinity is converted to 0 by some methods #1178

Open
jsejcksn opened this issue Apr 12, 2022 · 4 comments
Open

Duration Infinity is converted to 0 by some methods #1178

jsejcksn opened this issue Apr 12, 2022 · 4 comments

Comments

@jsejcksn
Copy link
Contributor

jsejcksn commented Apr 12, 2022

Describe the bug

I see that Infinity has been discussed in some other issues, but I don't see discussion around Duration.

Luxon treats Infinity as a valid duration, but some methods return 0 as the value representation.

To Reproduce

Here's an inexhaustive example which demonstrates inconsistency:

const dur = Duration.fromMillis(Number.POSITIVE_INFINITY);
dur.equals(Duration.fromMillis(Number.POSITIVE_INFINITY)); //=> true
dur.isValid; //=> true
dur.invalidReason; //=> null
dur.invalidExplanation; //=> null
dur.milliseconds; //=> Infinity
dur.toObject(); //=> { milliseconds: Infinity }
dur.normalize().toObject(); //=> { milliseconds: Infinity }
dur.toHuman(); //=> '∞ milliseconds'
dur.toISO(); //=> 'PTInfinityS'
dur.toString(); //=> 'PTInfinityS'

// 🤨
dur.toMillis(); //=> 0
dur.valueOf(); //=> 0
dur.as('milliseconds'); //=> 0
dur.toFormat('S'); //=> 0

Actual vs Expected behavior

The latter methods above should also return a representation of Infinity, and not 0.

Version information
Key Value
OS macOS
Browser Chrome 100.0.4896.88
Luxon 2.3.1
@icambron
Copy link
Member

icambron commented Apr 22, 2022

I'd take fixes for that. What should toISO() return, though? I'm pretty sure PTInfinityS is bad, and is just the result of toString()ing the number

@jsejcksn
Copy link
Contributor Author

What should toISO() return, though? I'm pretty sure PTInfinityS is bad, and is just the result of toString()ing the number

@icambron From my research (note that I haven't purchased the updated, full text of the standard, so I don't have access to read any deviations from what has been published in open drafts) ISO 8601 and its extensions don't address an infinite duration.

In an extension, open-ended intervals are defined using .. notation (e.g. ../2022-04-23 or 1900-01-01/..). Section 3.7 "Mutual agreement" describes using valid syntax with invalid values by agreement between parties, and this has given rise to such usage as 9999-13-00 to represent an indefinite future date by convention only.

So... the direct answer to your question is that, currently, there is no valid ISO representation of an infinite duration.

With the above in mind:

Perhaps it is sensible to consider infinite durations as invalid, and to create a new enumeration for the invalidReason property such as "infinite duration".

(Speaking of enumerations, can you point me to where the ones produced internally are located? It seems useful at minimum, and even necessary in some cases to have access to those enumerations for matching during error-handling and testing, but I didn't find them in a search of the repository.)

IMO, while PTInfinityS is absolutely not spec, it is a logical and useful representation to a human. I don't know whether or not invalid Luxon durations have a toISO() method: if so, would spec compliance matter in that case?

Ultimately, I have a need to represent infinite durations and want a reliable way to know whether a duration is infinite or not.

@icambron
Copy link
Member

icambron commented May 9, 2022

Thinking about this a bit more, I agree with this:

Perhaps it is sensible to consider infinite durations as invalid, and to create a new enumeration for the invalidReason property such as "infinite duration".

They're just not going to work in a consistent way, and we should just ban them.

Somewhat embarassingly, there's no enum, they're just strings. For example, in Duration.fromISO(), you see this line:

      return Duration.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`);

"unparsable" becomes invalidReason and that second arg becomes invalidExplanation. The idea is that the first one is really an enumeration and the second one might have specific details in it.

@Maxim-Mazurok
Copy link
Contributor

Maxim-Mazurok commented Dec 5, 2022

I'm also having trouble representing an infinite duration, my use case is representing a lifetime warranty.
I was doing this: Duration.fromObject({ days: Infinity }).shiftToAll().toHuman() which returns NaN years, NaN months, NaN weeks, NaN days, NaN hours, NaN minutes, NaN seconds, NaN milliseconds

Trying to use an open interval Interval.fromDateTimes(DateTime.now(), DateTime.fromMillis(Infinity)) produces an error: {"e": undefined, "invalid": {"explanation": null, "reason": "missing or invalid end"}, "isLuxonInterval": true, "s": undefined}

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

No branches or pull requests

3 participants