← Back to context

Comment by wuster

6 years ago

Best part of reading this is coming away having learned the existence of units the CLI. How did I spend 20 years on the shell and not have needed or discovered this?

One thing I got bitten by was the handling of Fahrenheit/Celsius, because it's a non-linear conversion between the two. When you ask to convert `10 degC` to `degF` you get 18, which is the delta of ºF corresponding to increment of 10ºC. To get the absolute temperature, you have to ask to convert `tempC(10)` to `tempF` which is 50, as expected.

https://www.gnu.org/software/units/

  • "Non-linear" threw me off for a second - I almost never see the mathematically correct definition of linear in computer science spaces. For anyone wondering, Celsius to Fahrenheit is an affine transform, technically not linear, because you have to add an offset, not just multiply.

    • On the other hand, an equation of the form y = a x + b is a linear equation. If you have Celsius and want Fahrenheit you accomplish that by applying a linear equation (F = 1.8 C + 32), so I certainly can't fault people for saying that the transformation they are doing is linear.

      I wonder what people would say for something using an equation of the form y = a x^2 + b x + c to transform something? I can't say that I've heard anyone talk of quadratic transformations. On the other hand, I can't think of ever transforming anything with a quadratic equation, so never had the need t speak of it.

      (Also, he called it a linear conversion, not a linear transformation).

  • FWIW, units on macOS (not GNU) handles conversion of `10 degC` to `degF` correctly, although it dates back to 1993.

    It seems that GNU units at some point added support for several non-linear units, which may have prompted them to rethink their syntax.

Be aware that currencies are stuck with rates from several years ago and don’t update.

  • Running `sudo units_cur` does the trick for me.

      $ units
      Currency exchange rates from FloatRates (USD base) on 2020-05-12
      $ sudo units_cur
      $ units
      Currency exchange rates from FloatRates (USD base) on 2020-07-09
    

    (GNU units, packed by Debian)

    • In case anyone else needs this:

        # systemctl edit units-currency-update.service
        
        [Unit]
        Description=Update units(1) currency rates
        
        [Service]
        Type=oneshot
        Nice=19
        ExecStart=/usr/bin/units_cur
        
        # systemctl edit units-currency-update.timer
        
        [Unit]
        Description=Update units(1) currency rates
        
        [Timer]
        OnCalendar=daily
        AccuracySec=3h
        Persistent=true
        
        [Install]
        WantedBy=timers.target
        
        # systemctl daemon-reload
        # systemctl enable units-currency-update.timer

  • Looking at the source of the default configuration (cat /usr/share/misc/units.lib), I believe it only defines conversions for currencies that are pegged to another one (mainly to EUR or USD).

        You have: 10 franc
        You want: dollar
        conformability error
         1.5244902 euro
         1 usdollar
        You have: 10 franc
        You want: euro
         * 1.5244902
         / 0.655957

  • I'm tempted to say it shouldn't even attempt to support currency conversion, as constantly in flux as it is.

  • I wonder if this could be addressed with periodic updates.

    • I didn’t look too deep into it, my understanding was that the source it uses to update itself has been taken offline. There are workarounds involving data massaging and a cron but honestly that’s a lot more work than typing “1000 chf to usd” into ddg and getting the converted amount. But if you know something I don’t, maybe you could share for everyone’s benefit?

I also discovered `units` because of this tale... but I was lucky enough to read it beck in the early days (pre 2005 at least).

'units' was new to me too. The version I have on my Mac wouldn't accept 'millilightseconds' but it would take 'milli-c-seconds' - presumably the units.lib database is a little different from one in the original article.

Though sadly millilightseconds is not supported on macOS, at least, so you have to go:

    3 millilightyears / 365 / 86400

Of course, round 365 to whatever average number of days you believe in :-)

units

You have: mph

You want: kph

        * 1.609344

        / 0.62137119

  • I have

      alias units='units --verbose
    

    in my shell rc which makes the output much more understandable:

      You have: mph
      You want: kph
              mph = 1.609344 kph
              mph = (1 / 0.62137119) kph

    • I find the reciprocal thing useless, so I have units='units --compact --one-line', which gives just the number you want.