Repository: nats-io/nats-server (go)

Issue:
Monitoring server not sorting connections by idle time correctly
### What version were you using?

nats-server: v2.9.21

### What environment was the server running in?

Linux amd64

### Is this defect reproducible?

When sorting connections by idle time, you can see from the results of the API that they're not correctly sorted.

For example, this is the current response of the demo server, for https://demo.nats.io:8222/connz?sort=idle:

<details>

```json
{
  "server_id": "NC5BFXEYWVQUHQQMG7FVARRY3AYVOKP7H2FIUI2ZTH55Z5FWHWJ2LOXY",
  "now": "2023-08-31T15:19:01.894405231Z",
  "num_connections": 34,
  "total": 34,
  "offset": 0,
  "limit": 1024,
  "connections": [
    {
      "cid": 232484,
      "kind": "Client",
      "type": "nats",
      "ip": "46.105.118.190",
      "port": 61513,
      "start": "2023-08-14T13:24:33.914546665Z",
      "last_activity": "2023-08-31T15:10:57.288873282Z",
      "rtt": "1m47.922127283s",
      "uptime": "17d1h54m27s",
      "idle": "8m4s",
      "pending_bytes": 0,
      "in_msgs": 2647,
      "out_msgs": 573,
      "in_bytes": 5304731,
      "out_bytes": 65807,
      "subscriptions": 3,
      "lang": ".NET",
      "version": "1.0.7.0"
    },
    {
      "cid": 302292,
      "kind": "Client",
      "type": "nats",
      "ip": "35.203.20.39",
      "port": 60212,
      "start": "2023-08-18T00:28:49.563009727Z",
      "last_activity": "2023-08-28T16:47:37.780172094Z",
      "rtt": "41.986973ms",
      "uptime": "13d14h50m12s",
      "idle": "2d22h31m24s",
      "pending_bytes": 0,
      "in_msgs": 9,
      "out_msgs": 9,
      "in_bytes": 201841,
      "out_bytes": 1354,
      "subscriptions": 1,
      "lang": "nats.js",
      "version": "2.12.1",
      "tls_version": "1.3",
      "tls_cipher_suite": "TLS_AES_128_GCM_SHA256"
    },
    {
      "cid": 510887,
      "kind": "Client",
      "type": "nats",
      "ip": "213.21.176.71",
      "port": 51602,
      "start": "2023-08-31T12:02:42.586895287Z",
      "last_activity": "2023-08-31T15:09:09.959922587Z",
      "rtt": "170.829052ms",
      "uptime": "3h16m19s",
      "idle": "9m51s",
      "pending_bytes": 0,
      "in_msgs": 2322,
      "out_msgs": 2322,
      "in_bytes": 4179400,
      "out_bytes": 3589812,
      "subscriptions": 1,
      "lang": "python3",
      "version": "2.3.1"
    },
    {
      "cid": 512755,
      "kind": "Client",
      "type": "nats",
      "ip": "3.67.185.186",
      "port": 2889,
      "start": "2023-08-31T13:56:16.917563807Z",
      "last_activity": "2023-08-31T15:19:01.853396005Z",
      "rtt": "122.629797ms",
      "uptime": "1h22m44s",
      "idle": "0s",
      "pending_bytes": 0,
      "in_msgs": 19835,
      "out_msgs": 19834,
      "in_bytes": 783400,
      "out_bytes": 1627544,
      "subscriptions": 2,
      "lang": "go",
      "version": "1.28.0"
    },
    {
      "cid": 512696,
      "kind": "Client",
      "type": "nats",
      "ip": "158.181.140.134",
      "port": 60166,
      "start": "2023-08-31T12:35:36.434240579Z",
      "last_activity": "2023-08-31T13:16:59.400240469Z",
      "rtt": "215.60588ms",
      "uptime": "2h43m25s",
      "idle": "2h2m2s",
      "pending_bytes": 0,
      "in_msgs": 8,
      "out_msgs": 0,
      "in_bytes": 523,
      "out_bytes": 0,
      "subscriptions": 0,
      "lang": "go",
      "version": "1.28.0"
    },
    {
      "cid": 512738,
      "kind": "Client",
      "type": "nats",
      "ip": "103.228.147.188",
      "port": 25359,
      "start": "2023-08-31T13:29:32.108773632Z",
      "last_activity": "2023-08-31T13:29:35.330791161Z",
      "rtt": "329.856582ms",
      "uptime": "1h49m29s",
      "idle": "1h49m26s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 3,
      "name": "products-jetstream",
      "lang": "nats.js",
      "version": "2.13.1",
      "tls_version": "1.3",
      "tls_cipher_suite": "TLS_AES_128_GCM_SHA256"
    },
    {
      "cid": 512737,
      "kind": "Client",
      "type": "nats",
      "ip": "103.228.147.188",
      "port": 25214,
      "start": "2023-08-31T13:29:32.045875267Z",
      "last_activity": "2023-08-31T13:29:35.131993396Z",
      "rtt": "271.093209ms",
      "uptime": "1h49m29s",
      "idle": "1h49m26s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "lang": "nats.js",
      "version": "2.13.1",
      "tls_version": "1.3",
      "tls_cipher_suite": "TLS_AES_128_GCM_SHA256"
    },
    {
      "cid": 512736,
      "kind": "Client",
      "type": "nats",
      "ip": "103.228.147.188",
      "port": 25375,
      "start": "2023-08-31T13:29:30.564841942Z",
      "last_activity": "2023-08-31T13:29:31.609500016Z",
      "rtt": "265.152418ms",
      "uptime": "1h49m31s",
      "idle": "1h49m30s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "lang": "nats.js",
      "version": "2.13.1",
      "tls_version": "1.3",
      "tls_cipher_suite": "TLS_AES_128_GCM_SHA256"
    },
    {
      "cid": 512735,
      "kind": "Client",
      "type": "nats",
      "ip": "103.228.147.188",
      "port": 25120,
      "start": "2023-08-31T13:29:30.550593092Z",
      "last_activity": "2023-08-31T13:29:31.488087925Z",
      "rtt": "266.701161ms",
      "uptime": "1h49m31s",
      "idle": "1h49m30s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "lang": "nats.js",
      "version": "2.13.1",
      "tls_version": "1.3",
      "tls_cipher_suite": "TLS_AES_128_GCM_SHA256"
    },
    {
      "cid": 512757,
      "kind": "Client",
      "type": "nats",
      "ip": "5.172.234.44",
      "port": 15761,
      "start": "2023-08-31T14:06:38.521316193Z",
      "last_activity": "2023-08-31T14:06:39.014367484Z",
      "rtt": "177.211815ms",
      "uptime": "1h12m23s",
      "idle": "1h12m22s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 3,
      "lang": "C",
      "version": "3.7.0-beta"
    },
    {
      "cid": 190,
      "kind": "Client",
      "type": "nats",
      "ip": "20.198.152.10",
      "port": 3529,
      "start": "2023-08-04T15:04:18.092808785Z",
      "last_activity": "2023-08-04T15:04:18.528062581Z",
      "rtt": "209.00094ms",
      "uptime": "27d0h14m43s",
      "idle": "27d0h14m43s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "name": "NATS CLI Version 0.0.18",
      "lang": "go",
      "version": "1.11.0"
    },
    {
      "cid": 189,
      "kind": "Client",
      "type": "nats",
      "ip": "20.198.152.10",
      "port": 3545,
      "start": "2023-08-04T15:04:18.063247078Z",
      "last_activity": "2023-08-04T15:04:18.490762948Z",
      "rtt": "213.378956ms",
      "uptime": "27d0h14m43s",
      "idle": "27d0h14m43s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "name": "NATS CLI Version 0.0.18",
      "lang": "go",
      "version": "1.11.0"
    },
    {
      "cid": 512793,
      "kind": "Client",
      "type": "nats",
      "ip": "149.100.31.93",
      "port": 37007,
      "start": "2023-08-31T15:18:59.790010071Z",
      "last_activity": "2023-08-31T15:19:00.153539702Z",
      "rtt": "179.817393ms",
      "uptime": "2s",
      "idle": "1s",
      "pending_bytes": 0,
      "in_msgs": 3,
      "out_msgs": 0,
      "in_bytes": 159,
      "out_bytes": 0,
      "subscriptions": 2,
      "lang": "python3",
      "version": "2.3.1"
    },
    {
      "cid": 510990,
      "kind": "Client",
      "type": "nats",
      "ip": "24.203.20.164",
      "port": 38663,
      "start": "2023-08-31T12:20:23.537600632Z",
      "last_activity": "2023-08-31T12:20:23.878404944Z",
      "rtt": "65.69959ms",
      "uptime": "2h58m38s",
      "idle": "2h58m38s",
      "pending_bytes": 0,
      "in_msgs": 2,
      "out_msgs": 2,
      "in_bytes": 71,
      "out_bytes": 1088,
      "subscriptions": 1,
      "lang": "nats.js",
      "version": "2.12.1",
      "tls_version": "1.3",
      "tls_cipher_suite": "TLS_AES_128_GCM_SHA256"
    },
    {
      "cid": 302267,
      "kind": "Client",
      "type": "nats",
      "ip": "35.203.112.31",
      "port": 2568,
      "start": "2023-08-17T23:05:24.227520133Z",
      "last_activity": "2023-08-17T23:05:24.53277908Z",
      "rtt": "40.589101ms",
      "uptime": "13d16h13m37s",
      "idle": "13d16h13m37s",
      "pending_bytes": 0,
      "in_msgs": 2,
      "out_msgs": 2,
      "in_bytes": 71,
      "out_bytes": 1046,
      "subscriptions": 1,
      "lang": "nats.js",
      "version": "2.12.1",
      "tls_version": "1.3",
      "tls_cipher_suite": "TLS_AES_128_GCM_SHA256"
    },
    {
      "cid": 206,
      "kind": "Client",
      "type": "nats",
      "ip": "139.162.174.82",
      "port": 55136,
      "start": "2023-08-04T15:04:18.859582308Z",
      "last_activity": "2023-08-04T15:04:19.145791177Z",
      "rtt": "123.871791ms",
      "uptime": "27d0h14m43s",
      "idle": "27d0h14m42s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "lang": "go",
      "version": "1.25.0"
    },
    {
      "cid": 208,
      "kind": "Client",
      "type": "nats",
      "ip": "172.104.228.102",
      "port": 61866,
      "start": "2023-08-04T15:04:19.039808071Z",
      "last_activity": "2023-08-04T15:04:19.299904845Z",
      "rtt": "124.063004ms",
      "uptime": "27d0h14m42s",
      "idle": "27d0h14m42s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "lang": "go",
      "version": "1.27.1"
    },
    {
      "cid": 205,
      "kind": "Client",
      "type": "nats",
      "ip": "202.61.207.151",
      "port": 12569,
      "start": "2023-08-04T15:04:18.826788417Z",
      "last_activity": "2023-08-04T15:04:19.084226953Z",
      "rtt": "127.8401ms",
      "uptime": "27d0h14m43s",
      "idle": "27d0h14m42s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "lang": "go",
      "version": "1.27.1"
    },
    {
      "cid": 209,
      "kind": "Client",
      "type": "nats",
      "ip": "34.32.242.155",
      "port": 45304,
      "start": "2023-08-04T15:04:19.075154418Z",
      "last_activity": "2023-08-04T15:04:19.321253743Z",
      "rtt": "112.891846ms",
      "uptime": "27d0h14m42s",
      "idle": "27d0h14m42s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "lang": "python3",
      "version": "2.2.0"
    },
    {
      "cid": 506461,
      "kind": "Client",
      "type": "nats",
      "ip": "165.22.78.170",
      "port": 52462,
      "start": "2023-08-31T06:40:38.883766916Z",
      "last_activity": "2023-08-31T06:40:39.125471256Z",
      "rtt": "119.635873ms",
      "uptime": "8h38m23s",
      "idle": "8h38m22s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "lang": "go",
      "version": "1.28.0"
    },
    {
      "cid": 498304,
      "kind": "Client",
      "type": "nats",
      "ip": "46.235.233.44",
      "port": 57392,
      "start": "2023-08-29T11:46:13.041284421Z",
      "last_activity": "2023-08-29T11:46:13.186823869Z",
      "rtt": "137.574244ms",
      "uptime": "2d3h32m48s",
      "idle": "2d3h32m48s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "lang": "nats.js",
      "version": "2.7.0-1"
    },
    {
      "cid": 499881,
      "kind": "Client",
      "type": "nats",
      "ip": "174.168.189.80",
      "port": 59688,
      "start": "2023-08-30T07:08:02.088854695Z",
      "last_activity": "2023-08-30T07:08:02.218662261Z",
      "rtt": "57.951947ms",
      "uptime": "1d8h10m59s",
      "idle": "1d8h10m59s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 1,
      "name": "NATS CLI Version 0.0.35",
      "lang": "go",
      "version": "1.19.0"
    },
    {
      "cid": 191,
      "kind": "Client",
      "type": "nats",
      "ip": "18.157.168.211",
      "port": 46488,
      "start": "2023-08-04T15:04:18.127140273Z",
      "last_activity": "2023-08-04T15:04:18.250155296Z",
      "rtt": "118.742415ms",
      "uptime": "27d0h14m43s",
      "idle": "27d0h14m43s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "lang": "rust",
      "version": "0.20.1"
    },
    {
      "cid": 342794,
      "kind": "Client",
      "type": "nats",
      "ip": "65.49.52.68",
      "port": 13309,
      "start": "2023-08-22T06:44:24.779488834Z",
      "last_activity": "2023-08-22T06:44:24.869589645Z",
      "rtt": "45.812053ms",
      "uptime": "9d8h34m37s",
      "idle": "9d8h34m37s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 3,
      "name": "ecommerce-ad-revenue",
      "lang": "go",
      "version": "1.24.0"
    },
    {
      "cid": 512753,
      "kind": "Client",
      "type": "nats",
      "ip": "20.99.129.96",
      "port": 1024,
      "start": "2023-08-31T13:52:23.95523995Z",
      "last_activity": "2023-08-31T13:52:24.034193931Z",
      "rtt": "48.041543ms",
      "uptime": "1h26m37s",
      "idle": "1h26m37s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "name": "TB NATS connection for Tenant 12c3b560-4096-11eb-a8a0-effd4ecfe4e7",
      "lang": "java",
      "version": "2.8.0"
    },
    {
      "cid": 430605,
      "kind": "Client",
      "type": "nats",
      "ip": "20.99.129.96",
      "port": 4544,
      "start": "2023-08-24T20:13:50.202295858Z",
      "last_activity": "2023-08-24T20:13:50.26299438Z",
      "rtt": "47.997872ms",
      "uptime": "6d19h5m11s",
      "idle": "6d19h5m11s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "name": "TB NATS connection for Tenant 12c3b560-4096-11eb-a8a0-effd4ecfe4e7",
      "lang": "java",
      "version": "2.8.0"
    },
    {
      "cid": 188,
      "kind": "Client",
      "type": "nats",
      "ip": "18.144.6.11",
      "port": 38406,
      "start": "2023-08-04T15:04:17.558775202Z",
      "last_activity": "2023-08-04T15:04:17.608147766Z",
      "rtt": "42.178401ms",
      "uptime": "27d0h14m44s",
      "idle": "27d0h14m44s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "lang": "rust",
      "version": "0.20.1"
    },
    {
      "cid": 342793,
      "kind": "Client",
      "type": "nats",
      "ip": "65.49.52.92",
      "port": 57323,
      "start": "2023-08-22T06:44:23.949148968Z",
      "last_activity": "2023-08-22T06:44:23.994467709Z",
      "rtt": "45.896184ms",
      "uptime": "9d8h34m37s",
      "idle": "9d8h34m37s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "name": "ecommerce-payment",
      "lang": "go",
      "version": "1.16.0"
    },
    {
      "cid": 342795,
      "kind": "Client",
      "type": "nats",
      "ip": "65.49.52.92",
      "port": 21787,
      "start": "2023-08-22T06:44:26.036225687Z",
      "last_activity": "2023-08-22T06:44:26.081219652Z",
      "rtt": "44.357775ms",
      "uptime": "9d8h34m35s",
      "idle": "9d8h34m35s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "name": "ecommerce-catalog",
      "lang": "go",
      "version": "1.16.0"
    },
    {
      "cid": 342796,
      "kind": "Client",
      "type": "nats",
      "ip": "65.49.52.92",
      "port": 47070,
      "start": "2023-08-22T06:44:26.735661559Z",
      "last_activity": "2023-08-22T06:44:26.780439263Z",
      "rtt": "44.049149ms",
      "uptime": "9d8h34m35s",
      "idle": "9d8h34m35s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "name": "ecommerce-payment",
      "lang": "go",
      "version": "1.16.0"
    },
    {
      "cid": 183,
      "kind": "Client",
      "type": "nats",
      "ip": "52.53.163.133",
      "port": 54468,
      "start": "2023-08-04T15:04:17.161658177Z",
      "last_activity": "2023-08-04T15:04:17.206095417Z",
      "rtt": "42.054901ms",
      "uptime": "27d0h14m44s",
      "idle": "27d0h14m44s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "lang": "rust",
      "version": "0.20.1"
    },
    {
      "cid": 495533,
      "kind": "Client",
      "type": "nats",
      "ip": "65.49.52.68",
      "port": 13099,
      "start": "2023-08-29T07:57:32.623812529Z",
      "last_activity": "2023-08-29T07:57:32.665044853Z",
      "rtt": "44.234068ms",
      "uptime": "2d7h21m29s",
      "idle": "2d7h21m29s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "name": "ecommerce-payment",
      "lang": "go",
      "version": "1.24.0"
    },
    {
      "cid": 512792,
      "kind": "Client",
      "type": "nats",
      "ip": "151.181.215.50",
      "port": 46494,
      "start": "2023-08-31T15:17:51.748456938Z",
      "last_activity": "2023-08-31T15:17:51.788927665Z",
      "rtt": "41.857148ms",
      "uptime": "1m10s",
      "idle": "1m10s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "name": "service",
      "lang": "go",
      "version": "1.28.0"
    },
    {
      "cid": 202,
      "kind": "Client",
      "type": "nats",
      "ip": "54.159.64.169",
      "port": 1318,
      "start": "2023-08-04T15:04:18.79136239Z",
      "last_activity": "2023-08-04T15:04:18.823379501Z",
      "rtt": "32.079352ms",
      "uptime": "27d0h14m43s",
      "idle": "27d0h14m43s",
      "pending_bytes": 0,
      "in_msgs": 0,
      "out_msgs": 0,
      "in_bytes": 0,
      "out_bytes": 0,
      "subscriptions": 0,
      "lang": "go",
      "version": "1.10.0"
    }
  ]
}
```

