github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/humanized-duration.go (about)

     1  // Copyright (c) 2015-2022 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package cmd
    19  
    20  import (
    21  	"fmt"
    22  	"math"
    23  	"time"
    24  )
    25  
    26  // humanizedDuration container to capture humanized time.
    27  type humanizedDuration struct {
    28  	Days         int64 `json:"days,omitempty"`
    29  	Hours        int64 `json:"hours,omitempty"`
    30  	Minutes      int64 `json:"minutes,omitempty"`
    31  	Seconds      int64 `json:"seconds,omitempty"`
    32  	MilliSeconds int64 `json:"milliSeconds,omitempty"`
    33  }
    34  
    35  // StringShort() humanizes humanizedDuration to human readable short format.
    36  // This does not print at seconds.
    37  func (r humanizedDuration) StringShort() string {
    38  	switch {
    39  	case r.Days == 0 && r.Hours == 0 && r.Minutes == 0 && r.Seconds == 0:
    40  		return fmt.Sprintf("%d milliseconds", r.MilliSeconds)
    41  	case r.Days == 0 && r.Hours == 0 && r.Minutes == 0:
    42  		return fmt.Sprintf("%d seconds", r.Seconds)
    43  	case r.Days == 0 && r.Hours == 0:
    44  		return fmt.Sprintf("%d minutes", r.Minutes)
    45  	case r.Days == 0:
    46  		return fmt.Sprintf("%d hours %d minutes", r.Hours, r.Minutes)
    47  	case r.Days <= 2:
    48  		return fmt.Sprintf("%d days, %d hours", r.Days, r.Hours)
    49  	default:
    50  		return fmt.Sprintf("%d days", r.Days)
    51  	}
    52  }
    53  
    54  // String() humanizes humanizedDuration to human readable,
    55  func (r humanizedDuration) String() string {
    56  	if r.Days == 0 && r.Hours == 0 && r.Minutes == 0 && r.Seconds == 0 {
    57  		return fmt.Sprintf("%d milliseconds", r.MilliSeconds)
    58  	}
    59  
    60  	if r.Days == 0 && r.Hours == 0 && r.Minutes == 0 {
    61  		return fmt.Sprintf("%d seconds", r.Seconds)
    62  	}
    63  	if r.Days == 0 && r.Hours == 0 {
    64  		return fmt.Sprintf("%d minutes %d seconds", r.Minutes, r.Seconds)
    65  	}
    66  	if r.Days == 0 {
    67  		return fmt.Sprintf("%d hours %d minutes %d seconds", r.Hours, r.Minutes, r.Seconds)
    68  	}
    69  	return fmt.Sprintf("%d days %d hours %d minutes %d seconds", r.Days, r.Hours, r.Minutes, r.Seconds)
    70  }
    71  
    72  // timeDurationToHumanizedDuration convert golang time.Duration to a custom more readable humanizedDuration.
    73  func timeDurationToHumanizedDuration(duration time.Duration) humanizedDuration {
    74  	r := humanizedDuration{}
    75  	if duration.Milliseconds() < 1000 {
    76  		r.MilliSeconds = int64(duration.Milliseconds())
    77  		return r
    78  	}
    79  	if duration.Seconds() < 60.0 {
    80  		r.Seconds = int64(duration.Seconds())
    81  		return r
    82  	}
    83  	if duration.Minutes() < 60.0 {
    84  		remainingSeconds := math.Mod(duration.Seconds(), 60)
    85  		r.Seconds = int64(remainingSeconds)
    86  		r.Minutes = int64(duration.Minutes())
    87  		return r
    88  	}
    89  	if duration.Hours() < 24.0 {
    90  		remainingMinutes := math.Mod(duration.Minutes(), 60)
    91  		remainingSeconds := math.Mod(duration.Seconds(), 60)
    92  		r.Seconds = int64(remainingSeconds)
    93  		r.Minutes = int64(remainingMinutes)
    94  		r.Hours = int64(duration.Hours())
    95  		return r
    96  	}
    97  	remainingHours := math.Mod(duration.Hours(), 24)
    98  	remainingMinutes := math.Mod(duration.Minutes(), 60)
    99  	remainingSeconds := math.Mod(duration.Seconds(), 60)
   100  	r.Hours = int64(remainingHours)
   101  	r.Minutes = int64(remainingMinutes)
   102  	r.Seconds = int64(remainingSeconds)
   103  	r.Days = int64(duration.Hours() / 24)
   104  	return r
   105  }