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

WIP lib.duration: add basic duration functions #43852

Closed
wants to merge 1 commit into from

Conversation

rycee
Copy link
Member

@rycee rycee commented Jul 20, 2018

Motivation for this change

I wanted a more structured and unified way to represent various time durations (e.g. timeouts and such things) in Home Manager and figured it was general enough that there might be an interest to add it to Nixpkgs instead of just HM.

While the majority of code is centered around a few utility functions, my main interest is the included duration type for the module system. Using it you can have a module along the lines

{ config, lib, ... }:

with lib;

{
  options = {
    value = mkOption {
      type = types.duration;
      apply = durations.parse;
    };

    result = mkOption {
      type = types.str;
    };
  };

  config = {
    value = "1d 12h";
    result = "In millis: ${toString (durations.toMillis config.value)}";
  };
}

and result would then contain "In millis: 129600000".

I don't consider this ready for merge yet, this is mainly for discussion whether it is of any interest for inclusion in Nixpkgs.

Things done

The included tests pass.

@rycee
Copy link
Member Author

rycee commented Jul 20, 2018

Yeah, the current format is (intentionally) a subset of the systemd.time format and in principle it shouldn't be too tricky to expand to the full format (as far as it is demonstrated in the man page). But looking at the systemd code it does seem like it supports things like "5.5s 0.5ms" which makes things more complicated… For my own purposes a subset of the systemd format is sufficient.

Another difficulty I'm facing is that I would like to be able to pretty print the duration. I.e., I'd like to have

toString (parse "150h") == "6d 6h"

but this is a bit tricky without having a remainder operator 😕

Also I wish there were some convenient way to convert from a Nix float value to an int value.

@rycee
Copy link
Member Author

rycee commented Jul 24, 2018

@volth Of course! Thanks, I hadn't thought of it 🙂

I've updated the PR to more closely match the systemd format and also extended the toString support. With the changes we have

toString (parse "8d 30h 0m 177s 1ms") == "1w 2d 6h 2m 57s 1ms"

#
# nix-repl> with lib.durations; parseWithIntFallback "y" "foo"
# { error = "Invalid duration \"foo\": Expected natural number but got \"\"."; }
parseWithIntFallback = fallbackUnit: value:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also planning to add a corresponding durationWithIntFallback type.

Copy link
Member

@zimbatm zimbatm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks useful! Are there any places where it could already be used in nixpkgs?

else foldl' add (duration 0) lstScaled;

# Duration value constructor.
duration = ms: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to mkDuration to indicate that it's a constructor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea, fixed.

Also include a module system option type for durations.
@rycee
Copy link
Member Author

rycee commented Aug 6, 2018

@zimbatm I think many NixOS options that contains the string "second" or "minute" are candidates for using this type (well the one with int fallback for backwards compatibility). Taking two random examples from the manual:

boot.initrd.luks.devices.<name?>.yubikey.gracePeriod could be

boot.initrd.luks.devices.<name?>.yubikey.gracePeriod

    Duration of time to wait before attempting to find the Yubikey.

    Type: duration

    Default: 2 seconds

and

services.factorio.autosave-interval could be

services.factorio.autosave-interval

    Autosave interval.

    Type: null or duration

    Default: null

    Example: 10 minutes

@basvandijk
Copy link
Member

basvandijk commented Aug 7, 2018

This might also be used in the strongswan-swanctl module which also uses durations. I even added a TODO to check for the correct duration format.

@edolstra
Copy link
Member

Nix is not a general purpose language. We absolutely should not be parsing durations in Nix code since this sort of thing slows down NixOS/Nixpkgs evaluation substantially. For specifying durations in NixOS options, I don't think we need much more than a set of multipliers (e.g. timeout = 123 * lib.durations.minute), or if you want to get superfancy, a duration type (e.g. timeout = lib.durationFromMinutes 123).

@rycee rycee closed this Nov 2, 2018
@rycee rycee deleted the lib/duration branch November 2, 2018 21:52
@rycee
Copy link
Member Author

rycee commented Nov 2, 2018

Closing a few left-over issues.

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.

None yet

5 participants