gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

times.go (3239B)


      1 package humanize
      2 
      3 import (
      4 	"fmt"
      5 	"math"
      6 	"sort"
      7 	"time"
      8 )
      9 
     10 // Seconds-based time units
     11 const (
     12 	Day      = 24 * time.Hour
     13 	Week     = 7 * Day
     14 	Month    = 30 * Day
     15 	Year     = 12 * Month
     16 	LongTime = 37 * Year
     17 )
     18 
     19 // Time formats a time into a relative string.
     20 //
     21 // Time(someT) -> "3 weeks ago"
     22 func Time(then time.Time) string {
     23 	return RelTime(then, time.Now(), "ago", "from now")
     24 }
     25 
     26 // A RelTimeMagnitude struct contains a relative time point at which
     27 // the relative format of time will switch to a new format string.  A
     28 // slice of these in ascending order by their "D" field is passed to
     29 // CustomRelTime to format durations.
     30 //
     31 // The Format field is a string that may contain a "%s" which will be
     32 // replaced with the appropriate signed label (e.g. "ago" or "from
     33 // now") and a "%d" that will be replaced by the quantity.
     34 //
     35 // The DivBy field is the amount of time the time difference must be
     36 // divided by in order to display correctly.
     37 //
     38 // e.g. if D is 2*time.Minute and you want to display "%d minutes %s"
     39 // DivBy should be time.Minute so whatever the duration is will be
     40 // expressed in minutes.
     41 type RelTimeMagnitude struct {
     42 	D      time.Duration
     43 	Format string
     44 	DivBy  time.Duration
     45 }
     46 
     47 var defaultMagnitudes = []RelTimeMagnitude{
     48 	{time.Second, "now", time.Second},
     49 	{2 * time.Second, "1 second %s", 1},
     50 	{time.Minute, "%d seconds %s", time.Second},
     51 	{2 * time.Minute, "1 minute %s", 1},
     52 	{time.Hour, "%d minutes %s", time.Minute},
     53 	{2 * time.Hour, "1 hour %s", 1},
     54 	{Day, "%d hours %s", time.Hour},
     55 	{2 * Day, "1 day %s", 1},
     56 	{Week, "%d days %s", Day},
     57 	{2 * Week, "1 week %s", 1},
     58 	{Month, "%d weeks %s", Week},
     59 	{2 * Month, "1 month %s", 1},
     60 	{Year, "%d months %s", Month},
     61 	{18 * Month, "1 year %s", 1},
     62 	{2 * Year, "2 years %s", 1},
     63 	{LongTime, "%d years %s", Year},
     64 	{math.MaxInt64, "a long while %s", 1},
     65 }
     66 
     67 // RelTime formats a time into a relative string.
     68 //
     69 // It takes two times and two labels.  In addition to the generic time
     70 // delta string (e.g. 5 minutes), the labels are used applied so that
     71 // the label corresponding to the smaller time is applied.
     72 //
     73 // RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier"
     74 func RelTime(a, b time.Time, albl, blbl string) string {
     75 	return CustomRelTime(a, b, albl, blbl, defaultMagnitudes)
     76 }
     77 
     78 // CustomRelTime formats a time into a relative string.
     79 //
     80 // It takes two times two labels and a table of relative time formats.
     81 // In addition to the generic time delta string (e.g. 5 minutes), the
     82 // labels are used applied so that the label corresponding to the
     83 // smaller time is applied.
     84 func CustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) string {
     85 	lbl := albl
     86 	diff := b.Sub(a)
     87 
     88 	if a.After(b) {
     89 		lbl = blbl
     90 		diff = a.Sub(b)
     91 	}
     92 
     93 	n := sort.Search(len(magnitudes), func(i int) bool {
     94 		return magnitudes[i].D > diff
     95 	})
     96 
     97 	if n >= len(magnitudes) {
     98 		n = len(magnitudes) - 1
     99 	}
    100 	mag := magnitudes[n]
    101 	args := []interface{}{}
    102 	escaped := false
    103 	for _, ch := range mag.Format {
    104 		if escaped {
    105 			switch ch {
    106 			case 's':
    107 				args = append(args, lbl)
    108 			case 'd':
    109 				args = append(args, diff/mag.DivBy)
    110 			}
    111 			escaped = false
    112 		} else {
    113 			escaped = ch == '%'
    114 		}
    115 	}
    116 	return fmt.Sprintf(mag.Format, args...)
    117 }