github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/humanizeutil/duration.go (about)

     1  // Copyright 2020 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package humanizeutil
    12  
    13  import (
    14  	"fmt"
    15  	"time"
    16  
    17  	"github.com/cockroachdb/redact"
    18  )
    19  
    20  // Duration formats a duration in a user-friendly way. The result is not exact
    21  // and the granularity is no smaller than microseconds.
    22  //
    23  // Examples:
    24  //
    25  //	0              ->  "0µs"
    26  //	123456ns       ->  "123µs"
    27  //	12345678ns     ->  "12ms"
    28  //	12345678912ns  ->  "1.2s"
    29  func Duration(val time.Duration) redact.SafeString {
    30  	val = val.Round(time.Microsecond)
    31  	if val == 0 {
    32  		return "0µs"
    33  	}
    34  
    35  	// Everything under 1ms will show up as µs.
    36  	if val < time.Millisecond {
    37  		return redact.SafeString(val.String())
    38  	}
    39  	// Everything in-between 1ms and 1s will show up as ms.
    40  	if val < time.Second {
    41  		return redact.SafeString(val.Round(time.Millisecond).String())
    42  	}
    43  	// Everything in-between 1s and 1m will show up as seconds with one decimal.
    44  	if val < time.Minute {
    45  		return redact.SafeString(val.Round(100 * time.Millisecond).String())
    46  	}
    47  
    48  	// Everything larger is rounded to the nearest second.
    49  	return redact.SafeString(val.Round(time.Second).String())
    50  }
    51  
    52  // LongDuration formats a duration that is expected to be on the order of
    53  // minutes / hours / days in a user-friendly way. The result is not exact and
    54  // the granularity is no smaller than seconds.
    55  //
    56  // Examples:
    57  //   - 0 seconds
    58  //   - 1 second
    59  //   - 3 minutes
    60  //   - 1 hour
    61  //   - 5 days
    62  //   - 1000 days
    63  func LongDuration(val time.Duration) redact.SafeString {
    64  	var round time.Duration
    65  	var unit string
    66  
    67  	switch {
    68  	case val < time.Minute:
    69  		round = time.Second
    70  		unit = "second"
    71  
    72  	case val < time.Hour:
    73  		round = time.Minute
    74  		unit = "minute"
    75  
    76  	case val < 24*time.Hour:
    77  		round = time.Hour
    78  		unit = "hour"
    79  
    80  	default:
    81  		round = 24 * time.Hour
    82  		unit = "day"
    83  	}
    84  
    85  	n := int64(val.Round(round) / round)
    86  	s := ""
    87  	if n != 1 {
    88  		s = "s"
    89  	}
    90  	return redact.SafeString(fmt.Sprintf("%d %s%s", n, unit, s))
    91  }