From 4312f7d62d657e3292cce0a824e5d3e594479f4a Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 18 Sep 2023 09:30:29 +0200 Subject: [PATCH 1/2] helpers/validate: adding a test for .net's `TimeSpan.MaxValue` used by ServiceBus --- helpers/validate/time_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/helpers/validate/time_test.go b/helpers/validate/time_test.go index e455d0dab155..d275f76bfeb1 100644 --- a/helpers/validate/time_test.go +++ b/helpers/validate/time_test.go @@ -81,6 +81,11 @@ func TestISO8601Duration(t *testing.T) { Value: "P1Y2M3DT7H42M3S", Errors: 0, }, + { + // .Net's TimeSpan.Max value (used as the default value for ServiceBus Topics) + Value: "P10675199DT2H48M5.4775807S", + Errors: 0, + }, { // Invalid prefix Value: "1Y2M3DT7H42M3S", From d7507e149d5ba4421dbd4e2106e6095c7be768a1 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 18 Sep 2023 09:33:36 +0200 Subject: [PATCH 2/2] dependencies: downgrading to `v1.12.5` of `github.com/rickb777/date` --- go.mod | 2 +- go.sum | 7 +- .../rickb777/date/period/arithmetic.go | 106 ----- .../rickb777/date/period/designator.go | 55 --- vendor/github.com/rickb777/date/period/doc.go | 4 +- .../github.com/rickb777/date/period/flag.go | 16 - .../github.com/rickb777/date/period/format.go | 83 ++-- .../rickb777/date/period/marshal.go | 6 +- .../github.com/rickb777/date/period/parse.go | 255 ++++------- .../github.com/rickb777/date/period/period.go | 433 ++++++++++++------ .../rickb777/date/period/period64.go | 142 ------ vendor/github.com/rickb777/date/period/sql.go | 36 -- vendor/modules.txt | 4 +- 13 files changed, 415 insertions(+), 734 deletions(-) delete mode 100644 vendor/github.com/rickb777/date/period/arithmetic.go delete mode 100644 vendor/github.com/rickb777/date/period/designator.go delete mode 100644 vendor/github.com/rickb777/date/period/flag.go delete mode 100644 vendor/github.com/rickb777/date/period/period64.go delete mode 100644 vendor/github.com/rickb777/date/period/sql.go diff --git a/go.mod b/go.mod index cf3450f061bf..bbc7ea7409a6 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/hashicorp/terraform-plugin-testing v1.5.1 github.com/magodo/terraform-provider-azurerm-example-gen v0.0.0-20220407025246-3a3ee0ab24a8 github.com/mitchellh/mapstructure v1.5.0 - github.com/rickb777/date v1.20.2 + github.com/rickb777/date v1.12.5-0.20200422084442-6300e543c4d9 github.com/sergi/go-diff v1.2.0 github.com/tombuildsstuff/giovanni v0.20.0 github.com/tombuildsstuff/kermit v0.20230703.1101016 diff --git a/go.sum b/go.sum index f3d63273ba7a..f52848aef91e 100644 --- a/go.sum +++ b/go.sum @@ -175,6 +175,7 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -192,12 +193,12 @@ github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DV github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rickb777/date v1.20.2 h1:CUpAaa4ksqvcRaidSgwzK7zeO2wUG5/VGy6Zlfcu/d4= -github.com/rickb777/date v1.20.2/go.mod h1:PVaM/Zn0IOzjm1uj84Eh9NJ/imtQSm1SVKtOvIunaYw= +github.com/rickb777/date v1.12.5-0.20200422084442-6300e543c4d9 h1:czJCcoUR3FMpHnRQow2E84H/0CPrX1fMAGn9HugzyI4= +github.com/rickb777/date v1.12.5-0.20200422084442-6300e543c4d9/go.mod h1:L8WrssTzvgYw34/Ppa0JpJfI7KKXZ2cVGI6Djt0brUU= +github.com/rickb777/plural v1.2.0/go.mod h1:UdpyWFCGbo3mvK3f/PfZOAOrkjzJlYN/sD46XNWJ+Es= github.com/rickb777/plural v1.4.1 h1:5MMLcbIaapLFmvDGRT5iPk8877hpTPt8Y9cdSKRw9sU= github.com/rickb777/plural v1.4.1/go.mod h1:kdmXUpmKBJTS0FtG/TFumd//VBWsNTD7zOw7x4umxNw= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= diff --git a/vendor/github.com/rickb777/date/period/arithmetic.go b/vendor/github.com/rickb777/date/period/arithmetic.go deleted file mode 100644 index 55993fe0b744..000000000000 --- a/vendor/github.com/rickb777/date/period/arithmetic.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2015 Rick Beton. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package period - -import ( - "time" -) - -// Add adds two periods together. Use this method along with Negate in order to subtract periods. -// -// The result is not normalised and may overflow arithmetically (to make this unlikely, use Normalise on -// the inputs before adding them). -func (period Period) Add(that Period) Period { - return Period{ - period.years + that.years, - period.months + that.months, - period.days + that.days, - period.hours + that.hours, - period.minutes + that.minutes, - period.seconds + that.seconds, - } -} - -//------------------------------------------------------------------------------------------------- - -// AddTo adds the period to a time, returning the result. -// A flag is also returned that is true when the conversion was precise and false otherwise. -// -// When the period specifies hours, minutes and seconds only, the result is precise. -// Also, when the period specifies whole years, months and days (i.e. without fractions), the -// result is precise. However, when years, months or days contains fractions, the result -// is only an approximation (it assumes that all days are 24 hours and every year is 365.2425 -// days, as per Gregorian calendar rules). -func (period Period) AddTo(t time.Time) (time.Time, bool) { - wholeYears := (period.years % 10) == 0 - wholeMonths := (period.months % 10) == 0 - wholeDays := (period.days % 10) == 0 - - if wholeYears && wholeMonths && wholeDays { - // in this case, time.AddDate provides an exact solution - stE3 := totalSecondsE3(period) - t1 := t.AddDate(int(period.years/10), int(period.months/10), int(period.days/10)) - return t1.Add(stE3 * time.Millisecond), true - } - - d, precise := period.Duration() - return t.Add(d), precise -} - -//------------------------------------------------------------------------------------------------- - -// Scale a period by a multiplication factor. Obviously, this can both enlarge and shrink it, -// and change the sign if negative. The result is normalised, but integer overflows are silently -// ignored. -// -// Bear in mind that the internal representation is limited by fixed-point arithmetic with two -// decimal places; each field is only int16. -// -// Known issue: scaling by a large reduction factor (i.e. much less than one) doesn't work properly. -func (period Period) Scale(factor float32) Period { - result, _ := period.ScaleWithOverflowCheck(factor) - return result -} - -// ScaleWithOverflowCheck a period by a multiplication factor. Obviously, this can both enlarge and shrink it, -// and change the sign if negative. The result is normalised. An error is returned if integer overflow -// happened. -// -// Bear in mind that the internal representation is limited by fixed-point arithmetic with one -// decimal place; each field is only int16. -// -// Known issue: scaling by a large reduction factor (i.e. much less than one) doesn't work properly. -func (period Period) ScaleWithOverflowCheck(factor float32) (Period, error) { - ap, neg := period.absNeg() - - if -0.5 < factor && factor < 0.5 { - d, pr1 := ap.Duration() - mul := float64(d) * float64(factor) - p2, pr2 := NewOf(time.Duration(mul)) - return p2.Normalise(pr1 && pr2), nil - } - - y := int64(float32(ap.years) * factor) - m := int64(float32(ap.months) * factor) - d := int64(float32(ap.days) * factor) - hh := int64(float32(ap.hours) * factor) - mm := int64(float32(ap.minutes) * factor) - ss := int64(float32(ap.seconds) * factor) - - p64 := &period64{years: y, months: m, days: d, hours: hh, minutes: mm, seconds: ss, neg: neg} - return p64.normalise64(true).toPeriod() -} - -// RationalScale scales a period by a rational multiplication factor. Obviously, this can both enlarge and shrink it, -// and change the sign if negative. The result is normalised. An error is returned if integer overflow -// happened. -// -// If the divisor is zero, a panic will arise. -// -// Bear in mind that the internal representation is limited by fixed-point arithmetic with two -// decimal places; each field is only int16. -//func (period Period) RationalScale(multiplier, divisor int) (Period, error) { -// return period.rationalScale64(int64(multiplier), int64(divisor)) -//} diff --git a/vendor/github.com/rickb777/date/period/designator.go b/vendor/github.com/rickb777/date/period/designator.go deleted file mode 100644 index 6d836ec4c638..000000000000 --- a/vendor/github.com/rickb777/date/period/designator.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2015 Rick Beton. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package period - -type ymdDesignator byte -type hmsDesignator byte - -const ( - Year ymdDesignator = 'Y' - Month ymdDesignator = 'M' - Week ymdDesignator = 'W' - Day ymdDesignator = 'D' - - Hour hmsDesignator = 'H' - Minute hmsDesignator = 'M' - Second hmsDesignator = 'S' -) - -func (d ymdDesignator) IsOneOf(xx ...ymdDesignator) bool { - for _, x := range xx { - if x == d { - return true - } - } - return false -} - -func (d ymdDesignator) IsNotOneOf(xx ...ymdDesignator) bool { - for _, x := range xx { - if x == d { - return false - } - } - return true -} - -func (d hmsDesignator) IsOneOf(xx ...hmsDesignator) bool { - for _, x := range xx { - if x == d { - return true - } - } - return false -} - -func (d hmsDesignator) IsNotOneOf(xx ...hmsDesignator) bool { - for _, x := range xx { - if x == d { - return false - } - } - return true -} diff --git a/vendor/github.com/rickb777/date/period/doc.go b/vendor/github.com/rickb777/date/period/doc.go index 5abe8447b16c..c8a57b4a0d94 100644 --- a/vendor/github.com/rickb777/date/period/doc.go +++ b/vendor/github.com/rickb777/date/period/doc.go @@ -5,9 +5,6 @@ // Package period provides functionality for periods of time using ISO-8601 conventions. // This deals with years, months, weeks/days, hours, minutes and seconds. // -// *** Warning: this package is the subject of many issues, so a replacement is under -// development. Please see https://github.com/rickb777/period. -// // Because of the vagaries of calendar systems, the meaning of year lengths, month lengths // and even day lengths depends on context. So a period is not necessarily a fixed duration // of time in terms of seconds. @@ -43,4 +40,5 @@ // * "P2.5Y" is 2.5 years. // // * "PT12M7.5S" is 12 minutes and 7.5 seconds. +// package period diff --git a/vendor/github.com/rickb777/date/period/flag.go b/vendor/github.com/rickb777/date/period/flag.go deleted file mode 100644 index 9488efa7ca8d..000000000000 --- a/vendor/github.com/rickb777/date/period/flag.go +++ /dev/null @@ -1,16 +0,0 @@ -package period - -// Set enables use of Period by the flag API. -func (period *Period) Set(p string) error { - p2, err := Parse(p) - if err != nil { - return err - } - *period = p2 - return nil -} - -// Type is for compatibility with the spf13/pflag library. -func (period Period) Type() string { - return "period" -} diff --git a/vendor/github.com/rickb777/date/period/format.go b/vendor/github.com/rickb777/date/period/format.go index 3b095292674e..32cb6a8311f7 100644 --- a/vendor/github.com/rickb777/date/period/format.go +++ b/vendor/github.com/rickb777/date/period/format.go @@ -5,32 +5,25 @@ package period import ( + "bytes" "fmt" - "io" "strings" "github.com/rickb777/plural" ) // Format converts the period to human-readable form using the default localisation. -// Multiples of 7 days are shown as weeks. func (period Period) Format() string { return period.FormatWithPeriodNames(PeriodYearNames, PeriodMonthNames, PeriodWeekNames, PeriodDayNames, PeriodHourNames, PeriodMinuteNames, PeriodSecondNames) } -// FormatWithoutWeeks converts the period to human-readable form using the default localisation. -// Multiples of 7 days are not shown as weeks. -func (period Period) FormatWithoutWeeks() string { - return period.FormatWithPeriodNames(PeriodYearNames, PeriodMonthNames, plural.Plurals{}, PeriodDayNames, PeriodHourNames, PeriodMinuteNames, PeriodSecondNames) -} - // FormatWithPeriodNames converts the period to human-readable form in a localisable way. func (period Period) FormatWithPeriodNames(yearNames, monthNames, weekNames, dayNames, hourNames, minNames, secNames plural.Plurals) string { period = period.Abs() parts := make([]string, 0) - parts = appendNonBlank(parts, yearNames.FormatFloat(float10(period.years))) - parts = appendNonBlank(parts, monthNames.FormatFloat(float10(period.months))) + parts = appendNonBlank(parts, yearNames.FormatFloat(absFloat10(period.years))) + parts = appendNonBlank(parts, monthNames.FormatFloat(absFloat10(period.months))) if period.days > 0 || (period.IsZero()) { if len(weekNames) > 0 { @@ -41,15 +34,15 @@ func (period Period) FormatWithPeriodNames(yearNames, monthNames, weekNames, day parts = appendNonBlank(parts, weekNames.FormatInt(int(weeks))) } if mdays > 0 || weeks == 0 { - parts = appendNonBlank(parts, dayNames.FormatFloat(float10(mdays))) + parts = appendNonBlank(parts, dayNames.FormatFloat(absFloat10(mdays))) } } else { - parts = appendNonBlank(parts, dayNames.FormatFloat(float10(period.days))) + parts = appendNonBlank(parts, dayNames.FormatFloat(absFloat10(period.days))) } } - parts = appendNonBlank(parts, hourNames.FormatFloat(float10(period.hours))) - parts = appendNonBlank(parts, minNames.FormatFloat(float10(period.minutes))) - parts = appendNonBlank(parts, secNames.FormatFloat(float10(period.seconds))) + parts = appendNonBlank(parts, hourNames.FormatFloat(absFloat10(period.hours))) + parts = appendNonBlank(parts, minNames.FormatFloat(absFloat10(period.minutes))) + parts = appendNonBlank(parts, secNames.FormatFloat(absFloat10(period.seconds))) return strings.Join(parts, ", ") } @@ -86,54 +79,50 @@ var PeriodSecondNames = plural.FromZero("", "%v second", "%v seconds") // String converts the period to ISO-8601 form. func (period Period) String() string { - return period.toPeriod64("").String() -} - -func (p64 period64) String() string { - if p64 == (period64{}) { + if period.IsZero() { return "P0D" } - buf := &strings.Builder{} - if p64.neg { + buf := &bytes.Buffer{} + if period.Sign() < 0 { buf.WriteByte('-') } buf.WriteByte('P') - writeField64(buf, p64.years, byte(Year)) - writeField64(buf, p64.months, byte(Month)) - - if p64.days != 0 { - if p64.days%70 == 0 { - writeField64(buf, p64.days/7, byte(Week)) + if period.years != 0 { + fmt.Fprintf(buf, "%gY", absFloat10(period.years)) + } + if period.months != 0 { + fmt.Fprintf(buf, "%gM", absFloat10(period.months)) + } + if period.days != 0 { + if period.days%70 == 0 { + fmt.Fprintf(buf, "%gW", absFloat10(period.days/7)) } else { - writeField64(buf, p64.days, byte(Day)) + fmt.Fprintf(buf, "%gD", absFloat10(period.days)) } } - - if p64.hours != 0 || p64.minutes != 0 || p64.seconds != 0 { + if period.hours != 0 || period.minutes != 0 || period.seconds != 0 { buf.WriteByte('T') } - - writeField64(buf, p64.hours, byte(Hour)) - writeField64(buf, p64.minutes, byte(Minute)) - writeField64(buf, p64.seconds, byte(Second)) + if period.hours != 0 { + fmt.Fprintf(buf, "%gH", absFloat10(period.hours)) + } + if period.minutes != 0 { + fmt.Fprintf(buf, "%gM", absFloat10(period.minutes)) + } + if period.seconds != 0 { + fmt.Fprintf(buf, "%gS", absFloat10(period.seconds)) + } return buf.String() } -func writeField64(w io.Writer, field int64, designator byte) { - if field != 0 { - if field%10 != 0 { - fmt.Fprintf(w, "%g", float32(field)/10) - } else { - fmt.Fprintf(w, "%d", field/10) - } - w.(io.ByteWriter).WriteByte(designator) +func absFloat10(v int16) float32 { + f := float32(v) / 10 + if v < 0 { + return -f } -} - -func float10(v int16) float32 { - return float32(v) / 10 + return f } diff --git a/vendor/github.com/rickb777/date/period/marshal.go b/vendor/github.com/rickb777/date/period/marshal.go index 6e1f2f1ce99b..c87ad5f6fb90 100644 --- a/vendor/github.com/rickb777/date/period/marshal.go +++ b/vendor/github.com/rickb777/date/period/marshal.go @@ -12,21 +12,19 @@ func (period Period) MarshalBinary() ([]byte, error) { } // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. -// This also provides support for gob decoding. +// This also provides support for gob encoding. func (period *Period) UnmarshalBinary(data []byte) error { return period.UnmarshalText(data) } // MarshalText implements the encoding.TextMarshaler interface for Periods. -// This also provides support for JSON encoding. func (period Period) MarshalText() ([]byte, error) { return []byte(period.String()), nil } // UnmarshalText implements the encoding.TextUnmarshaler interface for Periods. -// This also provides support for JSON decoding. func (period *Period) UnmarshalText(data []byte) (err error) { - u, err := Parse(string(data), false) + u, err := Parse(string(data)) if err == nil { *period = u } diff --git a/vendor/github.com/rickb777/date/period/parse.go b/vendor/github.com/rickb777/date/period/parse.go index 304bc5017227..270ae8d092df 100644 --- a/vendor/github.com/rickb777/date/period/parse.go +++ b/vendor/github.com/rickb777/date/period/parse.go @@ -12,10 +12,8 @@ import ( // MustParse is as per Parse except that it panics if the string cannot be parsed. // This is intended for setup code; don't use it for user inputs. -// By default, the value is normalised. -// Normalisation can be disabled using the optional flag. -func MustParse(value string, normalise ...bool) Period { - d, err := Parse(value, normalise...) +func MustParse(value string) Period { + d, err := Parse(value) if err != nil { panic(err) } @@ -26,27 +24,16 @@ func MustParse(value string, normalise ...bool) Period { // // In addition, a plus or minus sign can precede the period, e.g. "-P10D" // -// By default, the value is normalised, e.g. multiple of 12 months become years -// so "P24M" is the same as "P2Y". However, this is done without loss of precision, -// so for example whole numbers of days do not contribute to the months tally +// The value is normalised, e.g. multiple of 12 months become years so "P24M" +// is the same as "P2Y". However, this is done without loss of precision, so +// for example whole numbers of days do not contribute to the months tally // because the number of days per month is variable. // -// Normalisation can be disabled using the optional flag. -// // The zero value can be represented in several ways: all of the following // are equivalent: "P0Y", "P0M", "P0W", "P0D", "PT0H", PT0M", PT0S", and "P0". // The canonical zero is "P0D". -func Parse(period string, normalise ...bool) (Period, error) { - return ParseWithNormalise(period, len(normalise) == 0 || normalise[0]) -} - -// ParseWithNormalise parses strings that specify periods using ISO-8601 rules -// with an option to specify whether to normalise parsed period components. -// -// This method is deprecated and should not be used. It may be removed in a -// future version. -func ParseWithNormalise(period string, normalise bool) (Period, error) { - if period == "" || period == "-" || period == "+" { +func Parse(period string) (Period, error) { + if period == "" { return Period{}, fmt.Errorf("cannot parse a blank string as a period") } @@ -54,184 +41,118 @@ func ParseWithNormalise(period string, normalise bool) (Period, error) { return Period{}, nil } - p64, err := parse(period, normalise) - if err != nil { - return Period{}, err - } - return p64.toPeriod() -} - -func parse(period string, normalise bool) (*period64, error) { - neg := false - remaining := period - if remaining[0] == '-' { - neg = true - remaining = remaining[1:] - } else if remaining[0] == '+' { - remaining = remaining[1:] + result := period64{} + pcopy := period + if pcopy[0] == '-' { + result.neg = true + pcopy = pcopy[1:] + } else if pcopy[0] == '+' { + pcopy = pcopy[1:] } - if remaining[0] != 'P' { - return nil, fmt.Errorf("%s: expected 'P' period mark at the start", period) + if pcopy[0] != 'P' { + return Period{}, fmt.Errorf("expected 'P' period mark at the start: %s", period) } - remaining = remaining[1:] - - var number, weekValue, prevFraction int64 - result := &period64{input: period, neg: neg} - var years, months, weeks, days, hours, minutes, seconds itemState - var designator, prevDesignator byte - var err error - nComponents := 0 + pcopy = pcopy[1:] - years, months, weeks, days = Armed, Armed, Armed, Armed + st := parseState{period, pcopy, false, nil} + t := strings.IndexByte(pcopy, 'T') + if t >= 0 { + st.pcopy = pcopy[t+1:] - isHMS := false - for len(remaining) > 0 { - if remaining[0] == 'T' { - if isHMS { - return nil, fmt.Errorf("%s: 'T' designator cannot occur more than once", period) - } - isHMS = true + result.hours, st = parseField(st, 'H') + if st.err != nil { + return Period{}, fmt.Errorf("expected a number before the 'H' marker: %s", period) + } - years, months, weeks, days = Unready, Unready, Unready, Unready - hours, minutes, seconds = Armed, Armed, Armed + result.minutes, st = parseField(st, 'M') + if st.err != nil { + return Period{}, fmt.Errorf("expected a number before the 'M' marker: %s", period) + } - remaining = remaining[1:] + result.seconds, st = parseField(st, 'S') + if st.err != nil { + return Period{}, fmt.Errorf("expected a number before the 'S' marker: %s", period) + } - } else { - number, designator, remaining, err = parseNextField(remaining, period) - if err != nil { - return nil, err - } - - fraction := number % 10 - if prevFraction != 0 && fraction != 0 { - return nil, fmt.Errorf("%s: '%c' & '%c' only the last field can have a fraction", period, prevDesignator, designator) - } - - switch designator { - case 'Y': - years, err = years.testAndSet(number, 'Y', result, &result.years) - case 'W': - weeks, err = weeks.testAndSet(number, 'W', result, &weekValue) - case 'D': - days, err = days.testAndSet(number, 'D', result, &result.days) - case 'H': - hours, err = hours.testAndSet(number, 'H', result, &result.hours) - case 'S': - seconds, err = seconds.testAndSet(number, 'S', result, &result.seconds) - case 'M': - if isHMS { - minutes, err = minutes.testAndSet(number, 'M', result, &result.minutes) - } else { - months, err = months.testAndSet(number, 'M', result, &result.months) - } - default: - return nil, fmt.Errorf("%s: expected a number not '%c'", period, designator) - } - nComponents++ - - if err != nil { - return nil, err - } - - prevFraction = fraction - prevDesignator = designator + if len(st.pcopy) != 0 { + return Period{}, fmt.Errorf("unexpected remaining components %s: %s", st.pcopy, period) } - } - if nComponents == 0 { - return nil, fmt.Errorf("%s: expected 'Y', 'M', 'W', 'D', 'H', 'M', or 'S' designator", period) + st.pcopy = pcopy[:t] } - result.days += weekValue * 7 - - if normalise { - result = result.normalise64(true) + result.years, st = parseField(st, 'Y') + if st.err != nil { + return Period{}, fmt.Errorf("expected a number before the 'Y' marker: %s", period) + } + result.months, st = parseField(st, 'M') + if st.err != nil { + return Period{}, fmt.Errorf("expected a number before the 'M' marker: %s", period) + } + weeks, st := parseField(st, 'W') + if st.err != nil { + return Period{}, fmt.Errorf("expected a number before the 'W' marker: %s", period) } - return result, nil -} - -//------------------------------------------------------------------------------------------------- + days, st := parseField(st, 'D') + if st.err != nil { + return Period{}, fmt.Errorf("expected a number before the 'D' marker: %s", period) + } -type itemState int + if len(st.pcopy) != 0 { + return Period{}, fmt.Errorf("unexpected remaining components %s: %s", st.pcopy, period) + } -const ( - Unready itemState = iota - Armed - Set -) + result.days = weeks*7 + days + //fmt.Printf("%#v\n", st) -func (i itemState) testAndSet(number int64, designator byte, result *period64, value *int64) (itemState, error) { - switch i { - case Unready: - return i, fmt.Errorf("%s: '%c' designator cannot occur here", result.input, designator) - case Set: - return i, fmt.Errorf("%s: '%c' designator cannot occur more than once", result.input, designator) + if !st.ok { + return Period{}, fmt.Errorf("expected 'Y', 'M', 'W', 'D', 'H', 'M', or 'S' marker: %s", period) } - *value = number - return Set, nil + return result.normalise64(true).toPeriod(), nil } -//------------------------------------------------------------------------------------------------- +type parseState struct { + period, pcopy string + ok bool + err error +} -func parseNextField(str, original string) (int64, byte, string, error) { - i := scanDigits(str) - if i < 0 { - return 0, 0, "", fmt.Errorf("%s: missing designator at the end", original) +func parseField(st parseState, mark byte) (int64, parseState) { + //fmt.Printf("%c %#v\n", mark, st) + r := int64(0) + m := strings.IndexByte(st.pcopy, mark) + if m > 0 { + r, st.err = parseDecimalFixedPoint(st.pcopy[:m], st.period) + if st.err != nil { + return 0, st + } + st.pcopy = st.pcopy[m+1:] + st.ok = true } - - des := str[i] - number, err := parseDecimalNumber(str[:i], original, des) - return number, des, str[i+1:], err + return r, st } -// Fixed-point one decimal place -func parseDecimalNumber(number, original string, des byte) (int64, error) { - dec := strings.IndexByte(number, '.') +// Fixed-point three decimal places +func parseDecimalFixedPoint(s, original string) (int64, error) { + //was := s + dec := strings.IndexByte(s, '.') if dec < 0 { - dec = strings.IndexByte(number, ',') + dec = strings.IndexByte(s, ',') } - var integer, fraction int64 - var err error if dec >= 0 { - integer, err = strconv.ParseInt(number[:dec], 10, 64) - if err == nil { - number = number[dec+1:] - switch len(number) { - case 0: // skip - case 1: - fraction, err = strconv.ParseInt(number, 10, 64) - default: - fraction, err = strconv.ParseInt(number[:1], 10, 64) - } + dp := len(s) - dec + if dp > 1 { + s = s[:dec] + s[dec+1:dec+2] + } else { + s = s[:dec] + s[dec+1:] + "0" } } else { - integer, err = strconv.ParseInt(number, 10, 64) + s = s + "0" } - if err != nil { - return 0, fmt.Errorf("%s: expected a number but found '%c'", original, des) - } - - return integer*10 + fraction, err -} - -// scanDigits finds the first non-digit byte after a given starting point. -// Note that it does not care about runes or UTF-8 encoding; it assumes that -// a period string is always valid ASCII as well as UTF-8. -func scanDigits(s string) int { - for i, c := range s { - if !isDigit(c) { - return i - } - } - return -1 -} - -func isDigit(c rune) bool { - return ('0' <= c && c <= '9') || c == '.' || c == ',' + return strconv.ParseInt(s, 10, 64) } diff --git a/vendor/github.com/rickb777/date/period/period.go b/vendor/github.com/rickb777/date/period/period.go index 7eb2902a0f6f..a9b39c6a0d6b 100644 --- a/vendor/github.com/rickb777/date/period/period.go +++ b/vendor/github.com/rickb777/date/period/period.go @@ -9,14 +9,14 @@ import ( "time" ) -const daysPerYearE4 = 3652425 // 365.2425 days by the Gregorian rule -const daysPerMonthE4 = 304369 // 30.4369 days per month -const daysPerMonthE6 = 30436875 // 30.436875 days per month +const daysPerYearE4 int64 = 3652425 // 365.2425 days by the Gregorian rule +const daysPerMonthE4 int64 = 304369 // 30.4369 days per month +const daysPerMonthE6 int64 = 30436875 // 30.436875 days per month -const oneE4 = 10000 -const oneE5 = 100000 -const oneE6 = 1000000 -const oneE7 = 10000000 +const oneE4 int64 = 10000 +const oneE5 int64 = 100000 +const oneE6 int64 = 1000000 +const oneE7 int64 = 10000000 const hundredMs = 100 * time.Millisecond @@ -42,6 +42,7 @@ const hundredMs = 100 * time.Millisecond // // Note that although fractional weeks can be parsed, they will never be returned via String(). // This is because the number of weeks is always inferred from the number of days. +// type Period struct { years, months, days, hours, minutes, seconds int16 } @@ -51,8 +52,6 @@ type Period struct { // need to. // // All the parameters must have the same sign (otherwise a panic occurs). -// Because this implementation uses int16 internally, the paramters must -// be within the range ± 2^16 / 10. func NewYMD(years, months, days int) Period { return New(years, months, days, 0, 0, 0) } @@ -62,8 +61,6 @@ func NewYMD(years, months, days int) Period { // if you need to. // // All the parameters must have the same sign (otherwise a panic occurs). -// Because this implementation uses int16 internally, the paramters must -// be within the range ± 2^16 / 10. func NewHMS(hours, minutes, seconds int) Period { return New(0, 0, 0, hours, minutes, seconds) } @@ -85,6 +82,8 @@ func New(years, months, days, hours, minutes, seconds int) Period { years, months, days, hours, minutes, seconds)) } +// TODO NewFloat + // NewOf converts a time duration to a Period, and also indicates whether the conversion is precise. // Any time duration that spans more than ± 3276 hours will be approximated by assuming that there // are 24 hours per day, 365.2425 days per year (as per Gregorian calendar rules), and a month @@ -143,15 +142,15 @@ func NewOf(duration time.Duration) (p Period, precise bool) { // computations applied to the period can only be precise if they concern either the date (year, month, // day) part, or the clock (hour, minute, second) part, but not both. func Between(t1, t2 time.Time) (p Period) { + if t1.Location() != t2.Location() { + t2 = t2.In(t1.Location()) + } + sign := 1 if t2.Before(t1) { t1, t2, sign = t2, t1, -1 } - if t1.Location() != t2.Location() { - t2 = t2.In(t1.Location()) - } - year, month, day, hour, min, sec, hundredth := daysDiff(t1, t2) if sign < 0 { @@ -172,9 +171,9 @@ func daysDiff(t1, t2 time.Time) (year, month, day, hour, min, sec, hundredth int day = int(duration / (24 * time.Hour)) - hour = hh2 - hh1 - min = mm2 - mm1 - sec = ss2 - ss1 + hour = int(hh2 - hh1) + min = int(mm2 - mm1) + sec = int(ss2 - ss1) hundredth = (t2.Nanosecond() - t1.Nanosecond()) / 100000000 // Normalize negative values @@ -249,22 +248,15 @@ func (period Period) OnlyHMS() Period { // Abs converts a negative period to a positive one. func (period Period) Abs() Period { - a, _ := period.absNeg() - return a + return Period{absInt16(period.years), absInt16(period.months), absInt16(period.days), + absInt16(period.hours), absInt16(period.minutes), absInt16(period.seconds)} } -func (period Period) absNeg() (Period, bool) { - if period.IsNegative() { - return period.Negate(), true - } - return period, false -} - -func (period Period) condNegate(neg bool) Period { - if neg { - return period.Negate() +func absInt16(v int16) int16 { + if v < 0 { + return -v } - return period + return v } // Negate changes the sign of the period. @@ -272,11 +264,45 @@ func (period Period) Negate() Period { return Period{-period.years, -period.months, -period.days, -period.hours, -period.minutes, -period.seconds} } -func absInt16(v int16) int16 { - if v < 0 { - return -v +// Add adds two periods together. Use this method along with Negate in order to subtract periods. +// +// The result is not normalised and may overflow arithmetically (to make this unlikely, use Normalise on +// the inputs before adding them). +func (period Period) Add(that Period) Period { + return Period{ + period.years + that.years, + period.months + that.months, + period.days + that.days, + period.hours + that.hours, + period.minutes + that.minutes, + period.seconds + that.seconds, } - return v +} + +// Scale a period by a multiplication factor. Obviously, this can both enlarge and shrink it, +// and change the sign if negative. The result is normalised. +// +// Bear in mind that the internal representation is limited by fixed-point arithmetic with one +// decimal place; each field is only int16. +// +// Known issue: scaling by a large reduction factor (i.e. much less than one) doesn't work properly. +func (period Period) Scale(factor float32) Period { + + if -0.5 < factor && factor < 0.5 { + d, pr1 := period.Duration() + mul := float64(d) * float64(factor) + p2, pr2 := NewOf(time.Duration(mul)) + return p2.Normalise(pr1 && pr2) + } + + y := int64(float32(period.years) * factor) + m := int64(float32(period.months) * factor) + d := int64(float32(period.days) * factor) + hh := int64(float32(period.hours) * factor) + mm := int64(float32(period.minutes) * factor) + ss := int64(float32(period.seconds) * factor) + + return (&period64{y, m, d, hh, mm, ss, false}).normalise64(true).toPeriod() } // Years gets the whole number of years in the period. @@ -396,7 +422,29 @@ func (period Period) SecondsFloat() float32 { return float32(period.seconds) / 10 } -//------------------------------------------------------------------------------------------------- +// AddTo adds the period to a time, returning the result. +// A flag is also returned that is true when the conversion was precise and false otherwise. +// +// When the period specifies hours, minutes and seconds only, the result is precise. +// Also, when the period specifies whole years, months and days (i.e. without fractions), the +// result is precise. However, when years, months or days contains fractions, the result +// is only an approximation (it assumes that all days are 24 hours and every year is 365.2425 +// days, as per Gregorian calendar rules). +func (period Period) AddTo(t time.Time) (time.Time, bool) { + wholeYears := (period.years % 10) == 0 + wholeMonths := (period.months % 10) == 0 + wholeDays := (period.days % 10) == 0 + + if wholeYears && wholeMonths && wholeDays { + // in this case, time.AddDate provides an exact solution + stE3 := totalSecondsE3(period) + t1 := t.AddDate(int(period.years/10), int(period.months/10), int(period.days/10)) + return t1.Add(stE3 * time.Millisecond), true + } + + d, precise := period.Duration() + return t.Add(d), precise +} // DurationApprox converts a period to the equivalent duration in nanoseconds. // When the period specifies hours, minutes and seconds only, the result is precise. @@ -466,8 +514,7 @@ func (period Period) TotalMonthsApprox() int { // // Because the number of hours per day is imprecise (due to daylight savings etc), and because // the number of days per month is variable in the Gregorian calendar, there is a reluctance -// to transfer time to or from the days element, or to transfer days to or from the months -// element. To give control over this, there are two modes. +// to transfer time too or from the days element. To give control over this, there are two modes. // // In precise mode: // Multiples of 60 seconds become minutes. @@ -480,138 +527,220 @@ func (period Period) TotalMonthsApprox() int { // // Note that leap seconds are disregarded: every minute is assumed to have 60 seconds. func (period Period) Normalise(precise bool) Period { - n, _ := period.toPeriod64("").normalise64(precise).toPeriod() - return n + const limit = 32670 - (32670 / 60) + + // can we use a quicker algorithm for HHMMSS with int16 arithmetic? + if period.years == 0 && period.months == 0 && + (!precise || period.days == 0) && + period.hours > -limit && period.hours < limit { + + return period.normaliseHHMMSS(precise) + } + + // can we use a quicker algorithm for YYMM with int16 arithmetic? + if (period.years != 0 || period.months != 0) && //period.months%10 == 0 && + period.days == 0 && period.hours == 0 && period.minutes == 0 && period.seconds == 0 { + + return period.normaliseYYMM() + } + + // do things the no-nonsense way using int64 arithmetic + return period.toPeriod64().normalise64(precise).toPeriod() } -// Simplify applies some heuristic simplifications with the objective of reducing the number -// of non-zero fields and thus making the rendered form simpler. It should be applied to -// a normalised period, otherwise the results may be unpredictable. -// -// Note that months and days are never combined, due to the variability of month lengths. -// Days and hours are only combined when imprecise behaviour is selected; this is due to -// daylight savings transitions, during which there are more than or fewer than 24 hours -// per day. -// -// The following transformation rules are applied in order: -// -// * P1YnM becomes 12+n months for 0 < n <= 6 -// * P1DTnH becomes 24+n hours for 0 < n <= 6 (unless precise is true) -// * PT1HnM becomes 60+n minutes for 0 < n <= 10 -// * PT1MnS becomes 60+n seconds for 0 < n <= 10 -// -// At each step, if a fraction exists and would affect the calculation, the transformations -// stop. Also, when not precise, -// -// * for periods of at least ten years, month proper fractions are discarded -// * for periods of at least a year, day proper fractions are discarded -// * for periods of at least a month, hour proper fractions are discarded -// * for periods of at least a day, minute proper fractions are discarded -// * for periods of at least an hour, second proper fractions are discarded -// -// The thresholds can be set using the varargs th parameter. By default, the thresholds a, -// b, c, d are 6 months, 6 hours, 10 minutes, 10 seconds respectively as listed in the rules -// above. -// -// * No thresholds is equivalent to 6, 6, 10, 10. -// * A single threshold a is equivalent to a, a, a, a. -// * Two thresholds a, b are equivalent to a, a, b, b. -// * Three thresholds a, b, c are equivalent to a, b, c, c. -// * Four thresholds a, b, c, d are used as provided. -func (period Period) Simplify(precise bool, th ...int) Period { - switch len(th) { - case 0: - return period.doSimplify(precise, 60, 60, 100, 100) - case 1: - return period.doSimplify(precise, int16(th[0]*10), int16(th[0]*10), int16(th[0]*10), int16(th[0]*10)) - case 2: - return period.doSimplify(precise, int16(th[0]*10), int16(th[0]*10), int16(th[1]*10), int16(th[1]*10)) - case 3: - return period.doSimplify(precise, int16(th[0]*10), int16(th[1]*10), int16(th[2]*10), int16(th[2]*10)) - default: - return period.doSimplify(precise, int16(th[0]*10), int16(th[1]*10), int16(th[2]*10), int16(th[3]*10)) - } -} - -func (period Period) doSimplify(precise bool, a, b, c, d int16) Period { - if period.years%10 != 0 { - return period - } - - ap, neg := period.absNeg() - - // single year is dropped if there are some months - if ap.years == 10 && - 0 < ap.months && ap.months <= a && - ap.days == 0 { - ap.months += 120 - ap.years = 0 - } - - if ap.months%10 != 0 { - // month fraction is dropped for periods of at least ten years (1:120) - months := ap.months / 10 - if !precise && ap.years >= 100 && months == 0 { - ap.months = 0 - } - return ap.condNegate(neg) +func (period Period) normaliseHHMMSS(precise bool) Period { + s := period.Sign() + ap := period.Abs() + + // remember that the fields are all fixed-point 1E1 + ap.minutes += (ap.seconds / 600) * 10 + ap.seconds = ap.seconds % 600 + + ap.hours += (ap.minutes / 600) * 10 + ap.minutes = ap.minutes % 600 + + // up to 36 hours stays as hours + if !precise && ap.hours > 360 { + ap.days += (ap.hours / 240) * 10 + ap.hours = ap.hours % 240 } - if ap.days%10 != 0 { - // day fraction is dropped for periods of at least a year (1:365) - days := ap.days / 10 - if !precise && (ap.years > 0 || ap.months >= 120) && days == 0 { - ap.days = 0 - } - return ap.condNegate(neg) + d10 := ap.days % 10 + if d10 != 0 && (ap.hours != 0 || ap.minutes != 0 || ap.seconds != 0) { + ap.hours += d10 * 24 + ap.days -= d10 } - if !precise && ap.days == 10 && - ap.years == 0 && - ap.months == 0 && - 0 < ap.hours && ap.hours <= b { - ap.hours += 240 - ap.days = 0 + hh10 := ap.hours % 10 + if hh10 != 0 { + ap.minutes += hh10 * 60 + ap.hours -= hh10 } - if ap.hours%10 != 0 { - // hour fraction is dropped for periods of at least a month (1:720) - hours := ap.hours / 10 - if !precise && (ap.years > 0 || ap.months > 0 || ap.days >= 300) && hours == 0 { - ap.hours = 0 - } - return ap.condNegate(neg) + mm10 := ap.minutes % 10 + if mm10 != 0 { + ap.seconds += mm10 * 60 + ap.minutes -= mm10 + } + + if s < 0 { + return ap.Negate() + } + return ap +} + +func (period Period) normaliseYYMM() Period { + s := period.Sign() + ap := period.Abs() + + // remember that the fields are all fixed-point 1E1 + if ap.months > 129 { + ap.years += (ap.months / 120) * 10 + ap.months = ap.months % 120 } - if ap.hours == 10 && - 0 < ap.minutes && ap.minutes <= c { - ap.minutes += 600 - ap.hours = 0 + y10 := ap.years % 10 + if y10 != 0 && (ap.years < 10 || ap.months != 0) { + ap.months += y10 * 12 + ap.years -= y10 } - if ap.minutes%10 != 0 { - // minute fraction is dropped for periods of at least a day (1:1440) - minutes := ap.minutes / 10 - if !precise && (ap.years > 0 || ap.months > 0 || ap.days > 0 || ap.hours >= 240) && minutes == 0 { - ap.minutes = 0 + if s < 0 { + return ap.Negate() + } + return ap +} + +//------------------------------------------------------------------------------------------------- + +// used for stages in arithmetic +type period64 struct { + years, months, days, hours, minutes, seconds int64 + neg bool +} + +func (period Period) toPeriod64() *period64 { + return &period64{ + int64(period.years), int64(period.months), int64(period.days), + int64(period.hours), int64(period.minutes), int64(period.seconds), + false, + } +} + +func (p *period64) toPeriod() Period { + if p.neg { + return Period{ + int16(-p.years), int16(-p.months), int16(-p.days), + int16(-p.hours), int16(-p.minutes), int16(-p.seconds), } - return ap.condNegate(neg) } - if ap.minutes == 10 && - ap.hours == 0 && - 0 < ap.seconds && ap.seconds <= d { - ap.seconds += 600 - ap.minutes = 0 + return Period{ + int16(p.years), int16(p.months), int16(p.days), + int16(p.hours), int16(p.minutes), int16(p.seconds), } +} + +func (p *period64) normalise64(precise bool) *period64 { + return p.abs().rippleUp(precise).moveFractionToRight() +} + +func (p *period64) abs() *period64 { + + if !p.neg { + if p.years < 0 { + p.years = -p.years + p.neg = true + } + + if p.months < 0 { + p.months = -p.months + p.neg = true + } + + if p.days < 0 { + p.days = -p.days + p.neg = true + } - if ap.seconds%10 != 0 { - // second fraction is dropped for periods of at least an hour (1:3600) - seconds := ap.seconds / 10 - if !precise && (ap.years > 0 || ap.months > 0 || ap.days > 0 || ap.hours > 0 || ap.minutes >= 600) && seconds == 0 { - ap.seconds = 0 + if p.hours < 0 { + p.hours = -p.hours + p.neg = true } + + if p.minutes < 0 { + p.minutes = -p.minutes + p.neg = true + } + + if p.seconds < 0 { + p.seconds = -p.seconds + p.neg = true + } + } + return p +} + +func (p *period64) rippleUp(precise bool) *period64 { + // remember that the fields are all fixed-point 1E1 + + p.minutes = p.minutes + (p.seconds/600)*10 + p.seconds = p.seconds % 600 + + p.hours = p.hours + (p.minutes/600)*10 + p.minutes = p.minutes % 600 + + // 32670-(32670/60)-(32670/3600) = 32760 - 546 - 9.1 = 32204.9 + if !precise || p.hours > 32204 { + p.days += (p.hours / 240) * 10 + p.hours = p.hours % 240 + } + + if !precise || p.days > 32760 { + dE6 := p.days * oneE6 + p.months += dE6 / daysPerMonthE6 + p.days = (dE6 % daysPerMonthE6) / oneE6 + } + + p.years = p.years + (p.months/120)*10 + p.months = p.months % 120 + + return p +} + +// moveFractionToRight applies the rule that only the smallest field is permitted to have a decimal fraction. +func (p *period64) moveFractionToRight() *period64 { + // remember that the fields are all fixed-point 1E1 + + y10 := p.years % 10 + if y10 != 0 && (p.months != 0 || p.days != 0 || p.hours != 0 || p.minutes != 0 || p.seconds != 0) { + p.months += y10 * 12 + p.years = (p.years / 10) * 10 + } + + m10 := p.months % 10 + if m10 != 0 && (p.days != 0 || p.hours != 0 || p.minutes != 0 || p.seconds != 0) { + p.days += (m10 * daysPerMonthE6) / oneE6 + p.months = (p.months / 10) * 10 + } + + d10 := p.days % 10 + if d10 != 0 && (p.hours != 0 || p.minutes != 0 || p.seconds != 0) { + p.hours += d10 * 24 + p.days = (p.days / 10) * 10 + } + + hh10 := p.hours % 10 + if hh10 != 0 && (p.minutes != 0 || p.seconds != 0) { + p.minutes += hh10 * 60 + p.hours = (p.hours / 10) * 10 + } + + mm10 := p.minutes % 10 + if mm10 != 0 && p.seconds != 0 { + p.seconds += mm10 * 60 + p.minutes = (p.minutes / 10) * 10 } - return ap.condNegate(neg) + return p } diff --git a/vendor/github.com/rickb777/date/period/period64.go b/vendor/github.com/rickb777/date/period/period64.go deleted file mode 100644 index f3e2f4b0bce5..000000000000 --- a/vendor/github.com/rickb777/date/period/period64.go +++ /dev/null @@ -1,142 +0,0 @@ -package period - -import ( - "fmt" - "math" - "strings" -) - -// used for stages in arithmetic -type period64 struct { - // always positive values - years, months, days, hours, minutes, seconds int64 - // true if the period is negative - neg bool - input string -} - -func (period Period) toPeriod64(input string) *period64 { - if period.IsNegative() { - return &period64{ - years: int64(-period.years), months: int64(-period.months), days: int64(-period.days), - hours: int64(-period.hours), minutes: int64(-period.minutes), seconds: int64(-period.seconds), - neg: true, - input: input, - } - } - return &period64{ - years: int64(period.years), months: int64(period.months), days: int64(period.days), - hours: int64(period.hours), minutes: int64(period.minutes), seconds: int64(period.seconds), - input: input, - } -} - -func (p64 *period64) toPeriod() (Period, error) { - var f []string - if p64.years > math.MaxInt16 { - f = append(f, "years") - } - if p64.months > math.MaxInt16 { - f = append(f, "months") - } - if p64.days > math.MaxInt16 { - f = append(f, "days") - } - if p64.hours > math.MaxInt16 { - f = append(f, "hours") - } - if p64.minutes > math.MaxInt16 { - f = append(f, "minutes") - } - if p64.seconds > math.MaxInt16 { - f = append(f, "seconds") - } - - if len(f) > 0 { - if p64.input == "" { - p64.input = p64.String() - } - return Period{}, fmt.Errorf("%s: integer overflow occurred in %s", p64.input, strings.Join(f, ",")) - } - - if p64.neg { - return Period{ - int16(-p64.years), int16(-p64.months), int16(-p64.days), - int16(-p64.hours), int16(-p64.minutes), int16(-p64.seconds), - }, nil - } - - return Period{ - int16(p64.years), int16(p64.months), int16(p64.days), - int16(p64.hours), int16(p64.minutes), int16(p64.seconds), - }, nil -} - -func (p64 *period64) normalise64(precise bool) *period64 { - return p64.rippleUp(precise).moveFractionToRight() -} - -func (p64 *period64) rippleUp(precise bool) *period64 { - // remember that the fields are all fixed-point 1E1 - - p64.minutes += (p64.seconds / 600) * 10 - p64.seconds = p64.seconds % 600 - - p64.hours += (p64.minutes / 600) * 10 - p64.minutes = p64.minutes % 600 - - // 32670-(32670/60)-(32670/3600) = 32760 - 546 - 9.1 = 32204.9 - if !precise || p64.hours > 32204 { - p64.days += (p64.hours / 240) * 10 - p64.hours = p64.hours % 240 - } - - if !precise || p64.days > 32760 { - dE6 := p64.days * oneE5 - p64.months += (dE6 / daysPerMonthE6) * 10 - p64.days = (dE6 % daysPerMonthE6) / oneE5 - } - - p64.years += (p64.months / 120) * 10 - p64.months = p64.months % 120 - - return p64 -} - -// moveFractionToRight attempts to remove fractions in higher-order fields by moving their value to the -// next-lower-order field. For example, fractional years become months. -func (p64 *period64) moveFractionToRight() *period64 { - // remember that the fields are all fixed-point 1E1 - - y10 := p64.years % 10 - if y10 != 0 && (p64.months != 0 || p64.days != 0 || p64.hours != 0 || p64.minutes != 0 || p64.seconds != 0) { - p64.months += y10 * 12 - p64.years = (p64.years / 10) * 10 - } - - m10 := p64.months % 10 - if m10 != 0 && (p64.days != 0 || p64.hours != 0 || p64.minutes != 0 || p64.seconds != 0) { - p64.days += (m10 * daysPerMonthE6) / oneE6 - p64.months = (p64.months / 10) * 10 - } - - d10 := p64.days % 10 - if d10 != 0 && (p64.hours != 0 || p64.minutes != 0 || p64.seconds != 0) { - p64.hours += d10 * 24 - p64.days = (p64.days / 10) * 10 - } - - hh10 := p64.hours % 10 - if hh10 != 0 && (p64.minutes != 0 || p64.seconds != 0) { - p64.minutes += hh10 * 60 - p64.hours = (p64.hours / 10) * 10 - } - - mm10 := p64.minutes % 10 - if mm10 != 0 && p64.seconds != 0 { - p64.seconds += mm10 * 60 - p64.minutes = (p64.minutes / 10) * 10 - } - - return p64 -} diff --git a/vendor/github.com/rickb777/date/period/sql.go b/vendor/github.com/rickb777/date/period/sql.go deleted file mode 100644 index 31b546429aa3..000000000000 --- a/vendor/github.com/rickb777/date/period/sql.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2015 Rick Beton. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package period - -import ( - "database/sql/driver" - "fmt" -) - -// Scan parses some value, which can be either string or []byte. -// It implements sql.Scanner, https://golang.org/pkg/database/sql/#Scanner -func (period *Period) Scan(value interface{}) (err error) { - if value == nil { - return nil - } - - err = nil - switch v := value.(type) { - case []byte: - *period, err = Parse(string(v), false) - case string: - *period, err = Parse(v, false) - default: - err = fmt.Errorf("%T %+v is not a meaningful period", value, value) - } - - return err -} - -// Value converts the period to a string. It implements driver.Valuer, -// https://golang.org/pkg/database/sql/driver/#Valuer -func (period Period) Value() (driver.Value, error) { - return period.String(), nil -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 354c5ccb2256..30827ab7ac5f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1114,8 +1114,8 @@ github.com/mitchellh/reflectwalk # github.com/oklog/run v1.1.0 ## explicit; go 1.13 github.com/oklog/run -# github.com/rickb777/date v1.20.2 -## explicit; go 1.17 +# github.com/rickb777/date v1.12.5-0.20200422084442-6300e543c4d9 +## explicit; go 1.13 github.com/rickb777/date/period # github.com/rickb777/plural v1.4.1 ## explicit; go 1.17