@@ -10,6 +10,8 @@ import (
1010 "github.com/tarantool/go-tarantool/v3/test_helpers"
1111)
1212
13+ var _ fmt.Stringer = Interval {}
14+
1315func TestIntervalAdd (t * testing.T ) {
1416 orig := Interval {
1517 Year : 1 ,
@@ -133,3 +135,266 @@ func TestIntervalTarantoolEncoding(t *testing.T) {
133135 })
134136 }
135137}
138+
139+ func TestIntervalString (t * testing.T ) {
140+ tests := []struct {
141+ name string
142+ interval Interval
143+ expected string
144+ }{
145+ {
146+ name : "empty interval" ,
147+ interval : Interval {},
148+ expected : "0 seconds" ,
149+ },
150+ {
151+ name : "single positive year" ,
152+ interval : Interval {
153+ Year : 1 ,
154+ },
155+ expected : "+1 year" ,
156+ },
157+ {
158+ name : "single negative year" ,
159+ interval : Interval {
160+ Year : - 1 ,
161+ },
162+ expected : "-1 year" ,
163+ },
164+ {
165+ name : "multiple positive years" ,
166+ interval : Interval {
167+ Year : 5 ,
168+ },
169+ expected : "+5 years" ,
170+ },
171+ {
172+ name : "multiple positive components" ,
173+ interval : Interval {
174+ Year : 1 ,
175+ Month : 2 ,
176+ Day : 3 ,
177+ },
178+ expected : "+1 year, 2 months, 3 days" ,
179+ },
180+ {
181+ name : "positive components without sign after first" ,
182+ interval : Interval {
183+ Hour : 1 ,
184+ Min : 30 ,
185+ Sec : 45 ,
186+ },
187+ expected : "+1 hour, 30 minutes, 45 seconds" ,
188+ },
189+ {
190+ name : "mixed signs" ,
191+ interval : Interval {
192+ Year : - 1 ,
193+ Month : 2 ,
194+ Week : - 3 ,
195+ Day : 4 ,
196+ Hour : - 5 ,
197+ Min : 6 ,
198+ Sec : - 7 ,
199+ Nsec : 9 ,
200+ },
201+ expected : "-1 year, 2 months, -3 weeks, 4 days, -5 hours, 6 minutes," +
202+ " -7 seconds, 9 nanoseconds" ,
203+ },
204+ {
205+ name : "positive seconds with nanoseconds" ,
206+ interval : Interval {
207+ Sec : 5 ,
208+ Nsec : 123456789 ,
209+ },
210+ expected : "+5 seconds, 123456789 nanoseconds" ,
211+ },
212+ {
213+ name : "negative seconds with nanoseconds" ,
214+ interval : Interval {
215+ Sec : - 5 ,
216+ Nsec : - 123456789 ,
217+ },
218+ expected : "-5 seconds, -123456789 nanoseconds" ,
219+ },
220+ {
221+ name : "only positive nanoseconds" ,
222+ interval : Interval {
223+ Nsec : 500000000 ,
224+ },
225+ expected : "+500000000 nanoseconds" ,
226+ },
227+ {
228+ name : "only negative nanoseconds" ,
229+ interval : Interval {
230+ Nsec : - 500000000 ,
231+ },
232+ expected : "-500000000 nanoseconds" ,
233+ },
234+ {
235+ name : "complex interval" ,
236+ interval : Interval {
237+ Year : 1 ,
238+ Month : 6 ,
239+ Week : 2 ,
240+ Day : 3 ,
241+ Hour : 12 ,
242+ Min : 30 ,
243+ Sec : 45 ,
244+ Nsec : 123456789 ,
245+ },
246+ expected : "+1 year, 6 months, 2 weeks, 3 days, 12 hours, 30 minutes," +
247+ " 45 seconds, 123456789 nanoseconds" ,
248+ },
249+ {
250+ name : "all negative components" ,
251+ interval : Interval {
252+ Year : - 1 ,
253+ Day : - 2 ,
254+ Hour : - 3 ,
255+ },
256+ expected : "-1 year, -2 days, -3 hours" ,
257+ },
258+ }
259+
260+ for _ , tt := range tests {
261+ t .Run (tt .name , func (t * testing.T ) {
262+ result := tt .interval .String ()
263+ if result != tt .expected {
264+ t .Errorf ("Interval.String() = %v, want %v" , result , tt .expected )
265+ }
266+ })
267+ }
268+ }
269+ func TestIntervalString_WroksWithFmt (t * testing.T ) {
270+ ival := Interval {Hour : 2 , Min : 30 }
271+ result := ival .String ()
272+ expected := "+2 hours, 30 minutes"
273+ if result != expected {
274+ t .Errorf ("fmt.Sprintf('%%s') = %v, want %v" , result , expected )
275+ }
276+
277+ result = fmt .Sprintf ("%v" , ival )
278+ if result != expected {
279+ t .Errorf ("fmt.Sprintf('%%v') = %v, want %v" , result , expected )
280+ }
281+ }
282+
283+ func TestIntervalString_FromTarantool (t * testing.T ) {
284+ skipIfDatetimeUnsupported (t )
285+
286+ conn := test_helpers .ConnectWithValidation (t , dialer , opts )
287+ defer conn .Close ()
288+
289+ testCases := []struct {
290+ luaExpr string
291+ expected string
292+ }{
293+ {
294+ "return require('datetime').interval.new({})" ,
295+ "0 seconds" ,
296+ },
297+ {
298+ "return require('datetime').interval.new({year = 1})" ,
299+ "+1 year" ,
300+ },
301+ {
302+ "return require('datetime').interval.new({year = -1})" ,
303+ "-1 year" ,
304+ },
305+ {
306+ "return require('datetime').interval.new({year = 5})" ,
307+ "+5 years" ,
308+ },
309+ {
310+ "return require('datetime').interval.new({year = 1, month = 2, day = 3})" ,
311+ "+1 year, 2 months, 3 days" ,
312+ },
313+ {
314+ "return require('datetime').interval.new({hour = 1, min = 30, sec = 45})" ,
315+ "+1 hour, 30 minutes, 45 seconds" ,
316+ },
317+ {
318+ "return require('datetime').interval.new({year = -1, month = 2, week = -3, day = 4," +
319+ " hour = -5, min = 6, sec = -7, nsec = 9})" ,
320+ "-1 year, 2 months, -3 weeks, 4 days, -5 hours, 6 minutes, -7 seconds, 9 nanoseconds" ,
321+ },
322+ {
323+ "return require('datetime').interval.new({sec = 5, nsec = 123456789})" ,
324+ "+5 seconds, 123456789 nanoseconds" ,
325+ },
326+ {
327+ "return require('datetime').interval.new({sec = -5, nsec = -123456789})" ,
328+ "-5 seconds, -123456789 nanoseconds" ,
329+ },
330+ {
331+ "return require('datetime').interval.new({nsec = 500000000})" ,
332+ "+500000000 nanoseconds" ,
333+ },
334+ {
335+ "return require('datetime').interval.new({nsec = -500000000})" ,
336+ "-500000000 nanoseconds" ,
337+ },
338+ {
339+ "return require('datetime').interval.new({year = 1, month = 6, week = 2, day = 3," +
340+ " hour = 12, min = 30, sec = 45, nsec = 123456789})" ,
341+ "+1 year, 6 months, 2 weeks, 3 days, 12 hours, 30 minutes, 45 seconds," +
342+ " 123456789 nanoseconds" ,
343+ },
344+ {
345+ "return require('datetime').interval.new({year = -1, day = -2, hour = -3})" ,
346+ "-1 year, -2 days, -3 hours" ,
347+ },
348+ }
349+
350+ for _ , tc := range testCases {
351+ t .Run (tc .expected , func (t * testing.T ) {
352+ data , err := conn .Do (tarantool .NewEvalRequest (tc .luaExpr )).Get ()
353+ if err != nil {
354+ t .Fatalf ("Eval failed: %s" , err )
355+ }
356+ if len (data ) != 1 {
357+ t .Fatalf ("Expected 1 result, got %d" , len (data ))
358+ }
359+ ival , ok := data [0 ].(Interval )
360+ if ! ok {
361+ t .Fatalf ("Result is not Interval: %T" , data [0 ])
362+ }
363+ if got := ival .String (); got != tc .expected {
364+ t .Errorf ("String() = %q, want %q" , got , tc .expected )
365+ }
366+ })
367+ }
368+ }
369+
370+ func TestIntervalString_EdgeCases (t * testing.T ) {
371+ tests := []struct {
372+ name string
373+ interval Interval
374+ }{
375+ {
376+ name : "max values" ,
377+ interval : Interval {Year : 1 << 63 - 1 , Month : 1 << 63 - 1 },
378+ },
379+ {
380+ name : "min values" ,
381+ interval : Interval {Year : - 1 << 63 , Month : - 1 << 63 },
382+ },
383+ {
384+ name : "mixed signs complex" ,
385+ interval : Interval {Year : 1 , Month : - 1 , Day : 1 , Hour : - 1 },
386+ },
387+ }
388+
389+ for _ , tt := range tests {
390+ t .Run (tt .name , func (t * testing.T ) {
391+ result := tt .interval .String ()
392+ if result == "" {
393+ t .Error ("Interval.String() returned empty string" )
394+ }
395+ if len (result ) > 1000 {
396+ t .Error ("Interval.String() returned unexpectedly long string" )
397+ }
398+ })
399+ }
400+ }
0 commit comments