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

Proposal to add a duration type #717

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

salmangano
Copy link

When using toml as a configuration file format it is often useful to specify a duration. Although an integer can be used for this purpose, time offsets are so common that an explicit duration type with definite units would enhance readability and safety.

Many programming languages have explicit support for durations. C++ has std::chrono::duration types (https://en.cppreference.com/w/cpp/chrono/duration). Python has timedelta (https://docs.python.org/3/library/datetime.html#timedelta-objects). Java has https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html. Hence, toml implementations should be able to adopt this relatively easily.

@eksortso
Copy link
Contributor

I've been talking up an ISO 8601-inspired duration format in #514. Want to bring up your format there? Because I think it would have a receptive audience.

Your duration proposal seems okay so far. I like the unambiguous unit names. But since float quantities are not permitted, could we chain durations with different units together? For example: 4mins 33secs.

For aesthetic reasons, I would also want to allow whitespace and to make the final "s" optional, so that 10 min would be a legal equivalent to 10mins. Parsers would need to differentiate between a duration and an integer partway through, anyway, so those stylistic changes wouldn't make too much difference but would make the duration easier to read.

@ChristianSi
Copy link
Contributor

ChristianSi commented Mar 29, 2020

I like this as well, with the modifications suggested by @eksortso. Additionally I'd propose to support the standardized SI-compatible abbreviations in so far as they differ from the words used here:

hour(s) = h
sec(s) = s
millisec(s) = ms
microsec(s) = μs
nanosec(s) = ns

(See List of SI prefixes and Units outside the SI that are accepted for use with the SI.)

Additionally, "day(s)" (abbrev: d) should be supported.

"Units include" should be changed to "Supported units are" to avoid fragmentation.

Another point worth mentioning: If units are chained, they obviously should be in order, but they should also be normalized appropriately. For example, you can write 135 seconds as "135 s" or as "2 min 15 s", but not as "1 min 75 s".

Finally, it seems that a file slipped into the PR that doesn't belong there (examples/example-v0.5.0.toml).

@ChristianSi
Copy link
Contributor

ChristianSi commented Mar 29, 2020

Moreover, I must say that using a fractional part with seconds (and smaller units such as millisecs) feels quite natural to me. But, of course, if that's the case, then these units should not be chained (a part using floats must always be the last one in a chain).

This might make things too complicated, but I nevertheless want to mention it.

Also, some apps might need more than nanosecond precision and would be unable to use the proposed format if it forced them to round the duration to the nearest whole nanosecond.

@salmangano
Copy link
Author

I don't think chaining is strictly necessary as one can always drop down to the next lower unit. 1min 30 secs can be represented as 90secs. This matches how every lanuage I have seen handles durations. They are always in a single unit. Hence, the added complexity at the toml level seems strictly unnecessary .

After add this PR I noticed there was already an open proposal on the TOML wiki. Perhaps that is a better place to discuss. #514

@eksortso
Copy link
Contributor

This seems like the best place to discuss the details of this particular proposal. The issue thread can put it into context, and can compare & contrast it with other proposals.

That said, I'll still put out a PR for the ISO 8601-based format. I don't intend to undercut your PR though, @salmangano. I think it's promising. And I think we can learn off each other's work and experience.

@eksortso
Copy link
Contributor

Now, regarding those details...

Chaining would make durations more useful with minimal extra effort. Python accepts timedelta values that include groups of different units. (Nanoseconds would need to be converted though.) As for C++, durations can be added together, it looks like. So there is no difficulty in putting several units together in one duration expression. These languages can handle the unit conversions that would be involved.

I agree with @ChristianSi that putting the units in order is important, but I disagree that they must be normalized when written. The ISO 8601 standard doesn't require normalized quantities, but the strict unit order is explicitly defined.

I've already figured out roughly how to express all this in ABNF, so if I persuade you, you can adapt the ABNF for your own format.

@eksortso
Copy link
Contributor

Fractional units ought to be allowed. Both C++ and Python permit arithmetic number types. So we could safely allow floats instead of integers. But I'd only allow the last expressed unit to have a fractional part, per ISO 8601.

Negative unit values are allowed by both languages, even though ISO 8601 doesn't appear to allow them. @salmangano, your format expresses negative durations naturally. That's a good thing.

Again, my rough draft of the ABNF will cover this stuff explicitly. Once I post it, I'll point you to it.

@abelbraaksma
Copy link
Contributor

abelbraaksma commented May 18, 2020

But I'd only allow the last expressed unit to have a fractional part, per ISO 8601.

While 8601 allows it on the last, but any part, I propose to only allow it on seconds. This is also the approach that the standards body of W3.org adopted.

It's non-trivial what it means to have fractional minutes, hours or even days, months or years. You're better of keeping it simple, and users will quickly come to understand that only the seconds part can be decimal (or double).

Btw, 8601 allows weeks, and an abbreviated format (without the letters). I wouldn't use either of those either (but I think there was already consensus on that in the main thread).

even though ISO 8601 doesn't appear to allow them

They don't disallow them, which in standard's parlor usually means that they allow them. My suggestion would be, again, to keep it simple: either the whole duration is negative, or the whole duration is positive. Subtracting parts is complicated, and without timezone information not even reliably possible. What's more, you'll get a different amount of days depending on the time of year (daylight saving time) if you allow subtractions of parts.

Ending up with a duration that's either years and months, or days and time means you have ordered types. These types are exact. Once you mix these, they mean something else depending on time of year.

That's OK, and ultimately up to implementers, but doing all that for positive or negative durations is already quite some work. If independent parts can be positive and negative it's that much harder. And likewise, that much harder to explain to end users and in spec prose.

@eksortso
Copy link
Contributor

@abelbraaksma Maybe #514 would be a better place to bring all these points up. It would apply to any and all duration proposals. In any case, it's worth limiting the scope of discussion to durations as a type of multidimensional number system, just because TOML itself won't be doing datetime arithmetic any time soon.

@salmangano Could we persuade you to allow fractional seconds, with at least millisecond-level precision required?

@abelbraaksma
Copy link
Contributor

abelbraaksma commented May 19, 2020

just because TOML itself won't be doing datetime arithmetic any time soon.

I realize that, but the main purpose of durations is to usually subtract or add them to time or date data types. That'll be done outside of toml, of course.

I'll go to the main issue ;)

@zhuoqiang
Copy link

I find the current time type is also OK for representing duration, except it could not be negative.

if we allowed time to be negative, that could sovle some of the basic usage of duration:

# timeout duration 1min 3 seconds and 123 ms
timeout = 00:01:03.123

# 1 hour ahead of time, sadly we could not add `-` in current toml spec ....
offset_duration = -01:00:00

@abelbraaksma
Copy link
Contributor

I find the current time type is also OK for representing duration, except it could not be negative.

I'm not so sure it's a good idea to use one type for such distinct purposes. Durations an be added, subtracted, divided or even multiplied in most languages. DateTime, Date or Time types cannot (you can add a duration to a Date, but you cannot add Date to a Date). Using a different syntax allows parsers to map them to specific types in the parser.

@tintin10q
Copy link

Yeah I agree with this you can just store 2 date times and calculate the difference in whatever loads the toml file. Besides there is no ISO duration standart.

I find the current time type is also OK for representing duration, except it could not be negative.

I'm not so sure it's a good idea to use one type for such distinct purposes. Durations an be added, subtracted, divided or even multiplied in most languages. DateTime, Date or Time types cannot (you can add a duration to a Date, but you cannot add Date to a Date). Using a different syntax allows parsers to map them to specific types in the parser.

@eksortso
Copy link
Contributor

Yeah I agree with this you can just store 2 date times and calculate the difference in whatever loads the toml file. Besides there is no ISO duration standart.

@tintin10q You agree, but then you immediately contradict yourself. @abelbraaksma made a case for a distinct syntax for durations. I agree with them, and have in fact made a case for using an ISO-type standard. I said so explicitly here a few years ago, and like I mentioned, that conversation was in #514.

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

Successfully merging this pull request may close these issues.

7 participants