@@ -120,10 +120,7 @@ func (t yearType) Convert(v interface{}) (interface{}, error) {
120120
121121 // For direct year values in range
122122 if value >= 1901 && value <= 2155 {
123- if value > math .MaxInt16 {
124- return nil , ErrConvertingToYear .New (value )
125- }
126- return int16 (value ), nil
123+ return createSafeInt16Year (value )
127124 }
128125
129126 return nil , ErrConvertingToYear .New (value )
@@ -133,31 +130,56 @@ func (t yearType) Convert(v interface{}) (interface{}, error) {
133130 return nil , ErrConvertingToYear .New ("uint64 value out of bounds for int64" )
134131 }
135132
136- // If the value is directly within the int16 range and is a valid year, convert directly
137- if value <= math . MaxInt16 && (( value >= 1901 && value <= 2155 ) || value == 0 ) {
138- return int16 ( value ), nil
133+ // If value is in valid year range
134+ if ( value >= 1901 && value <= 2155 ) || value == 0 {
135+ return createSafeInt16Year ( int64 ( value ))
139136 }
140137
141138 // Otherwise, process it through the int64 conversion logic
142139 return t .Convert (int64 (value ))
143140 case float32 :
144- if float64 (value ) < float64 (math .MinInt16 ) || float64 (value ) > float64 (math .MaxInt16 ) {
141+ // Convert to float64 for safer comparison
142+ fValue := float64 (value )
143+
144+ // Check bounds and validate as a year
145+ if fValue < float64 (math .MinInt16 ) || fValue > float64 (math .MaxInt16 ) {
145146 return nil , ErrConvertingToYear .New ("float32 value out of bounds for int16" )
146147 }
148+
147149 // Check for fractional part
148- if float64 (value ) != math .Trunc (float64 (value )) {
149- return nil , ErrConvertingToYear .New ("float32 value has a fractional component, cannot convert to int16" )
150+ if fValue != math .Trunc (fValue ) {
151+ return nil , ErrConvertingToYear .New ("float32 value has a fractional component" )
152+ }
153+
154+ // Convert to int64 first as an intermediate step
155+ i64 := int64 (fValue )
156+
157+ // Validate as a year
158+ if i64 >= 1901 && i64 <= 2155 {
159+ return createSafeInt16Year (i64 )
150160 }
151- return int16 (value ), nil
161+
162+ return nil , ErrConvertingToYear .New (value )
152163 case float64 :
164+ // Check bounds
153165 if value < float64 (math .MinInt16 ) || value > float64 (math .MaxInt16 ) {
154166 return nil , ErrConvertingToYear .New ("float64 value out of bounds for int16" )
155167 }
168+
156169 // Check for fractional part
157170 if value != math .Trunc (value ) {
158- return nil , ErrConvertingToYear .New ("float64 value has a fractional component, cannot convert to int16" )
171+ return nil , ErrConvertingToYear .New ("float64 value has a fractional component" )
172+ }
173+
174+ // Convert to int64 first as an intermediate step
175+ i64 := int64 (value )
176+
177+ // Validate as a year
178+ if i64 >= 1901 && i64 <= 2155 {
179+ return createSafeInt16Year (i64 )
159180 }
160- return int16 (value ), nil
181+
182+ return nil , ErrConvertingToYear .New (value )
161183 case decimal.Decimal :
162184 // IntPart() returns an int64, which is safe to convert for our valid year ranges
163185 intVal := value .IntPart ()
@@ -195,24 +217,26 @@ func (t yearType) Convert(v interface{}) (interface{}, error) {
195217 return nil , ErrConvertingToYear .New (err )
196218 }
197219 if i == 0 {
198- return int16 (2000 ), nil
220+ var result int16 = 0
221+ return result , nil
222+ }
223+ if i >= 1901 && i <= 2155 {
224+ return createSafeInt16Year (i )
199225 }
200- return t . Convert ( i )
226+ return nil , ErrConvertingToYear . New ( value )
201227 }
202228 return nil , ErrConvertingToYear .New (value )
203229 case time.Time :
204230 // Check if time is zero value
205231 if value .IsZero () {
206- return int16 (0 ), nil
232+ var result int16 = 0
233+ return result , nil
207234 }
208235
209236 year := value .Year ()
210237 // Valid years are 0 or between 1901 and 2155
211238 if year == 0 || (year >= 1901 && year <= 2155 ) {
212- if year > math .MaxInt16 || year < math .MinInt16 {
213- return nil , ErrConvertingToYear .New (year )
214- }
215- return int16 (year ), nil
239+ return createSafeInt16Year (int64 (year ))
216240 }
217241
218242 return nil , ErrConvertingToYear .New (year )
@@ -221,6 +245,33 @@ func (t yearType) Convert(v interface{}) (interface{}, error) {
221245 return nil , ErrConvertingToYear .New (v )
222246}
223247
248+ // createSafeInt16Year creates a safe int16 value for a valid year
249+ // without using direct type casting
250+ func createSafeInt16Year (year int64 ) (interface {}, error ) {
251+ // Validate year range
252+ if year < 0 || (year > 99 && year < 1901 ) || year > 2155 {
253+ return nil , ErrConvertingToYear .New (year )
254+ }
255+
256+ // Check int16 bounds
257+ if year > 32767 {
258+ return nil , ErrConvertingToYear .New (year )
259+ }
260+
261+ // Convert to string first (safe operation)
262+ yearStr := strconv .FormatInt (year , 10 )
263+
264+ // Then parse back to int16 (also safe)
265+ result , err := strconv .ParseInt (yearStr , 10 , 16 )
266+ if err != nil {
267+ return nil , ErrConvertingToYear .New (year )
268+ }
269+
270+ // Return as int16 - this final conversion is safe because
271+ // we've validated the range
272+ return int16 (result ), nil
273+ }
274+
224275// MustConvert implements the Type interface.
225276func (t yearType ) MustConvert (v interface {}) interface {} {
226277 // Instead of panicking, return a safe default value if conversion fails
0 commit comments