github.com/go-graphite/carbonapi@v0.17.0/date/date.go (about)

     1  package date
     2  
     3  import (
     4  	"errors"
     5  	"strconv"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/go-graphite/carbonapi/pkg/parser"
    10  )
    11  
    12  var errBadTime = errors.New("bad time")
    13  var timeNow = time.Now
    14  
    15  // parseTime parses a time and returns hours and minutes
    16  func parseTime(s string) (hour, minute int, err error) {
    17  
    18  	switch s {
    19  	case "midnight":
    20  		return 0, 0, nil
    21  	case "noon":
    22  		return 12, 0, nil
    23  	case "teatime":
    24  		return 16, 0, nil
    25  	}
    26  
    27  	parts := strings.Split(s, ":")
    28  
    29  	if len(parts) != 2 {
    30  		return 0, 0, errBadTime
    31  	}
    32  
    33  	hour, err = strconv.Atoi(parts[0])
    34  	if err != nil {
    35  		return 0, 0, errBadTime
    36  	}
    37  
    38  	minute, err = strconv.Atoi(parts[1])
    39  	if err != nil {
    40  		return 0, 0, errBadTime
    41  	}
    42  
    43  	return hour, minute, nil
    44  }
    45  
    46  var TimeFormats = []string{"20060102", "01/02/06"}
    47  
    48  // DateParamToEpoch turns a passed string parameter into a unix epoch
    49  func DateParamToEpoch(s, qtz string, d int64, defaultTimeZone *time.Location) int64 {
    50  
    51  	if s == "" {
    52  		// return the default if nothing was passed
    53  		return d
    54  	}
    55  
    56  	// relative timestamp
    57  	if s[0] == '-' {
    58  		offset, err := parser.IntervalString(s, -1)
    59  		if err != nil {
    60  			return d
    61  		}
    62  
    63  		return timeNow().Add(time.Duration(offset) * time.Second).Unix()
    64  	}
    65  
    66  	switch s {
    67  	case "now":
    68  		return timeNow().Unix()
    69  	case "midnight", "noon", "teatime":
    70  		yy, mm, dd := timeNow().Date()
    71  		hh, min, _ := parseTime(s) // error ignored, we know it's valid
    72  		dt := time.Date(yy, mm, dd, hh, min, 0, 0, defaultTimeZone)
    73  		return dt.Unix()
    74  	}
    75  
    76  	sint, err := strconv.Atoi(s)
    77  	// need to check that len(s) != 8 to avoid turning 20060102 into seconds
    78  	if err == nil && len(s) != 8 {
    79  		return int64(sint) // We got a timestamp so returning it
    80  	}
    81  
    82  	s = strings.Replace(s, "_", " ", 1) // Go can't parse _ in date strings
    83  
    84  	var ts, ds string
    85  	split := strings.Fields(s)
    86  
    87  	switch {
    88  	case len(split) == 1:
    89  		ds = s
    90  	case len(split) == 2:
    91  		ts, ds = split[0], split[1]
    92  	case len(split) > 2:
    93  		return d
    94  	}
    95  
    96  	var tz = defaultTimeZone
    97  	if qtz != "" {
    98  		if z, err := time.LoadLocation(qtz); err != nil {
    99  			tz = z
   100  		}
   101  	}
   102  
   103  	var t time.Time
   104  dateStringSwitch:
   105  	switch ds {
   106  	case "today":
   107  		t = timeNow()
   108  		// nothing
   109  	case "yesterday":
   110  		t = timeNow().AddDate(0, 0, -1)
   111  	case "tomorrow":
   112  		t = timeNow().AddDate(0, 0, 1)
   113  	default:
   114  		for _, format := range TimeFormats {
   115  			t, err = time.ParseInLocation(format, ds, tz)
   116  			if err == nil {
   117  				break dateStringSwitch
   118  			}
   119  		}
   120  
   121  		return d
   122  	}
   123  
   124  	var hour, minute int
   125  	if ts != "" {
   126  		hour, minute, _ = parseTime(ts)
   127  		// defaults to hour=0, minute=0 on error, which is midnight, which is fine for now
   128  	}
   129  
   130  	yy, mm, dd := t.Date()
   131  	t = time.Date(yy, mm, dd, hour, minute, 0, 0, defaultTimeZone)
   132  
   133  	return t.Unix()
   134  }