Skip to content

Commit

Permalink
Bugfix: this resolves issue #19 fraction designator parsing bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Rick committed Sep 19, 2023
1 parent fba60ed commit a792460
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 15 deletions.
32 changes: 17 additions & 15 deletions period/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ func parse(period string, normalise bool) (*period64, error) {
}
remaining = remaining[1:]

var number, weekValue, prevFraction int64
var integer, fraction, weekValue int64
result := &period64{input: period, neg: neg}
var years, months, weeks, days, hours, minutes, seconds itemState
var designator, prevDesignator byte
var designator, previousFractionDesignator byte
var err error
nComponents := 0

Expand All @@ -99,16 +99,17 @@ func parse(period string, normalise bool) (*period64, error) {
remaining = remaining[1:]

} else {
number, designator, remaining, err = parseNextField(remaining, period)
integer, fraction, 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)
if previousFractionDesignator != 0 && fraction != 0 {
return nil, fmt.Errorf("%s: '%c' & '%c' only the last field can have a fraction", period, previousFractionDesignator, designator)
}

number := integer*10 + fraction

switch designator {
case 'Y':
years, err = years.testAndSet(number, 'Y', result, &result.years)
Expand All @@ -135,8 +136,9 @@ func parse(period string, normalise bool) (*period64, error) {
return nil, err
}

prevFraction = fraction
prevDesignator = designator
if fraction != 0 {
previousFractionDesignator = designator
}
}
}

Expand Down Expand Up @@ -177,19 +179,19 @@ func (i itemState) testAndSet(number int64, designator byte, result *period64, v

//-------------------------------------------------------------------------------------------------

func parseNextField(str, original string) (int64, byte, string, error) {
func parseNextField(str, original string) (int64, int64, byte, string, error) {
i := scanDigits(str)
if i < 0 {
return 0, 0, "", fmt.Errorf("%s: missing designator at the end", original)
return 0, 0, 0, "", fmt.Errorf("%s: missing designator at the end", original)
}

des := str[i]
number, err := parseDecimalNumber(str[:i], original, des)
return number, des, str[i+1:], err
integer, fraction, err := parseDecimalNumber(str[:i], original, des)
return integer, fraction, des, str[i+1:], err
}

// Fixed-point one decimal place
func parseDecimalNumber(number, original string, des byte) (int64, error) {
func parseDecimalNumber(number, original string, des byte) (int64, int64, error) {
dec := strings.IndexByte(number, '.')
if dec < 0 {
dec = strings.IndexByte(number, ',')
Expand All @@ -214,10 +216,10 @@ func parseDecimalNumber(number, original string, des byte) (int64, error) {
}

if err != nil {
return 0, fmt.Errorf("%s: expected a number but found '%c'", original, des)
return 0, 0, fmt.Errorf("%s: expected a number but found '%c'", original, des)
}

return integer*10 + fraction, err
return integer, fraction, err
}

// scanDigits finds the first non-digit byte after a given starting point.
Expand Down
2 changes: 2 additions & 0 deletions period/period_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ func TestParseErrors(t *testing.T) {
{"P1D2D", false, ": 'D' designator cannot occur more than once", "P1D2D"},
{"PT1HT1S", false, ": 'T' designator cannot occur more than once", "PT1HT1S"},
{"P0.1YT0.1S", false, ": 'Y' & 'S' only the last field can have a fraction", "P0.1YT0.1S"},
{"P0.1Y1M1DT1H1M0.1S", false, ": 'Y' & 'S' only the last field can have a fraction", "P0.1Y1M1DT1H1M0.1S"},
{"P", false, ": expected 'Y', 'M', 'W', 'D', 'H', 'M', or 'S' designator", "P"},

// integer overflow
{"P32768Y", false, ": integer overflow occurred in years", "P32768Y"},
{"P32768M", false, ": integer overflow occurred in months", "P32768M"},
Expand Down

0 comments on commit a792460

Please sign in to comment.