Skip to content

Commit a792460

Browse files
author
Rick
committed
Bugfix: this resolves issue #19 fraction designator parsing bug
1 parent fba60ed commit a792460

File tree

2 files changed

+19
-15
lines changed

2 files changed

+19
-15
lines changed

period/parse.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ func parse(period string, normalise bool) (*period64, error) {
7676
}
7777
remaining = remaining[1:]
7878

79-
var number, weekValue, prevFraction int64
79+
var integer, fraction, weekValue int64
8080
result := &period64{input: period, neg: neg}
8181
var years, months, weeks, days, hours, minutes, seconds itemState
82-
var designator, prevDesignator byte
82+
var designator, previousFractionDesignator byte
8383
var err error
8484
nComponents := 0
8585

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

101101
} else {
102-
number, designator, remaining, err = parseNextField(remaining, period)
102+
integer, fraction, designator, remaining, err = parseNextField(remaining, period)
103103
if err != nil {
104104
return nil, err
105105
}
106106

107-
fraction := number % 10
108-
if prevFraction != 0 && fraction != 0 {
109-
return nil, fmt.Errorf("%s: '%c' & '%c' only the last field can have a fraction", period, prevDesignator, designator)
107+
if previousFractionDesignator != 0 && fraction != 0 {
108+
return nil, fmt.Errorf("%s: '%c' & '%c' only the last field can have a fraction", period, previousFractionDesignator, designator)
110109
}
111110

111+
number := integer*10 + fraction
112+
112113
switch designator {
113114
case 'Y':
114115
years, err = years.testAndSet(number, 'Y', result, &result.years)
@@ -135,8 +136,9 @@ func parse(period string, normalise bool) (*period64, error) {
135136
return nil, err
136137
}
137138

138-
prevFraction = fraction
139-
prevDesignator = designator
139+
if fraction != 0 {
140+
previousFractionDesignator = designator
141+
}
140142
}
141143
}
142144

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

178180
//-------------------------------------------------------------------------------------------------
179181

180-
func parseNextField(str, original string) (int64, byte, string, error) {
182+
func parseNextField(str, original string) (int64, int64, byte, string, error) {
181183
i := scanDigits(str)
182184
if i < 0 {
183-
return 0, 0, "", fmt.Errorf("%s: missing designator at the end", original)
185+
return 0, 0, 0, "", fmt.Errorf("%s: missing designator at the end", original)
184186
}
185187

186188
des := str[i]
187-
number, err := parseDecimalNumber(str[:i], original, des)
188-
return number, des, str[i+1:], err
189+
integer, fraction, err := parseDecimalNumber(str[:i], original, des)
190+
return integer, fraction, des, str[i+1:], err
189191
}
190192

191193
// Fixed-point one decimal place
192-
func parseDecimalNumber(number, original string, des byte) (int64, error) {
194+
func parseDecimalNumber(number, original string, des byte) (int64, int64, error) {
193195
dec := strings.IndexByte(number, '.')
194196
if dec < 0 {
195197
dec = strings.IndexByte(number, ',')
@@ -214,10 +216,10 @@ func parseDecimalNumber(number, original string, des byte) (int64, error) {
214216
}
215217

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

220-
return integer*10 + fraction, err
222+
return integer, fraction, err
221223
}
222224

223225
// scanDigits finds the first non-digit byte after a given starting point.

period/period_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ func TestParseErrors(t *testing.T) {
4141
{"P1D2D", false, ": 'D' designator cannot occur more than once", "P1D2D"},
4242
{"PT1HT1S", false, ": 'T' designator cannot occur more than once", "PT1HT1S"},
4343
{"P0.1YT0.1S", false, ": 'Y' & 'S' only the last field can have a fraction", "P0.1YT0.1S"},
44+
{"P0.1Y1M1DT1H1M0.1S", false, ": 'Y' & 'S' only the last field can have a fraction", "P0.1Y1M1DT1H1M0.1S"},
4445
{"P", false, ": expected 'Y', 'M', 'W', 'D', 'H', 'M', or 'S' designator", "P"},
46+
4547
// integer overflow
4648
{"P32768Y", false, ": integer overflow occurred in years", "P32768Y"},
4749
{"P32768M", false, ": integer overflow occurred in months", "P32768M"},

0 commit comments

Comments
 (0)