|  | @@ -7,6 +7,8 @@ package base
 | 
	
		
			
				|  |  |  import (
 | 
	
		
			
				|  |  |  	"crypto/md5"
 | 
	
		
			
				|  |  |  	"encoding/hex"
 | 
	
		
			
				|  |  | +	"fmt"
 | 
	
		
			
				|  |  | +	"time"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Encode string to md5 hex value
 | 
	
	
		
			
				|  | @@ -15,3 +17,64 @@ func EncodeMd5(str string) string {
 | 
	
		
			
				|  |  |  	m.Write([]byte(str))
 | 
	
		
			
				|  |  |  	return hex.EncodeToString(m.Sum(nil))
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Seconds-based time units
 | 
	
		
			
				|  |  | +const (
 | 
	
		
			
				|  |  | +	Minute = 60
 | 
	
		
			
				|  |  | +	Hour   = 60 * Minute
 | 
	
		
			
				|  |  | +	Day    = 24 * Hour
 | 
	
		
			
				|  |  | +	Week   = 7 * Day
 | 
	
		
			
				|  |  | +	Month  = 30 * Day
 | 
	
		
			
				|  |  | +	Year   = 12 * Month
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// TimeSince calculates the time interval and generate user-friendly string.
 | 
	
		
			
				|  |  | +func TimeSince(then time.Time) string {
 | 
	
		
			
				|  |  | +	now := time.Now()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	lbl := "ago"
 | 
	
		
			
				|  |  | +	diff := now.Unix() - then.Unix()
 | 
	
		
			
				|  |  | +	if then.After(now) {
 | 
	
		
			
				|  |  | +		lbl = "from now"
 | 
	
		
			
				|  |  | +		diff = then.Unix() - now.Unix()
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	switch {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	case diff <= 0:
 | 
	
		
			
				|  |  | +		return "now"
 | 
	
		
			
				|  |  | +	case diff <= 2:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("1 second %s", lbl)
 | 
	
		
			
				|  |  | +	case diff < 1*Minute:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("%d seconds %s", diff, lbl)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	case diff < 2*Minute:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("1 minute %s", lbl)
 | 
	
		
			
				|  |  | +	case diff < 1*Hour:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("%d minutes %s", diff/Minute, lbl)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	case diff < 2*Hour:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("1 hour %s", lbl)
 | 
	
		
			
				|  |  | +	case diff < 1*Day:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("%d hours %s", diff/Hour, lbl)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	case diff < 2*Day:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("1 day %s", lbl)
 | 
	
		
			
				|  |  | +	case diff < 1*Week:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("%d days %s", diff/Day, lbl)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	case diff < 2*Week:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("1 week %s", lbl)
 | 
	
		
			
				|  |  | +	case diff < 1*Month:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("%d weeks %s", diff/Week, lbl)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	case diff < 2*Month:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("1 month %s", lbl)
 | 
	
		
			
				|  |  | +	case diff < 1*Year:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("%d months %s", diff/Month, lbl)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	case diff < 18*Month:
 | 
	
		
			
				|  |  | +		return fmt.Sprintf("1 year %s", lbl)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return then.String()
 | 
	
		
			
				|  |  | +}
 |