github.com/starshine-sys/bcr@v0.21.0/format_time.go (about) 1 package bcr 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 // This entire file is yoinked straight from 9 // https://github.com/jonas747/yagpdb/blob/3811b434db38ae154dc102b0c8f2dde1fd56b4d9/common/util.go#L85-L186 10 11 // DurationFormatPrecision ... 12 type DurationFormatPrecision int 13 14 // ... 15 const ( 16 DurationPrecisionSeconds DurationFormatPrecision = iota 17 DurationPrecisionMinutes 18 DurationPrecisionHours 19 DurationPrecisionDays 20 DurationPrecisionWeeks 21 DurationPrecisionYears 22 ) 23 24 func (d DurationFormatPrecision) String() string { 25 switch d { 26 case DurationPrecisionSeconds: 27 return "second" 28 case DurationPrecisionMinutes: 29 return "minute" 30 case DurationPrecisionHours: 31 return "hour" 32 case DurationPrecisionDays: 33 return "day" 34 case DurationPrecisionWeeks: 35 return "week" 36 case DurationPrecisionYears: 37 return "year" 38 } 39 return "Unknown" 40 } 41 42 // FromSeconds ... 43 func (d DurationFormatPrecision) FromSeconds(in int64) int64 { 44 switch d { 45 case DurationPrecisionSeconds: 46 return in % 60 47 case DurationPrecisionMinutes: 48 return (in / 60) % 60 49 case DurationPrecisionHours: 50 return ((in / 60) / 60) % 24 51 case DurationPrecisionDays: 52 return (((in / 60) / 60) / 24) % 7 53 case DurationPrecisionWeeks: 54 // There's 52 weeks + 1 day per year (techically +1.25... but were doing +1) 55 // Make sure 364 days isnt 0 weeks and 0 years 56 days := (((in / 60) / 60) / 24) % 365 57 return days / 7 58 case DurationPrecisionYears: 59 return (((in / 60) / 60) / 24) / 365 60 } 61 62 panic("We shouldn't be here") 63 } 64 65 func pluralize(val int64) string { 66 if val == 1 { 67 return "" 68 } 69 return "s" 70 } 71 72 // HumanizeDuration ... 73 func HumanizeDuration(precision DurationFormatPrecision, in time.Duration) string { 74 seconds := int64(in.Seconds()) 75 76 out := make([]string, 0) 77 78 for i := int(precision); i < int(DurationPrecisionYears)+1; i++ { 79 curPrec := DurationFormatPrecision(i) 80 units := curPrec.FromSeconds(seconds) 81 if units > 0 { 82 out = append(out, fmt.Sprintf("%d %s%s", units, curPrec.String(), pluralize(units))) 83 } 84 } 85 86 outStr := "" 87 88 for i := len(out) - 1; i >= 0; i-- { 89 if i == 0 && i != len(out)-1 { 90 outStr += " and " 91 } else if i != len(out)-1 { 92 outStr += " " 93 } 94 outStr += out[i] 95 } 96 97 if outStr == "" { 98 outStr = "less than 1 " + precision.String() 99 } 100 101 return outStr 102 } 103 104 // HumanizeTime ... 105 func HumanizeTime(precision DurationFormatPrecision, in time.Time) string { 106 107 now := time.Now() 108 if now.After(in) { 109 duration := now.Sub(in) 110 return HumanizeDuration(precision, duration) + " ago" 111 } 112 duration := in.Sub(now) 113 return "in " + HumanizeDuration(precision, duration) 114 }