time.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package format
  2. import (
  3. "fmt"
  4. "math"
  5. "strings"
  6. "time"
  7. )
  8. // humanDuration returns a human-readable approximation of a
  9. // duration (eg. "About a minute", "4 hours ago", etc.).
  10. func humanDuration(d time.Duration) string {
  11. seconds := int(d.Seconds())
  12. switch {
  13. case seconds < 1:
  14. return "Less than a second"
  15. case seconds == 1:
  16. return "1 second"
  17. case seconds < 60:
  18. return fmt.Sprintf("%d seconds", seconds)
  19. }
  20. minutes := int(d.Minutes())
  21. switch {
  22. case minutes == 1:
  23. return "About a minute"
  24. case minutes < 60:
  25. return fmt.Sprintf("%d minutes", minutes)
  26. }
  27. hours := int(math.Round(d.Hours()))
  28. switch {
  29. case hours == 1:
  30. return "About an hour"
  31. case hours < 48:
  32. return fmt.Sprintf("%d hours", hours)
  33. case hours < 24*7*2:
  34. return fmt.Sprintf("%d days", hours/24)
  35. case hours < 24*30*2:
  36. return fmt.Sprintf("%d weeks", hours/24/7)
  37. case hours < 24*365*2:
  38. return fmt.Sprintf("%d months", hours/24/30)
  39. }
  40. return fmt.Sprintf("%d years", int(d.Hours())/24/365)
  41. }
  42. func HumanTime(t time.Time, zeroValue string) string {
  43. return humanTime(t, zeroValue)
  44. }
  45. func HumanTimeLower(t time.Time, zeroValue string) string {
  46. return strings.ToLower(humanTime(t, zeroValue))
  47. }
  48. func humanTime(t time.Time, zeroValue string) string {
  49. if t.IsZero() {
  50. return zeroValue
  51. }
  52. delta := time.Since(t)
  53. if int(delta.Hours())/24/365 < -20 {
  54. return "Forever"
  55. } else if delta < 0 {
  56. return humanDuration(-delta) + " from now"
  57. }
  58. return humanDuration(delta) + " ago"
  59. }