</details>

These are the idle times in order of their appearance in the response:

```
8m4s
2d22h31m24s
9m51s
0s
2h2m2s
1h49m26s
1h49m26s
1h49m30s
1h49m30s
1h12m22s
27d0h14m43s
27d0h14m43s
1s
2h58m38s
13d16h13m37s
27d0h14m42s
27d0h14m42s
27d0h14m42s
27d0h14m42s
8h38m22s
2d3h32m48s
1d8h10m59s
27d0h14m43s
9d8h34m37s
1h26m37s
6d19h5m11s
27d0h14m44s
9d8h34m37s
9d8h34m35s
9d8h34m35s
27d0h14m44s
2d7h21m29s
1m10s
27d0h14m43s
```

They are clearly not sorted.

### Given the capability you are leveraging, describe your expectation?

I expected the connections to be sorted by their idle time in descending order.

### Given the expectation, what is the defect you are observing?

The issue seems to be in [`byIdle.Less`](https://github.com/nats-io/nats-server/blob/887a4ae692292c4efd95539993b7d665fea78ec5/server/monitor_sort_opts.go#L97).

The function is subtracting the connection's start time from the last activity time.

```go
type byIdle struct{ ConnInfos }

func (l byIdle) Less(i, j int) bool {
	ii := l.ConnInfos[i].LastActivity.Sub(l.ConnInfos[i].Start)
	ij := l.ConnInfos[j].LastActivity.Sub(l.ConnInfos[j].Start)
	return ii < ij
}
```

Pull request:
Fix monitoring server connz idle time sorting
 - [x] Link to issue, e.g. `Resolves #NNN`
 - [ ] Documentation added (if applicable)
 - [x] Tests added
 - [ ] Branch rebased on top of current main (`git pull --rebase origin main`)
 - [x] Changes squashed to a single commit (described [here](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html))
 - [ ] Build is green in Travis CI
 - [x] You have certified that the contribution is your original work and that you license the work to the project under the [Apache 2 license](https://github.com/nats-io/nats-server/blob/main/LICENSE)

Resolves #4462 

### Changes proposed in this pull request:

 - Changed how [`byIdle`](https://github.com/nats-io/nats-server/blob/887a4ae692292c4efd95539993b7d665fea78ec5/server/monitor_sort_opts.go#L97) struct compares the idle times (was subtracting the start time from the last activity time).
 - Added tests for `byIdle`.
 - Changed and simplified the test [`TestConnzSortedByIdle`](https://github.com/nats-io/nats-server/blob/8a9f441c40c43e5a5786506174d810bc559748aa/server/monitor_test.go#L1185) (No need for the clients to publish and subscribe if we are manually changing the client's `last` time, and we only need to test the sorting order). Also the test was not catching the problem because the clients `start` time was the same, now every client has a different start time.


Patch:
diff --git a/server/monitor.go b/server/monitor.go
index 53c562ac..407a028a 100644
--- a/server/monitor.go
+++ b/server/monitor.go
@@ -492,7 +492,7 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) {
 	case ByLast:
 		sort.Sort(sort.Reverse(byLast{pconns}))
 	case ByIdle:
-		sort.Sort(sort.Reverse(byIdle{pconns}))
+		sort.Sort(sort.Reverse(byIdle{pconns, c.Now}))
 	case ByUptime:
 		sort.Sort(byUptime{pconns, time.Now()})
 	case ByStop:
diff --git a/server/monitor_sort_opts.go b/server/monitor_sort_opts.go
index 58cc3900..2fcaf2e9 100644
--- a/server/monitor_sort_opts.go
+++ b/server/monitor_sort_opts.go
@@ -92,12 +92,13 @@ func (l byLast) Less(i, j int) bool {
 }
 
 // Idle time
-type byIdle struct{ ConnInfos }
+type byIdle struct {
+	ConnInfos
+	now time.Time
+}
 
 func (l byIdle) Less(i, j int) bool {
-	ii := l.ConnInfos[i].LastActivity.Sub(l.ConnInfos[i].Start)
-	ij := l.ConnInfos[j].LastActivity.Sub(l.ConnInfos[j].Start)
-	return ii < ij
+	return l.now.Sub(l.ConnInfos[i].LastActivity) < l.now.Sub(l.ConnInfos[j].LastActivity)
 }
 
 // Uptime


Test patch:
diff --git a/server/monitor_test.go b/server/monitor_test.go
index a8d52e4e..d3bd215e 100644
--- a/server/monitor_test.go
+++ b/server/monitor_test.go
@@ -1186,77 +1186,167 @@ func TestConnzSortedByIdle(t *testing.T) {
 	s := runMonitorServer()
 	defer s.Shutdown()
 
-	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
+	url := fmt.Sprintf("http://%s/connz?sort=idle", s.MonitorAddr())
+	now := time.Now()
 
-	testIdle := func(mode int) {
-		firstClient := createClientConnSubscribeAndPublish(t, s)
-		defer firstClient.Close()
-		firstClient.Subscribe("client.1", func(m *nats.Msg) {})
-		firstClient.Flush()
-
-		secondClient := createClientConnSubscribeAndPublish(t, s)
-		defer secondClient.Close()
-
-		// Make it such that the second client started 10 secs ago. 10 is important since bug
-		// was strcmp, e.g. 1s vs 11s
-		var cid uint64
-		switch mode {
-		case 0:
-			cid = uint64(2)
-		case 1:
-			cid = uint64(4)
-		}
-		client := s.getClient(cid)
-		if client == nil {
-			t.Fatalf("Error looking up client %v\n", 2)
-		}
+	clients := []struct {
+		start time.Time // Client start time.
+		last  time.Time // Client last activity time.
+	}{
+		{start: now.Add(-10 * time.Second), last: now.Add(-5 * time.Second)},
+		{start: now.Add(-20 * time.Second), last: now.Add(-10 * time.Second)},
+		{start: now.Add(-3 * time.Second), last: now.Add(-2 * time.Second)},
+		{start: now.Add(-30 * time.Second), last: now.Add(-20 * time.Second)},
+	}
 
-		// We want to make sure that we set start/last after the server has finished
-		// updating this client's last activity. Doing another Flush() now (even though
-		// one is done in createClientConnSubscribeAndPublish) ensures that server has
-		// finished updating the client's last activity, since for that last flush there
-		// should be no new message/sub/unsub activity.
-		secondClient.Flush()
+	testIdle := func(mode int) {
+		// Connect the specified number of clients.
+		for _, c := range clients {
+			clientConn := createClientConnSubscribeAndPublish(t, s)
+			defer clientConn.Close()
 
-		client.mu.Lock()
-		client.start = client.start.Add(-10 * time.Second)
-		client.last = client.start
-		client.mu.Unlock()
+			cid, err := clientConn.GetClientID()
+			if err != nil {
+				t.Fatalf("error getting the client CID: %v", err)
+			}
 
-		// The Idle granularity is a whole second
-		time.Sleep(time.Second)
-		firstClient.Publish("client.1", []byte("new message"))
+			client := s.getClient(cid)
+			if client == nil {
+				t.Fatalf("error looking up client %d", cid)
+			}
 
-		c := pollConz(t, s, mode, url+"connz?sort=idle", &ConnzOptions{Sort: ByIdle})
-		// Make sure we are returned 2 connections...
-		if len(c.Conns) != 2 {
-			t.Fatalf("Expected to get two connections, got %v", len(c.Conns))
+			// Change the client's start and last activity times.
+			client.mu.Lock()
+			client.start = c.start
+			client.last = c.last
+			client.mu.Unlock()
 		}
 
-		// And that the Idle time is valid (even if equal to "0s")
-		if c.Conns[0].Idle == "" || c.Conns[1].Idle == "" {
-			t.Fatal("Expected Idle value to be valid")
-		}
+		connz := pollConz(t, s, mode, url, &ConnzOptions{Sort: ByIdle})
 
-		idle1, err := time.ParseDuration(c.Conns[0].Idle)
-		if err != nil {
-			t.Fatalf("Unable to parse duration %v, err=%v", c.Conns[0].Idle, err)
-		}
-		idle2, err := time.ParseDuration(c.Conns[1].Idle)
-		if err != nil {
-			t.Fatalf("Unable to parse duration %v, err=%v", c.Conns[0].Idle, err)
+		wantConns := len(clients)
+		gotConns := len(connz.Conns)
+
+		if gotConns != wantConns {
+			t.Fatalf("want %d connections, got %d", wantConns, gotConns)
 		}
 
-		if idle2 < idle1 {
-			t.Fatalf("Expected conns sorted in descending order by Idle, got %v < %v\n",
-				idle2, idle1)
+		idleDurations := getConnsIdleDurations(t, connz.Conns)
+
+		if !sortedDurationsDesc(idleDurations) {
+			t.Errorf("want durations sorted in descending order, got %v", idleDurations)
 		}
 	}
+
 	for mode := 0; mode < 2; mode++ {
 		testIdle(mode)
 	}
 }
 
+// getConnsIdleDurations returns a slice of parsed idle durations from a connection info slice.
+func getConnsIdleDurations(t *testing.T, conns []*ConnInfo) []time.Duration {
+	t.Helper()
+
+	durations := make([]time.Duration, 0, len(conns))
+
+	for _, conn := range conns {
+		idle, err := time.ParseDuration(conn.Idle)
+		if err != nil {
+			t.Fatalf("error parsing duration %q: %v", conn.Idle, err)
+		}
+		durations = append(durations, idle)
+	}
+
+	return durations
+}
+
+// sortedDurationsDesc checks if a time.Duration slice is sorted in descending order.
+func sortedDurationsDesc(durations []time.Duration) bool {
+	return sort.SliceIsSorted(durations, func(i, j int) bool {
+		// Must be longer than the next duration.
+		return durations[i] > durations[j]
+	})
+}
+
+func TestConnzSortByIdleTime(t *testing.T) {
+	now := time.Now().UTC()
+
+	cases := map[string]ConnInfos{
+		"zero values": {{}, {}, {}, {}},
+		"equal last activity times": {
+			{Start: now.Add(-50 * time.Minute), LastActivity: now.Add(-time.Minute)},
+			{Start: now.Add(-30 * time.Minute), LastActivity: now.Add(-time.Minute)},
+			{Start: now.Add(-10 * time.Second), LastActivity: now.Add(-time.Minute)},
+			{Start: now.Add(-2 * time.Hour), LastActivity: now.Add(-time.Minute)},
+		},
+		"last activity in the future": {
+			{Start: now.Add(-50 * time.Minute), LastActivity: now.Add(10 * time.Minute)}, // +10m
+			{Start: now.Add(-30 * time.Minute), LastActivity: now.Add(5 * time.Minute)},  // +5m
+			{Start: now.Add(-24 * time.Hour), LastActivity: now.Add(2 * time.Second)},    // +2s
+			{Start: now.Add(-10 * time.Second), LastActivity: now.Add(15 * time.Minute)}, // +15m
+			{Start: now.Add(-2 * time.Hour), LastActivity: now.Add(time.Minute)},         // +1m
+		},
+		"unsorted": {
+			{Start: now.Add(-50 * time.Minute), LastActivity: now.Add(-10 * time.Minute)}, // 10m ago
+			{Start: now.Add(-30 * time.Minute), LastActivity: now.Add(-5 * time.Minute)},  // 5m ago
+			{Start: now.Add(-24 * time.Hour), LastActivity: now.Add(-2 * time.Second)},    // 2s ago
+			{Start: now.Add(-10 * time.Second), LastActivity: now.Add(-15 * time.Minute)}, // 15m ago
+			{Start: now.Add(-2 * time.Hour), LastActivity: now.Add(-time.Minute)},         // 1m ago
+		},
+		"unsorted with zero value start time": {
+			{LastActivity: now.Add(-10 * time.Minute)}, // 10m ago
+			{LastActivity: now.Add(-5 * time.Minute)},  // 5m ago
+			{LastActivity: now.Add(-2 * time.Second)},  // 2s ago
+			{LastActivity: now.Add(-15 * time.Minute)}, // 15m ago
+			{LastActivity: now.Add(-time.Minute)},      // 1m ago
+		},
+		"sorted": {
+			{Start: now.Add(-24 * time.Hour), LastActivity: now.Add(-2 * time.Second)},    // 2s ago
+			{Start: now.Add(-2 * time.Hour), LastActivity: now.Add(-time.Minute)},         // 1m ago
+			{Start: now.Add(-30 * time.Minute), LastActivity: now.Add(-5 * time.Minute)},  // 5m ago
+			{Start: now.Add(-50 * time.Minute), LastActivity: now.Add(-10 * time.Minute)}, // 10m ago
+			{Start: now.Add(-10 * time.Second), LastActivity: now.Add(-15 * time.Minute)}, // 15m ago
+		},
+		"sorted with zero value start time": {
+			{LastActivity: now.Add(-2 * time.Second)},  // 2s ago
+			{LastActivity: now.Add(-time.Minute)},      // 1m ago
+			{LastActivity: now.Add(-5 * time.Minute)},  // 5m ago
+			{LastActivity: now.Add(-10 * time.Minute)}, // 10m ago
+			{LastActivity: now.Add(-15 * time.Minute)}, // 15m ago
+		},
+	}
+
+	for name, conns := range cases {
+		t.Run(name, func(t *testing.T) {
+			sort.Sort(byIdle{conns, now})
+
+			idleDurations := getIdleDurations(conns, now)
+
+			if !sortedDurationsAsc(idleDurations) {
+				t.Errorf("want durations sorted in ascending order, got %v", idleDurations)
+			}
+		})
+	}
+}
+
+// getIdleDurations returns a slice of idle durations from a connection info list up until now time.
+func getIdleDurations(conns ConnInfos, now time.Time) []time.Duration {
+	durations := make([]time.Duration, 0, len(conns))
+
+	for _, conn := range conns {
+		durations = append(durations, now.Sub(conn.LastActivity))
+	}
+
+	return durations
+}
+
+// sortedDurationsAsc checks if a time.Duration slice is sorted in ascending order.
+func sortedDurationsAsc(durations []time.Duration) bool {
+	return sort.SliceIsSorted(durations, func(i, j int) bool {
+		return durations[i] < durations[j]
+	})
+}
+
 func TestConnzSortBadRequest(t *testing.T) {
 	s := runMonitorServer()
 	defer s.Shutdown()