Adding a duration type to NixOS?

I opened PR #43852 a while ago that introduces a lib/durations.nix file with basic support for “durations” and also a corresponding module type duration.

By a “duration” I mean a string much like “1w 2d 6h 2m 57s 1ms” to indicate a length of time. The library includes some parsing, pretty printing, and extraction functions.

I mainly created this to have a consistent and human-understandable method of specifying durations in Home Manager modules but figured it could be useful in NixOS as well. Basically what I find is that, some programs expects a timeout value in milliseconds, another in seconds and we end up using types.int and have the documentation or option name indicate the actually expected type.

Does this seem like a good idea?

1 Like

The only issue I can see is how there could be a loss of intention when something using the duration type converts to seconds, and a user uses one of month or year. The scheduling of events based on month in that case could cause surprises. Though I do understand how it’s the specified systemd.time behaviour.

It may need a strongly worded warning for module implementors to not rely on month and year when relying on the durations to schedule things, and converting to seconds. Though, this wouldn’t be useful as it would be the users that would end up using month and year. Maybe allow or disable ambiguously scheduled types as a parameter?

I originally didn’t include month and year for this reason. But @volth mentioned that it might be good to include to closer match the systemd format. I reused the definition from systemd.time(7) where a month is defined as 30.44 days and a year as 365.25 days. So there is a specific number of seconds per month and year given this definition.

Personally I don’t have much opinion about months and years since I haven’t had need to schedule things so rarely :slightly_smiling_face:

I believe it hinges on whether the converted format will have loss of precision behind the intention.

When the duration format goes from “3 months” to “3 months”, it’s fine, but when it goes from “3 months” to 3 * 30.44d, the intention isn’t the same.

Not that it is necessarily an error, but a situation which may need to be known. A well-written note about the semantics here could be fine enough.

I’m not 100% sure where one would use the duration type, so I might overlook something here, but I feel like since the context where the duration would be used is, well, nix, and it’s very stateless nature, then users are probably more prone to thinking that “duration 1 month” means “on average 1 month” or “approximately one month” rather than “exactly 1 month from this specific instance in time”.

I feel like the type is true to the zen of nix as is.

I think maybe it’d be better to leave aside month and year for the time
being, as you initially did, and see how things evolve?

So long as a clear error message is shown when trying to use them, I
think an error message saying “You tried to use months, but it is not
defined. Please use 30d instead and comment on [GitHub issue] if you
would really want to have months” would be enough for a first run, and
then we would get some insight on what people actually expect when
inputting months :slight_smile:

Overall, I’d guess said GitHub issue would be receiving next to no
comments, though, but that’s only my opinion.

Yes, I agree completely that documenting the behavior would be important. I’ll work on adding to the manual when I have some spare time.

1 Like

Yeah, I suspect use of durations of months and years is rare. The longest duration I see mentioned in the option descriptions is services.matrix-synapse.user_creation_max_duration, which defaults to 2 weeks in milliseconds, i.e., 1209600000 or “2w” in the format of the duration type :wink: