Skip to content

Instantly share code, notes, and snippets.

@harshavardhana
Created September 13, 2015 09:19
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save harshavardhana/327e0577c4fed9211f65 to your computer and use it in GitHub Desktop.
Save harshavardhana/327e0577c4fed9211f65 to your computer and use it in GitHub Desktop.
humanizeDuration humanizes time.Duration output to a meaningful value - golang's default ``time.Duration`` output is badly formatted and unreadable.
package main
import (
"fmt"
"math"
"time"
)
// humanizeDuration humanizes time.Duration output to a meaningful value,
// golang's default ``time.Duration`` output is badly formatted and unreadable.
func humanizeDuration(duration time.Duration) string {
if duration.Seconds() < 60.0 {
return fmt.Sprintf("%d seconds", int64(duration.Seconds()))
}
if duration.Minutes() < 60.0 {
remainingSeconds := math.Mod(duration.Seconds(), 60)
return fmt.Sprintf("%d minutes %d seconds", int64(duration.Minutes()), int64(remainingSeconds))
}
if duration.Hours() < 24.0 {
remainingMinutes := math.Mod(duration.Minutes(), 60)
remainingSeconds := math.Mod(duration.Seconds(), 60)
return fmt.Sprintf("%d hours %d minutes %d seconds",
int64(duration.Hours()), int64(remainingMinutes), int64(remainingSeconds))
}
remainingHours := math.Mod(duration.Hours(), 24)
remainingMinutes := math.Mod(duration.Minutes(), 60)
remainingSeconds := math.Mod(duration.Seconds(), 60)
return fmt.Sprintf("%d days %d hours %d minutes %d seconds",
int64(duration.Hours()/24), int64(remainingHours),
int64(remainingMinutes), int64(remainingSeconds))
}
@toolateforteddy
Copy link

I DRY'd this up for you. :)

package humanize

import (
	"fmt"
	"math"
	"strings"
	"time"
)

func humanizeDuration(duration time.Duration) string {
	days := int64(duration.Hours() / 24)
	hours := int64(math.Mod(duration.Hours(), 24))
	minutes := int64(math.Mod(duration.Minutes(), 60))
	seconds := int64(math.Mod(duration.Seconds(), 60))

	chunks := []struct {
		singularName string
		amount       int64
	}{
		{"day", days},
		{"hour", hours},
		{"minute", minutes},
		{"second", seconds},
	}

	parts := []string{}

	for _, chunk := range chunks {
		switch chunk.amount {
		case 0:
			continue
		case 1:
			parts = append(parts, fmt.Sprintf("%d %s", chunk.amount, chunk.singularName))
		default:
			parts = append(parts, fmt.Sprintf("%d %ss", chunk.amount, chunk.singularName))
		}
	}

	return strings.Join(parts, " ")
}

@VojtechVitek
Copy link

package main

import (
	"fmt"
	"strings"
	"time"
)

const (
	day  = time.Minute * 60 * 24
	year = 365 * day
)

func duration(d time.Duration) string {
	if d < day {
		return d.String()
	}

	var b strings.Builder
	if d >= year {
		years := d / year
		fmt.Fprintf(&b, "%dy", years)
		d -= years * year
	}

	days := d / day
	d -= days * day
	fmt.Fprintf(&b, "%dd%s", days, d)

	return b.String()
}

func main() {
	fmt.Println(duration(time.Duration(12*year+365*day+5*day+5*time.Hour)))
}

https://play.golang.org/p/q5boDH4rDUq

@gkotian
Copy link

gkotian commented Mar 25, 2020

Thanks for this. It was super helpful to me 👍

@iDevelopThings
Copy link

Thank yaw sir ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment