github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/prometheus/common/model/time.go (about)

     1  // Copyright 2013 The Prometheus Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package model
    15  
    16  import (
    17  	"fmt"
    18  	"math"
    19  	"regexp"
    20  	"strconv"
    21  	"strings"
    22  	"time"
    23  )
    24  
    25  const (
    26  	// MinimumTick is the minimum supported time resolution. This has to be
    27  	// at least time.Second in order for the code below to work.
    28  	minimumTick = time.Millisecond
    29  	// second is the Time duration equivalent to one second.
    30  	second = int64(time.Second / minimumTick)
    31  	// The number of nanoseconds per minimum tick.
    32  	nanosPerTick = int64(minimumTick / time.Nanosecond)
    33  
    34  	// Earliest is the earliest Time representable. Handy for
    35  	// initializing a high watermark.
    36  	Earliest = Time(math.MinInt64)
    37  	// Latest is the latest Time representable. Handy for initializing
    38  	// a low watermark.
    39  	Latest = Time(math.MaxInt64)
    40  )
    41  
    42  // Time is the number of milliseconds since the epoch
    43  // (1970-01-01 00:00 UTC) excluding leap seconds.
    44  type Time int64
    45  
    46  // Interval describes an interval between two timestamps.
    47  type Interval struct {
    48  	Start, End Time
    49  }
    50  
    51  // Now returns the current time as a Time.
    52  func Now() Time {
    53  	return TimeFromUnixNano(time.Now().UnixNano())
    54  }
    55  
    56  // TimeFromUnix returns the Time equivalent to the Unix Time t
    57  // provided in seconds.
    58  func TimeFromUnix(t int64) Time {
    59  	return Time(t * second)
    60  }
    61  
    62  // TimeFromUnixNano returns the Time equivalent to the Unix Time
    63  // t provided in nanoseconds.
    64  func TimeFromUnixNano(t int64) Time {
    65  	return Time(t / nanosPerTick)
    66  }
    67  
    68  // Equal reports whether two Times represent the same instant.
    69  func (t Time) Equal(o Time) bool {
    70  	return t == o
    71  }
    72  
    73  // Before reports whether the Time t is before o.
    74  func (t Time) Before(o Time) bool {
    75  	return t < o
    76  }
    77  
    78  // After reports whether the Time t is after o.
    79  func (t Time) After(o Time) bool {
    80  	return t > o
    81  }
    82  
    83  // Add returns the Time t + d.
    84  func (t Time) Add(d time.Duration) Time {
    85  	return t + Time(d/minimumTick)
    86  }
    87  
    88  // Sub returns the Duration t - o.
    89  func (t Time) Sub(o Time) time.Duration {
    90  	return time.Duration(t-o) * minimumTick
    91  }
    92  
    93  // Time returns the time.Time representation of t.
    94  func (t Time) Time() time.Time {
    95  	return time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick)
    96  }
    97  
    98  // Unix returns t as a Unix time, the number of seconds elapsed
    99  // since January 1, 1970 UTC.
   100  func (t Time) Unix() int64 {
   101  	return int64(t) / second
   102  }
   103  
   104  // UnixNano returns t as a Unix time, the number of nanoseconds elapsed
   105  // since January 1, 1970 UTC.
   106  func (t Time) UnixNano() int64 {
   107  	return int64(t) * nanosPerTick
   108  }
   109  
   110  // The number of digits after the dot.
   111  var dotPrecision = int(math.Log10(float64(second)))
   112  
   113  // String returns a string representation of the Time.
   114  func (t Time) String() string {
   115  	return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
   116  }
   117  
   118  // MarshalJSON implements the json.Marshaler interface.
   119  func (t Time) MarshalJSON() ([]byte, error) {
   120  	return []byte(t.String()), nil
   121  }
   122  
   123  // UnmarshalJSON implements the json.Unmarshaler interface.
   124  func (t *Time) UnmarshalJSON(b []byte) error {
   125  	p := strings.Split(string(b), ".")
   126  	switch len(p) {
   127  	case 1:
   128  		v, err := strconv.ParseInt(string(p[0]), 10, 64)
   129  		if err != nil {
   130  			return err
   131  		}
   132  		*t = Time(v * second)
   133  
   134  	case 2:
   135  		v, err := strconv.ParseInt(string(p[0]), 10, 64)
   136  		if err != nil {
   137  			return err
   138  		}
   139  		v *= second
   140  
   141  		prec := dotPrecision - len(p[1])
   142  		if prec < 0 {
   143  			p[1] = p[1][:dotPrecision]
   144  		} else if prec > 0 {
   145  			p[1] = p[1] + strings.Repeat("0", prec)
   146  		}
   147  
   148  		va, err := strconv.ParseInt(p[1], 10, 32)
   149  		if err != nil {
   150  			return err
   151  		}
   152  
   153  		*t = Time(v + va)
   154  
   155  	default:
   156  		return fmt.Errorf("invalid time %q", string(b))
   157  	}
   158  	return nil
   159  }
   160  
   161  // Duration wraps time.Duration. It is used to parse the custom duration format
   162  // from YAML.
   163  // This type should not propagate beyond the scope of input/output processing.
   164  type Duration time.Duration
   165  
   166  // Set implements pflag/flag.Value
   167  func (d *Duration) Set(s string) error {
   168  	var err error
   169  	*d, err = ParseDuration(s)
   170  	return err
   171  }
   172  
   173  // Type implements pflag.Value
   174  func (d *Duration) Type() string {
   175  	return "duration"
   176  }
   177  
   178  var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$")
   179  
   180  // ParseDuration parses a string into a time.Duration, assuming that a year
   181  // always has 365d, a week always has 7d, and a day always has 24h.
   182  func ParseDuration(durationStr string) (Duration, error) {
   183  	matches := durationRE.FindStringSubmatch(durationStr)
   184  	if len(matches) != 3 {
   185  		return 0, fmt.Errorf("not a valid duration string: %q", durationStr)
   186  	}
   187  	var (
   188  		n, _ = strconv.Atoi(matches[1])
   189  		dur  = time.Duration(n) * time.Millisecond
   190  	)
   191  	switch unit := matches[2]; unit {
   192  	case "y":
   193  		dur *= 1000 * 60 * 60 * 24 * 365
   194  	case "w":
   195  		dur *= 1000 * 60 * 60 * 24 * 7
   196  	case "d":
   197  		dur *= 1000 * 60 * 60 * 24
   198  	case "h":
   199  		dur *= 1000 * 60 * 60
   200  	case "m":
   201  		dur *= 1000 * 60
   202  	case "s":
   203  		dur *= 1000
   204  	case "ms":
   205  		// Value already correct
   206  	default:
   207  		return 0, fmt.Errorf("invalid time unit in duration string: %q", unit)
   208  	}
   209  	return Duration(dur), nil
   210  }
   211  
   212  func (d Duration) String() string {
   213  	var (
   214  		ms   = int64(time.Duration(d) / time.Millisecond)
   215  		unit = "ms"
   216  	)
   217  	if ms == 0 {
   218  		return "0s"
   219  	}
   220  	factors := map[string]int64{
   221  		"y":  1000 * 60 * 60 * 24 * 365,
   222  		"w":  1000 * 60 * 60 * 24 * 7,
   223  		"d":  1000 * 60 * 60 * 24,
   224  		"h":  1000 * 60 * 60,
   225  		"m":  1000 * 60,
   226  		"s":  1000,
   227  		"ms": 1,
   228  	}
   229  
   230  	switch int64(0) {
   231  	case ms % factors["y"]:
   232  		unit = "y"
   233  	case ms % factors["w"]:
   234  		unit = "w"
   235  	case ms % factors["d"]:
   236  		unit = "d"
   237  	case ms % factors["h"]:
   238  		unit = "h"
   239  	case ms % factors["m"]:
   240  		unit = "m"
   241  	case ms % factors["s"]:
   242  		unit = "s"
   243  	}
   244  	return fmt.Sprintf("%v%v", ms/factors[unit], unit)
   245  }
   246  
   247  // MarshalYAML implements the yaml.Marshaler interface.
   248  func (d Duration) MarshalYAML() (interface{}, error) {
   249  	return d.String(), nil
   250  }
   251  
   252  // UnmarshalYAML implements the yaml.Unmarshaler interface.
   253  func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
   254  	var s string
   255  	if err := unmarshal(&s); err != nil {
   256  		return err
   257  	}
   258  	dur, err := ParseDuration(s)
   259  	if err != nil {
   260  		return err
   261  	}
   262  	*d = dur
   263  	return nil
   264  }