github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/duration/duration.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package duration
    12  
    13  import (
    14  	"bytes"
    15  	"fmt"
    16  	"math"
    17  	"math/big"
    18  	"strings"
    19  	"time"
    20  	"unicode"
    21  
    22  	"github.com/cockroachdb/apd/v3"
    23  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgcode"
    24  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgerror"
    25  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/types"
    26  	"github.com/cockroachdb/cockroachdb-parser/pkg/util/arith"
    27  	"github.com/cockroachdb/errors"
    28  )
    29  
    30  const (
    31  	// MicrosPerMilli is the amount of microseconds in a millisecond.
    32  	MicrosPerMilli = 1000
    33  	// MillisPerSec is the amount of milliseconds in a second.
    34  	MillisPerSec = 1000
    35  	// MicrosPerSec is the amount of microseconds in a second.
    36  	MicrosPerSec = MicrosPerMilli * MillisPerSec
    37  	// SecsPerMinute is the amount of seconds in a minute.
    38  	SecsPerMinute = 60
    39  	// SecsPerHour is the amount of seconds in an hour.
    40  	SecsPerHour = 3600
    41  	// SecsPerDay is the amount of seconds in a day.
    42  	SecsPerDay = 86400
    43  	// MinsPerHour is the amount of minutes in an hour.
    44  	MinsPerHour = 60
    45  	// HoursPerDay is the number of hours in a day.
    46  	HoursPerDay = 24
    47  	// DaysPerMonth is the assumed amount of days in a month.
    48  	// is always evaluated to 30, as it is in postgres.
    49  	DaysPerMonth = 30
    50  	// DaysPerYear is the number of days in a year.
    51  	// It is assumed to include a quarter day to account for the leap year.
    52  	// Matches DAYS_PER_YEAR in postgres.
    53  	DaysPerYear = 365.25
    54  	// MonthsPerYear is the amount of months in the year.
    55  	MonthsPerYear = 12
    56  )
    57  
    58  const (
    59  	nanosInDay    = 24 * int64(time.Hour) // Try as I might, couldn't do this without the cast.
    60  	nanosInMonth  = DaysPerMonth * nanosInDay
    61  	nanosInSecond = 1000 * 1000 * 1000
    62  	nanosInMicro  = 1000
    63  )
    64  
    65  var (
    66  	bigDaysInMonth  = apd.NewBigInt(DaysPerMonth)
    67  	bigNanosInDay   = apd.NewBigInt(nanosInDay)
    68  	bigNanosInMonth = apd.NewBigInt(nanosInMonth)
    69  )
    70  
    71  // errEncodeOverflow is returned by Encode when the sortNanos returned would
    72  // have overflowed or underflowed.
    73  var errEncodeOverflow = pgerror.WithCandidateCode(errors.New("overflow during Encode"), pgcode.IntervalFieldOverflow)
    74  
    75  // A Duration represents a length of time.
    76  //
    77  // A duration of "1 month" cannot be represented as a fixed number of
    78  // nanoseconds because the length of months vary. The same is true for days
    79  // because of leap seconds. Given a begin or end time to anchor a duration, the
    80  // nanosecond count can be calculated, but it's useful to represent durations
    81  // such as "1 year 3 months" without an anchor. Duration allows this.
    82  //
    83  // For the purposes of Compare and Encode, 1 month is considered equivalent to
    84  // 30 days and 1 day is equivalent to 24 * 60 * 60 * 1E9 nanoseconds.
    85  //
    86  // Although the Nanos field is a number of nanoseconds, all operations
    87  // round to the nearest microsecond. Any setting of this field should avoid
    88  // setting with precision below microseconds. The only exceptions are the
    89  // encode/decode operations.
    90  //
    91  // TODO(dan): Until the overflow and underflow handling is fixed, this is only
    92  // useful for durations of < 292 years.
    93  type Duration struct {
    94  	Months int64
    95  	Days   int64
    96  	// nanos is an unexported field so that it cannot be misused by other
    97  	// packages. It should almost always be rounded to the nearest microsecond.
    98  	nanos int64
    99  }
   100  
   101  // MakeDuration returns a Duration rounded to the nearest microsecond.
   102  func MakeDuration(nanos, days, months int64) Duration {
   103  	return Duration{
   104  		Months: months,
   105  		Days:   days,
   106  		nanos:  rounded(nanos),
   107  	}
   108  }
   109  
   110  // MakeDurationJustifyHours returns a duration where hours are moved
   111  // to days if the number of hours exceeds 24.
   112  func MakeDurationJustifyHours(nanos, days, months int64) Duration {
   113  	const nanosPerDay = int64(HoursPerDay * time.Hour)
   114  	extraDays := nanos / nanosPerDay
   115  	days += extraDays
   116  	nanos -= extraDays * nanosPerDay
   117  	return Duration{
   118  		Months: months,
   119  		Days:   days,
   120  		nanos:  rounded(nanos),
   121  	}
   122  }
   123  
   124  // Age returns a Duration rounded to the nearest microsecond
   125  // from the time difference of (lhs - rhs).
   126  //
   127  // Note that we cannot use time.Time's sub, as time.Duration does not give
   128  // an accurate picture of day/month differences.
   129  //
   130  // This is lifted from Postgres' timestamptz_age. The following comment applies:
   131  // Note that this does not result in an accurate absolute time span
   132  // since year and month are out of context once the arithmetic
   133  // is done.
   134  func Age(lhs, rhs time.Time) Duration {
   135  	// Strictly compare only UTC time.
   136  	lhs = lhs.UTC()
   137  	rhs = rhs.UTC()
   138  
   139  	years := int64(lhs.Year() - rhs.Year())
   140  	months := int64(lhs.Month() - rhs.Month())
   141  	days := int64(lhs.Day() - rhs.Day())
   142  	hours := int64(lhs.Hour() - rhs.Hour())
   143  	minutes := int64(lhs.Minute() - rhs.Minute())
   144  	seconds := int64(lhs.Second() - rhs.Second())
   145  	nanos := int64(lhs.Nanosecond() - rhs.Nanosecond())
   146  
   147  	flip := func() {
   148  		years = -years
   149  		months = -months
   150  		days = -days
   151  		hours = -hours
   152  		minutes = -minutes
   153  		seconds = -seconds
   154  		nanos = -nanos
   155  	}
   156  
   157  	// Flip signs so we're always operating from a positive.
   158  	if rhs.After(lhs) {
   159  		flip()
   160  	}
   161  
   162  	// For each field that is now negative, promote them to positive.
   163  	// We could probably use smarter math here, but to keep things simple and postgres-esque,
   164  	// we'll do the same way postgres does. We do not expect these overflow values
   165  	// to be too large from the math above anyway.
   166  	for nanos < 0 {
   167  		nanos += int64(time.Second)
   168  		seconds--
   169  	}
   170  	for seconds < 0 {
   171  		seconds += SecsPerMinute
   172  		minutes--
   173  	}
   174  	for minutes < 0 {
   175  		minutes += MinsPerHour
   176  		hours--
   177  	}
   178  	for hours < 0 {
   179  		hours += HoursPerDay
   180  		days--
   181  	}
   182  	for days < 0 {
   183  		// Get days in month preceding the current month of whichever is greater.
   184  		if rhs.After(lhs) {
   185  			days += daysInCurrentMonth(lhs)
   186  		} else {
   187  			days += daysInCurrentMonth(rhs)
   188  		}
   189  		months--
   190  	}
   191  	for months < 0 {
   192  		months += MonthsPerYear
   193  		years--
   194  	}
   195  
   196  	// Revert the sign back.
   197  	if rhs.After(lhs) {
   198  		flip()
   199  	}
   200  
   201  	return Duration{
   202  		Months: years*MonthsPerYear + months,
   203  		Days:   days,
   204  		nanos: rounded(
   205  			nanos +
   206  				int64(time.Second)*seconds +
   207  				int64(time.Minute)*minutes +
   208  				int64(time.Hour)*hours,
   209  		),
   210  	}
   211  }
   212  
   213  func daysInCurrentMonth(t time.Time) int64 {
   214  	// Take the first day of the month, add a month and subtract a day.
   215  	// This returns the last day of the month, which the number of days in the month.
   216  	return int64(time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.UTC).AddDate(0, 1, -1).Day())
   217  }
   218  
   219  // DecodeDuration returns a Duration without rounding nanos.
   220  func DecodeDuration(months, days, nanos int64) Duration {
   221  	return Duration{
   222  		Months: months,
   223  		Days:   days,
   224  		nanos:  nanos,
   225  	}
   226  }
   227  
   228  // Nanos returns the nanos of d.
   229  func (d Duration) Nanos() int64 {
   230  	return d.nanos
   231  }
   232  
   233  // SetNanos rounds and sets nanos.
   234  func (d *Duration) SetNanos(nanos int64) {
   235  	d.nanos = rounded(nanos)
   236  }
   237  
   238  // round rounds nanos to the nearest microsecond.
   239  func (d Duration) round() Duration {
   240  	d.nanos = rounded(d.nanos)
   241  	return d
   242  }
   243  
   244  // rounded returns nanos rounded to the nearest microsecond.
   245  func (d Duration) rounded() int64 {
   246  	return rounded(d.nanos)
   247  }
   248  
   249  // rounded returns nanos rounded to the nearest microsecond.
   250  func rounded(nanos int64) int64 {
   251  	dur := time.Duration(nanos) * time.Nanosecond
   252  	v := dur.Round(time.Microsecond).Nanoseconds()
   253  	// Near the boundaries of int64 will return the argument unchanged. Check
   254  	// for those cases and truncate instead of round so that we never have nanos.
   255  	if m := v % nanosInMicro; m != 0 {
   256  		v -= m
   257  	}
   258  	return v
   259  }
   260  
   261  // Compare returns an integer representing the relative length of two Durations.
   262  // The result will be 0 if d==x, -1 if d < x, and +1 if d > x.
   263  func (d Duration) Compare(x Duration) int {
   264  	normD := d.normalize()
   265  	normX := x.normalize()
   266  	if normD.Months < normX.Months {
   267  		return -1
   268  	} else if normD.Months > normX.Months {
   269  		return 1
   270  	} else if normD.Days < normX.Days {
   271  		return -1
   272  	} else if normD.Days > normX.Days {
   273  		return 1
   274  	} else if normD.nanos < normX.nanos {
   275  		return -1
   276  	} else if normD.nanos > normX.nanos {
   277  		return 1
   278  	}
   279  	return 0
   280  }
   281  
   282  // FromInt64 converts an int64 number of seconds to a
   283  // duration. Inverse conversion of AsInt64.
   284  func FromInt64(x int64) Duration {
   285  	days := x / (nanosInDay / nanosInSecond)
   286  	seconds := x % (nanosInDay / nanosInSecond)
   287  	d := Duration{Days: days, nanos: seconds * nanosInSecond}
   288  	return d.normalize()
   289  }
   290  
   291  // FromFloat64 converts a float64 number of seconds to a duration. Inverse
   292  // conversion of AsFloat64.
   293  func FromFloat64(x float64) Duration {
   294  	months := int64(x / float64(nanosInMonth/nanosInSecond))
   295  	secDays := math.Mod(x, float64(nanosInMonth/nanosInSecond))
   296  	days := int64(secDays / float64(nanosInDay/nanosInSecond))
   297  	secsRem := math.Mod(secDays, float64(nanosInDay/nanosInSecond))
   298  	d := Duration{Months: months, Days: days, nanos: int64(secsRem * 1e9)}
   299  	return d.normalize().round()
   300  }
   301  
   302  // FromBigInt converts an apd.BigInt number of nanoseconds to a duration. Inverse
   303  // conversion of AsBigInt. Boolean false if the result overflows.
   304  func FromBigInt(src *apd.BigInt) (Duration, bool) {
   305  	var rem apd.BigInt
   306  	var monthsDec apd.BigInt
   307  	monthsDec.QuoRem(src, bigNanosInMonth, &rem)
   308  	if !monthsDec.IsInt64() {
   309  		return Duration{}, false
   310  	}
   311  
   312  	var daysDec apd.BigInt
   313  	var nanosRem apd.BigInt
   314  	daysDec.QuoRem(&rem, bigNanosInDay, &nanosRem)
   315  	// Note: we do not need to check for overflow of daysDec because any
   316  	// excess bits were spilled into months above already.
   317  
   318  	d := Duration{Months: monthsDec.Int64(), Days: daysDec.Int64(), nanos: nanosRem.Int64()}
   319  	return d.normalize().round(), true
   320  }
   321  
   322  // AsInt64 converts a duration to an int64 number of seconds.
   323  // The conversion may overflow, in which case the boolean return
   324  // value is false.
   325  func (d Duration) AsInt64() (int64, bool) {
   326  	numYears := d.Months / 12
   327  	numMonthsInYear := d.Months % 12
   328  	// To do overflow detection with years, we have to convert to float in order
   329  	// to maintain accuracy, as DaysPerYear is a floating point number.
   330  	ySecs := float64(numYears*SecsPerDay) * DaysPerYear
   331  	// Since float has a higher range than int, fail if the number of seconds in the year
   332  	// value is greater than what an int can handle.
   333  	if ySecs > float64(math.MaxInt64) || ySecs < float64(math.MinInt64) {
   334  		return 0, false
   335  	}
   336  	mSecs, ok := arith.MulHalfPositiveWithOverflow(numMonthsInYear, nanosInMonth/nanosInSecond)
   337  	if !ok {
   338  		return 0, ok
   339  	}
   340  	dSecs, ok := arith.MulHalfPositiveWithOverflow(d.Days, nanosInDay/nanosInSecond)
   341  	if !ok {
   342  		return 0, ok
   343  	}
   344  	if dSecs, ok = arith.AddWithOverflow(mSecs, dSecs); !ok {
   345  		return 0, ok
   346  	}
   347  	if dSecs, ok = arith.AddWithOverflow(dSecs, int64(ySecs)); !ok {
   348  		return 0, ok
   349  	}
   350  	return arith.AddWithOverflow(dSecs, d.nanos/nanosInSecond)
   351  }
   352  
   353  // AsFloat64 converts a duration to a float64 number of seconds.
   354  func (d Duration) AsFloat64() float64 {
   355  	numYears := d.Months / 12
   356  	numMonthsInYear := d.Months % 12
   357  	return (float64(d.Nanos()) / float64(time.Second)) +
   358  		float64(d.Days*SecsPerDay) +
   359  		float64(numYears*SecsPerDay)*DaysPerYear +
   360  		float64(numMonthsInYear*DaysPerMonth*SecsPerDay)
   361  }
   362  
   363  // AsBigInt converts a duration to an apd.BigInt with the number of nanoseconds.
   364  func (d Duration) AsBigInt(dst *apd.BigInt) {
   365  	dst.SetInt64(d.Months)
   366  	dst.Mul(dst, bigDaysInMonth)
   367  	dst.Add(dst, apd.NewBigInt(d.Days))
   368  	dst.Mul(dst, bigNanosInDay)
   369  	// Uses rounded instead of nanos here to remove any on-disk nanos.
   370  	dst.Add(dst, apd.NewBigInt(d.rounded()))
   371  }
   372  
   373  const (
   374  	hourNanos   = uint64(time.Hour / time.Nanosecond)
   375  	minuteNanos = uint64(time.Minute / time.Nanosecond)
   376  	secondNanos = uint64(time.Second / time.Nanosecond)
   377  )
   378  
   379  // Format emits a string representation of a Duration to a Buffer truncated to microseconds.
   380  func (d Duration) Format(buf *bytes.Buffer) {
   381  	d.FormatWithStyle(buf, IntervalStyle_POSTGRES)
   382  }
   383  
   384  // FormatWithStyle emits a string representation of a Duration to a Buffer
   385  // truncated to microseconds with a given style.
   386  func (d Duration) FormatWithStyle(buf *bytes.Buffer, style IntervalStyle) {
   387  	switch style {
   388  	case IntervalStyle_POSTGRES:
   389  		d.encodePostgres(buf)
   390  	case IntervalStyle_ISO_8601:
   391  		d.encodeISO8601(buf)
   392  	case IntervalStyle_SQL_STANDARD:
   393  		d.encodeSQLStandard(buf)
   394  	default:
   395  		d.encodePostgres(buf)
   396  	}
   397  }
   398  
   399  func (d Duration) encodePostgres(buf *bytes.Buffer) {
   400  	if d.nanos == 0 && d.Days == 0 && d.Months == 0 {
   401  		buf.WriteString("00:00:00")
   402  		return
   403  	}
   404  
   405  	wrote := false
   406  	// Defining both arguments in the signature gives a 10% speedup.
   407  	wrotePrev := func(wrote bool, buf *bytes.Buffer) bool {
   408  		if wrote {
   409  			buf.WriteString(" ")
   410  		}
   411  		return true
   412  	}
   413  
   414  	months := d.Months
   415  	if absGE(months, 12) {
   416  		years := months / 12
   417  		wrote = wrotePrev(wrote, buf)
   418  		fmt.Fprintf(buf, "%d year%s", years, isPlural(years))
   419  		months %= 12
   420  	}
   421  	if months != 0 {
   422  		wrote = wrotePrev(wrote, buf)
   423  		fmt.Fprintf(buf, "%d mon%s", months, isPlural(months))
   424  	}
   425  
   426  	// Keep track of whether the previous unit was negative.
   427  	// If so, and the next one is positive, add `+` in front of the positive unit.
   428  	wasNegative := d.Months < 0
   429  	if d.Days != 0 {
   430  		wrote = wrotePrev(wrote, buf)
   431  		if wasNegative && d.Days > 0 {
   432  			buf.WriteString("+")
   433  		}
   434  		fmt.Fprintf(buf, "%d day%s", d.Days, isPlural(d.Days))
   435  		wasNegative = d.Days < 0
   436  	}
   437  
   438  	if d.nanos == 0 {
   439  		return
   440  	}
   441  
   442  	wrotePrev(wrote, buf)
   443  
   444  	if d.nanos/nanosInMicro < 0 {
   445  		buf.WriteString("-")
   446  	} else if wasNegative {
   447  		buf.WriteString("+")
   448  	}
   449  
   450  	hours, minutes, seconds, micros := extractAbsTime(d.nanos)
   451  	fmt.Fprintf(buf, "%02d:%02d:%02d", hours, minutes, seconds)
   452  
   453  	if micros != 0 {
   454  		s := fmt.Sprintf(".%06d", micros)
   455  		buf.WriteString(strings.TrimRight(s, "0"))
   456  	}
   457  }
   458  
   459  func (d Duration) encodeSQLStandard(buf *bytes.Buffer) {
   460  	hasNegative := d.Months < 0 || d.Days < 0 || d.nanos < 0
   461  	hasPositive := d.Months > 0 || d.Days > 0 || d.nanos > 0
   462  	hasYearMonth := d.Months != 0
   463  	hasDayTime := d.Days != 0 || d.nanos != 0
   464  	hasDay := d.Days != 0
   465  
   466  	// A SQL Standard value always has the same sign, and must only
   467  	// have Year-Month XOR (Days and/or Time) values.
   468  	sqlStandardValue := !(hasNegative && hasPositive) &&
   469  		!(hasYearMonth && hasDayTime)
   470  
   471  	var years, months, days int64
   472  	hours, minutes, seconds, micros := extractTime(d.nanos)
   473  	if absGE(d.Months, 12) {
   474  		years = d.Months / 12
   475  		d.Months %= 12
   476  	}
   477  	months = d.Months
   478  	days = d.Days
   479  
   480  	if hasNegative && sqlStandardValue {
   481  		buf.WriteByte('-')
   482  		years = -years
   483  		months = -months
   484  		days = -days
   485  		hours = -hours
   486  		minutes = -minutes
   487  		seconds = -seconds
   488  		micros = -micros
   489  	}
   490  
   491  	switch {
   492  	case !hasNegative && !hasPositive:
   493  		buf.WriteByte('0')
   494  	case !sqlStandardValue:
   495  		yearSign := '+'
   496  		if years < 0 || months < 0 {
   497  			yearSign = '-'
   498  			years = -years
   499  			months = -months
   500  		}
   501  		daySign := '+'
   502  		if days < 0 {
   503  			daySign = '-'
   504  			days = -days
   505  		}
   506  		secSign := '+'
   507  		if d.nanos < 0 {
   508  			secSign = '-'
   509  			hours = -hours
   510  			minutes = -minutes
   511  			seconds = -seconds
   512  			micros = -micros
   513  		}
   514  		needSpace := false
   515  		if hasYearMonth {
   516  			fmt.Fprintf(
   517  				buf,
   518  				"%c%d-%d",
   519  				yearSign, years, months,
   520  			)
   521  			needSpace = true
   522  		}
   523  		if hasDayTime {
   524  			if needSpace {
   525  				buf.WriteString(" ")
   526  			}
   527  			fmt.Fprintf(
   528  				buf,
   529  				"%c%d %c%d:%02d:",
   530  				daySign, days,
   531  				secSign, hours, minutes,
   532  			)
   533  			writeSecondsMicroseconds(buf, seconds, micros)
   534  		}
   535  	case hasYearMonth:
   536  		fmt.Fprintf(buf, "%d-%d", years, months)
   537  	case hasDay:
   538  		fmt.Fprintf(buf, "%d %d:%02d:", days, hours, minutes)
   539  		writeSecondsMicroseconds(buf, seconds, micros)
   540  	default:
   541  		fmt.Fprintf(buf, "%d:%02d:", hours, minutes)
   542  		writeSecondsMicroseconds(buf, seconds, micros)
   543  	}
   544  }
   545  
   546  func (d Duration) encodeISO8601(buf *bytes.Buffer) {
   547  	if d.nanos == 0 && d.Days == 0 && d.Months == 0 {
   548  		buf.WriteString("PT0S")
   549  		return
   550  	}
   551  
   552  	buf.WriteByte('P')
   553  	years := d.Months / 12
   554  	writeISO8601IntPart(buf, years, 'Y')
   555  	d.Months %= 12
   556  
   557  	writeISO8601IntPart(buf, d.Months, 'M')
   558  	writeISO8601IntPart(buf, d.Days, 'D')
   559  	if d.nanos != 0 {
   560  		buf.WriteByte('T')
   561  	}
   562  
   563  	hnAbs, mnAbs, snAbs, microsAbs := extractAbsTime(d.nanos)
   564  	hours := int64(hnAbs)
   565  	minutes := int64(mnAbs)
   566  	seconds := int64(snAbs)
   567  	microsSign := ""
   568  
   569  	if d.nanos < 0 {
   570  		hours = -hours
   571  		minutes = -minutes
   572  		seconds = -seconds
   573  		microsSign = "-"
   574  	}
   575  	writeISO8601IntPart(buf, hours, 'H')
   576  	writeISO8601IntPart(buf, minutes, 'M')
   577  
   578  	if microsAbs != 0 {
   579  		// the sign is captured by microsSign, hence using abs values here.
   580  		s := fmt.Sprintf("%s%d.%06d", microsSign, snAbs, microsAbs)
   581  		trimmed := strings.TrimRight(s, "0")
   582  		fmt.Fprintf(buf, "%sS", trimmed)
   583  	} else {
   584  		writeISO8601IntPart(buf, seconds, 'S')
   585  	}
   586  }
   587  
   588  // Return an ISO-8601-style interval field, but only if value isn't zero.
   589  func writeISO8601IntPart(buf *bytes.Buffer, value int64, units rune) {
   590  	if value == 0 {
   591  		return
   592  	}
   593  	fmt.Fprintf(buf, "%d%c", value, units)
   594  }
   595  
   596  func writeSecondsMicroseconds(buf *bytes.Buffer, seconds, micros int64) {
   597  	fmt.Fprintf(buf, "%02d", seconds)
   598  
   599  	if micros != 0 {
   600  		s := fmt.Sprintf(".%06d", micros)
   601  		buf.WriteString(strings.TrimRight(s, "0"))
   602  	}
   603  }
   604  
   605  // extractAbsTime returns positive amount of hours, minutes, seconds,
   606  // and microseconds contained in the given amount of nanoseconds.
   607  func extractAbsTime(nanosOrig int64) (hours, minutes, seconds, micros uint64) {
   608  	// Extract abs(d.nanos). See https://play.golang.org/p/U3_gNMpyUew.
   609  	var nanos uint64
   610  	if nanosOrig >= 0 {
   611  		nanos = uint64(nanosOrig)
   612  	} else {
   613  		nanos = uint64(-nanosOrig)
   614  	}
   615  
   616  	hours = nanos / hourNanos
   617  	nanos %= hourNanos
   618  	minutes = nanos / minuteNanos
   619  	nanos %= minuteNanos
   620  	seconds = nanos / secondNanos
   621  	nanos %= secondNanos
   622  	micros = nanos / nanosInMicro
   623  	return
   624  }
   625  
   626  // extractTime returns signed amount of hours, minutes, seconds,
   627  // and microseconds contained in the given amount of nanoseconds.
   628  func extractTime(nanosOrig int64) (hours, minutes, seconds, micros int64) {
   629  	hnAbs, mnAbs, snAbs, microsAbs := extractAbsTime(nanosOrig)
   630  	hours = int64(hnAbs)
   631  	minutes = int64(mnAbs)
   632  	seconds = int64(snAbs)
   633  	micros = int64(microsAbs)
   634  	if nanosOrig < 0 {
   635  		hours = -hours
   636  		minutes = -minutes
   637  		seconds = -seconds
   638  		micros = -micros
   639  	}
   640  	return
   641  }
   642  
   643  func isPlural(i int64) string {
   644  	if i == 1 {
   645  		return ""
   646  	}
   647  	return "s"
   648  }
   649  
   650  // absGE returns whether x is greater than or equal to y in magnitude.
   651  // y is always positive, x may be negative.
   652  func absGE(x, y int64) bool {
   653  	if x < 0 {
   654  		return x <= -y
   655  	}
   656  	return x >= y
   657  }
   658  
   659  // String returns a string representation of a Duration.
   660  func (d Duration) String() string {
   661  	var buf bytes.Buffer
   662  	d.Format(&buf)
   663  	return buf.String()
   664  }
   665  
   666  // ISO8601String returns an ISO 8601 representation ('P1Y2M3DT4H') of a Duration.
   667  func (d Duration) ISO8601String() string {
   668  	var buf bytes.Buffer
   669  	d.FormatWithStyle(&buf, IntervalStyle_ISO_8601)
   670  	return buf.String()
   671  }
   672  
   673  // StringNanos returns a string representation of a Duration including
   674  // its hidden nanoseconds value. To be used only by the encoding/decoding
   675  // packages for pretty printing of on-disk values. The encoded value is
   676  // expected to be in "postgres" interval style format.
   677  func (d Duration) StringNanos() string {
   678  	var buf bytes.Buffer
   679  	d.encodePostgres(&buf)
   680  	nanos := d.nanos % nanosInMicro
   681  	if nanos != 0 {
   682  		fmt.Fprintf(&buf, "%+dns", nanos)
   683  	}
   684  	return buf.String()
   685  }
   686  
   687  // Encode returns three integers such that the original Duration is recoverable
   688  // (using Decode) and the first int will approximately sort a collection of
   689  // encoded Durations.
   690  func (d Duration) Encode() (sortNanos int64, months int64, days int64, err error) {
   691  	// Calculate the total nanoseconds while checking for int64 overflow as:
   692  	//
   693  	//   totalNanos = d.Months*nanosInMonth + d.Days*nanosInDay * d.nanos
   694  	//
   695  	monthNanos, ok := arith.MulHalfPositiveWithOverflow(d.Months, nanosInMonth)
   696  	if !ok {
   697  		return 0, 0, 0, errEncodeOverflow
   698  	}
   699  	dayNanos, ok := arith.MulHalfPositiveWithOverflow(d.Days, nanosInDay)
   700  	if !ok {
   701  		return 0, 0, 0, errEncodeOverflow
   702  	}
   703  	totalNanos, ok := arith.AddWithOverflow(monthNanos, dayNanos)
   704  	if !ok {
   705  		return 0, 0, 0, errEncodeOverflow
   706  	}
   707  	totalNanos, ok = arith.AddWithOverflow(totalNanos, d.nanos)
   708  	if !ok {
   709  		return 0, 0, 0, errEncodeOverflow
   710  	}
   711  	return totalNanos, d.Months, d.Days, nil
   712  }
   713  
   714  // EncodeBigInt is the same as Encode, except that it always returns
   715  // successfully and is slower.
   716  func (d Duration) EncodeBigInt() (sortNanos *big.Int, months int64, days int64) {
   717  	bigMonths := big.NewInt(d.Months)
   718  	bigMonths.Mul(bigMonths, big.NewInt(nanosInMonth))
   719  	bigDays := big.NewInt(d.Days)
   720  	bigDays.Mul(bigDays, big.NewInt(nanosInDay))
   721  	totalNanos := big.NewInt(d.nanos)
   722  	totalNanos.Add(totalNanos, bigMonths).Add(totalNanos, bigDays)
   723  	return totalNanos, d.Months, d.Days
   724  }
   725  
   726  // Decode reverses the three integers returned from Encode and produces an equal
   727  // Duration to the original.
   728  func Decode(sortNanos int64, months int64, days int64) (Duration, error) {
   729  	nanos := sortNanos - months*nanosInMonth - days*nanosInDay
   730  	// TODO(dan): Handle underflow, then document that DecodeBigInt can be used
   731  	// in underflow cases.
   732  	return Duration{Months: months, Days: days, nanos: nanos}, nil
   733  }
   734  
   735  // TODO(dan): Write DecodeBigInt.
   736  
   737  // Add returns the time t+d, using a configurable mode.
   738  func Add(t time.Time, d Duration) time.Time {
   739  	// Fast path adding units < 1 day.
   740  	// Avoiding AddDate(0,0,0) is required to prevent changing times
   741  	// on DST boundaries.
   742  	// For example, 2020-10-2503:00+03 and 2020-10-25 03:00+02 are both
   743  	// valid times, but `time.Date` in `time.AddDate` may translate
   744  	// one to the other.
   745  	if d.Months == 0 && d.Days == 0 {
   746  		return t.Add(time.Duration(d.nanos))
   747  	}
   748  	// We can fast-path if the duration is always a fixed amount of time,
   749  	// or if the day number that we're starting from can never result
   750  	// in normalization.
   751  	if d.Months == 0 || t.Day() <= 28 {
   752  		return t.AddDate(0, int(d.Months), int(d.Days)).Add(time.Duration(d.nanos))
   753  	}
   754  
   755  	// Adjustments for 1-based math.
   756  	expectedMonth := time.Month((int(t.Month())-1+int(d.Months))%MonthsPerYear) + 1
   757  	// If we have a negative duration, we have a negative modulus.
   758  	// Push it back up to the positive expectedMonth.
   759  	if expectedMonth <= 0 {
   760  		expectedMonth += MonthsPerYear
   761  	}
   762  
   763  	// Use AddDate() to get a rough value.  This might overshoot the
   764  	// end of the expected month by multiple days.  We could iteratively
   765  	// subtract a day until we jump a month backwards, but that's
   766  	// at least twice as slow as computing the correct value ourselves.
   767  	res := t.AddDate(0 /* years */, int(d.Months), 0 /* days */)
   768  
   769  	// Unpack fields as little as possible.
   770  	year, month, _ := res.Date()
   771  	hour, min, sec := res.Clock()
   772  
   773  	if month != expectedMonth {
   774  		// Pro-tip: Count across your knuckles and the divots between
   775  		// them, wrapping around when you hit July. Knuckle == 31 days.
   776  		var lastDayOfMonth int
   777  		switch expectedMonth {
   778  		case time.February:
   779  			// Leap year if divisible by 4, but not centuries unless also divisible by 400.
   780  			// Adjust the earth's orbital parameters?
   781  			if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
   782  				lastDayOfMonth = 29
   783  			} else {
   784  				lastDayOfMonth = 28
   785  			}
   786  		case time.January, time.March, time.May, time.July, time.August, time.October, time.December:
   787  			lastDayOfMonth = 31
   788  		default:
   789  			lastDayOfMonth = 30
   790  		}
   791  
   792  		res = time.Date(
   793  			year, expectedMonth, lastDayOfMonth,
   794  			hour, min, sec,
   795  			res.Nanosecond(), res.Location())
   796  	}
   797  
   798  	return res.AddDate(0, 0, int(d.Days)).Add(time.Duration(d.nanos))
   799  }
   800  
   801  // Add returns a Duration representing a time length of d+x.
   802  func (d Duration) Add(x Duration) Duration {
   803  	return MakeDuration(d.nanos+x.nanos, d.Days+x.Days, d.Months+x.Months)
   804  }
   805  
   806  // Sub returns a Duration representing a time length of d-x.
   807  func (d Duration) Sub(x Duration) Duration {
   808  	return MakeDuration(d.nanos-x.nanos, d.Days-x.Days, d.Months-x.Months)
   809  }
   810  
   811  // Mul returns a Duration representing a time length of d*x.
   812  func (d Duration) Mul(x int64) Duration {
   813  	return MakeDuration(d.nanos*x, d.Days*x, d.Months*x)
   814  }
   815  
   816  // Div returns a Duration representing a time length of d/x.
   817  func (d Duration) Div(x int64) Duration {
   818  	return d.DivFloat(float64(x))
   819  }
   820  
   821  // MulFloat returns a Duration representing a time length of d*x.
   822  func (d Duration) MulFloat(x float64) Duration {
   823  	monthInt, monthFrac := math.Modf(float64(d.Months) * x)
   824  	dayInt, dayFrac := math.Modf((float64(d.Days) * x) + (monthFrac * DaysPerMonth))
   825  
   826  	return MakeDuration(
   827  		int64((float64(d.nanos)*x)+(dayFrac*float64(nanosInDay))),
   828  		int64(dayInt),
   829  		int64(monthInt),
   830  	)
   831  }
   832  
   833  // DivFloat returns a Duration representing a time length of d/x.
   834  func (d Duration) DivFloat(x float64) Duration {
   835  	// In order to keep it compatible with PostgreSQL, we use the same logic.
   836  	// Refer to https://github.com/postgres/postgres/blob/e56bce5d43789cce95d099554ae9593ada92b3b7/src/backend/utils/adt/timestamp.c#L3266-L3304.
   837  	month := int32(float64(d.Months) / x)
   838  	day := int32(float64(d.Days) / x)
   839  
   840  	remainderDays := (float64(d.Months)/x - float64(month)) * DaysPerMonth
   841  	remainderDays = secRoundToEven(remainderDays)
   842  	secRemainder := (float64(d.Days)/x - float64(day) +
   843  		remainderDays - float64(int64(remainderDays))) * SecsPerDay
   844  	secRemainder = secRoundToEven(secRemainder)
   845  	if math.Abs(secRemainder) >= SecsPerDay {
   846  		day += int32(secRemainder / SecsPerDay)
   847  		secRemainder -= float64(int32(secRemainder/SecsPerDay) * SecsPerDay)
   848  	}
   849  	day += int32(remainderDays)
   850  	microSecs := float64(time.Duration(d.nanos).Microseconds())/x + secRemainder*MicrosPerMilli*MillisPerSec
   851  	retNanos := time.Duration(int64(math.RoundToEven(microSecs))) * time.Microsecond
   852  
   853  	return MakeDuration(
   854  		retNanos.Nanoseconds(),
   855  		int64(day),
   856  		int64(month),
   857  	)
   858  }
   859  
   860  // secRoundToEven rounds the given float to the nearest second,
   861  // assuming the input float is a microsecond representation of
   862  // time
   863  // This maps to the TSROUND macro in Postgres.
   864  func secRoundToEven(f float64) float64 {
   865  	return math.RoundToEven(f*MicrosPerMilli*MillisPerSec) / (MicrosPerMilli * MillisPerSec)
   866  }
   867  
   868  // normalized returns a new Duration transformed using the equivalence rules.
   869  // Each quantity of days greater than the threshold is moved into months,
   870  // likewise for nanos. Integer overflow is avoided by partial transformation.
   871  func (d Duration) normalize() Duration {
   872  	if d.Days > 0 {
   873  		d = d.shiftPosDaysToMonths()
   874  	} else if d.Days < 0 {
   875  		d = d.shiftNegDaysToMonths()
   876  	}
   877  	// After shifting days into months, there are two cases:
   878  	// - Months did not hit MaxInt64 or MinInt64, in which case Days is now in
   879  	//   (-30,30). We shift nanos, then days one more time in case the nano shift
   880  	//   made a full month.
   881  	// - Months did hit MaxInt64 or MinInt64, in which case there can be no more
   882  	//   months. We only need to shift nanos.
   883  	if d.nanos > 0 {
   884  		d = d.shiftPosNanosToDays()
   885  		d = d.shiftPosDaysToMonths()
   886  	} else if d.nanos < 0 {
   887  		d = d.shiftNegNanosToDays()
   888  		d = d.shiftNegDaysToMonths()
   889  	}
   890  	return d
   891  }
   892  
   893  func (d Duration) shiftPosDaysToMonths() Duration {
   894  	var maxMonths = int64(math.MaxInt64)
   895  	if d.Months > 0 {
   896  		// If d.Months < 0, then this would overflow, but because of the exchange
   897  		// rate, we can never transfer more than math.MaxInt64 anyway.
   898  		maxMonths = math.MaxInt64 - d.Months
   899  	}
   900  	monthsFromDays := int64Min(d.Days/DaysPerMonth, maxMonths)
   901  	d.Months += monthsFromDays
   902  	d.Days -= monthsFromDays * DaysPerMonth
   903  	return d
   904  }
   905  
   906  func (d Duration) shiftPosNanosToDays() Duration {
   907  	var maxDays = int64(math.MaxInt64)
   908  	if d.Days > 0 {
   909  		// If d.Days < 0, then this would overflow, but because of the exchange
   910  		// rate, we can never transfer more than math.MaxInt64 anyway.
   911  		maxDays = math.MaxInt64 - d.Days
   912  	}
   913  	daysFromNanos := int64Min(d.nanos/nanosInDay, maxDays)
   914  	d.Days += daysFromNanos
   915  	d.nanos -= daysFromNanos * nanosInDay
   916  	return d
   917  }
   918  
   919  func (d Duration) shiftNegDaysToMonths() Duration {
   920  	var minMonths = int64(math.MinInt64)
   921  	if d.Months < 0 {
   922  		// If d.Months > 0, then this would overflow, but because of the exchange
   923  		// rate, we can never transfer more than math.MaxInt64 anyway.
   924  		minMonths = math.MinInt64 - d.Months
   925  	}
   926  	monthsFromDays := int64Max(d.Days/DaysPerMonth, minMonths)
   927  	d.Months += monthsFromDays
   928  	d.Days -= monthsFromDays * DaysPerMonth
   929  	return d
   930  }
   931  
   932  func (d Duration) shiftNegNanosToDays() Duration {
   933  	var minDays = int64(math.MinInt64)
   934  	if d.Days < 0 {
   935  		// If d.Days > 0, then this would overflow, but because of the exchange
   936  		// rate, we can never transfer more than math.MaxInt64 anyway.
   937  		minDays = math.MinInt64 - d.Days
   938  	}
   939  	daysFromNanos := int64Max(d.nanos/nanosInDay, minDays)
   940  	d.Days += daysFromNanos
   941  	d.nanos -= daysFromNanos * nanosInDay
   942  	return d
   943  }
   944  
   945  func int64Max(a int64, b int64) int64 {
   946  	if a > b {
   947  		return a
   948  	}
   949  	return b
   950  }
   951  
   952  func int64Min(a int64, b int64) int64 {
   953  	if a < b {
   954  		return a
   955  	}
   956  	return b
   957  }
   958  
   959  const (
   960  	minTimeDuration time.Duration = -1 << 63
   961  	maxTimeDuration time.Duration = 1<<63 - 1
   962  )
   963  
   964  // DiffMicros computes the microsecond difference between two time values. The reason
   965  // this function is necessary even though time.Sub(time) exists is that time.Duration
   966  // can only hold values up to ~290 years, because it stores duration at the nanosecond
   967  // resolution. This function should be used if a difference of more than 290 years is
   968  // possible between time values, and a microsecond resolution is acceptable.
   969  func DiffMicros(t1, t2 time.Time) int64 {
   970  	micros := int64(0)
   971  	nanos := time.Duration(0)
   972  	for {
   973  		// time.Sub(time) can overflow for durations larger than ~290 years, so
   974  		// we need to perform this diff iteratively. If this method overflows,
   975  		// it will return either minTimeDuration or maxTimeDuration.
   976  		d := t1.Sub(t2)
   977  		overflow := d == minTimeDuration || d == maxTimeDuration
   978  		if d == minTimeDuration {
   979  			// We use -maxTimeDuration here because -minTimeDuration would overflow.
   980  			d = -maxTimeDuration
   981  		}
   982  		micros += int64(d / time.Microsecond)
   983  		nanos += d % time.Microsecond
   984  		if !overflow {
   985  			break
   986  		}
   987  		t1 = t1.Add(-d)
   988  	}
   989  	micros += int64(nanos / time.Microsecond)
   990  	nanoRem := nanos % time.Microsecond
   991  	if nanoRem >= time.Microsecond/2 {
   992  		micros++
   993  	} else if nanoRem <= -time.Microsecond/2 {
   994  		micros--
   995  	}
   996  	return micros
   997  }
   998  
   999  // AddMicros adds the microsecond delta to the provided time value. The reason
  1000  // this function is necessary even though time.Add(duration) exists is that time.Duration
  1001  // can only hold values up to ~290 years, because it stores duration at the nanosecond
  1002  // resolution. This function makes it possible to add more than 290 years to a time.Time,
  1003  // at the tradeoff of working on a microsecond resolution.
  1004  func AddMicros(t time.Time, d int64) time.Time {
  1005  	negMult := time.Duration(1)
  1006  	if d < 0 {
  1007  		negMult = -1
  1008  		d = -d
  1009  	}
  1010  	const maxMicroDur = int64(maxTimeDuration / time.Microsecond)
  1011  	for d > maxMicroDur {
  1012  		const maxWholeNanoDur = time.Duration(maxMicroDur) * time.Microsecond
  1013  		t = t.Add(negMult * maxWholeNanoDur)
  1014  		d -= maxMicroDur
  1015  	}
  1016  	return t.Add(negMult * time.Duration(d) * time.Microsecond)
  1017  }
  1018  
  1019  // Truncate returns a new duration obtained from the first argument
  1020  // by discarding the portions at finer resolution than that given by the
  1021  // second argument.
  1022  // Example: Truncate(time.Second+1, time.Second) == time.Second.
  1023  func Truncate(d time.Duration, r time.Duration) time.Duration {
  1024  	if r == 0 {
  1025  		panic(errors.AssertionFailedf("zero passed as resolution"))
  1026  	}
  1027  	return d - (d % r)
  1028  }
  1029  
  1030  // ParseInterval parses the given interval in the given style.
  1031  func ParseInterval(
  1032  	style IntervalStyle, s string, itm types.IntervalTypeMetadata,
  1033  ) (Duration, error) {
  1034  	// At this time the only supported interval formats are:
  1035  	// - SQL standard.
  1036  	// - Postgres compatible.
  1037  	// - iso8601 format (with designators only), see interval.go for
  1038  	//   sources of documentation.
  1039  	// - Golang time.parseDuration compatible.
  1040  
  1041  	// If it's a blank string, exit early.
  1042  	if len(s) == 0 {
  1043  		return Duration{}, makeParseError(s, types.Interval, nil)
  1044  	}
  1045  	if s[0] == 'P' {
  1046  		// If it has a leading P we're most likely working with an iso8601
  1047  		// interval.
  1048  		dur, err := iso8601ToDuration(s)
  1049  		if err != nil {
  1050  			return Duration{}, makeParseError(s, types.Interval, err)
  1051  		}
  1052  		return dur, nil
  1053  	}
  1054  	if strings.IndexFunc(s, unicode.IsLetter) == -1 {
  1055  		// If it has no letter, then we're most likely working with a SQL standard
  1056  		// interval, as both postgres and golang have letter(s) and iso8601 has been tested.
  1057  		dur, err := sqlStdToDuration(s, itm)
  1058  		if err != nil {
  1059  			return Duration{}, makeParseError(s, types.Interval, err)
  1060  		}
  1061  		return dur, nil
  1062  	}
  1063  
  1064  	// We're either a postgres string or a Go duration.
  1065  	// Our postgres syntax parser also supports golang, so just use that for both.
  1066  	dur, err := parseDuration(style, s, itm)
  1067  	if err != nil {
  1068  		return Duration{}, makeParseError(s, types.Interval, err)
  1069  	}
  1070  	return dur, nil
  1071  }
  1072  
  1073  func makeParseError(s string, typ *types.T, err error) error {
  1074  	if err != nil {
  1075  		return pgerror.Wrapf(err, pgcode.InvalidTextRepresentation,
  1076  			"could not parse %q as type %s", s, typ)
  1077  	}
  1078  	return pgerror.Newf(pgcode.InvalidTextRepresentation,
  1079  		"could not parse %q as type %s", s, typ)
  1080  }