github.com/viant/toolbox@v0.34.5/time_helper_test.go (about) 1 package toolbox 2 3 import ( 4 "github.com/stretchr/testify/assert" 5 "math" 6 "testing" 7 "time" 8 ) 9 10 func TestAtTime_Next(t *testing.T) { 11 12 timeLayout := "2006-01-02 15:04:05" 13 14 var useCases = []struct { 15 description string 16 at *AtTime 17 baseTime string 18 expectTime string 19 }{ 20 21 { 22 description: "evey 1/2 - next day", 23 at: &AtTime{ 24 WeekDay: "*", 25 Hour: "*", 26 Minute: "30", 27 }, 28 baseTime: "2019-01-01 23:33:01", 29 expectTime: "2019-01-02 01:30:00", 30 }, 31 32 { 33 description: "evey 1/2, last minute - next day", 34 at: &AtTime{ 35 WeekDay: "*", 36 Hour: "*", 37 Minute: "0,30", 38 }, 39 baseTime: "2019-01-01 23:59:00", 40 expectTime: "2019-01-02 01:00:00", 41 }, 42 43 { 44 description: "evey 1/2, last day of the month - next day", 45 at: &AtTime{ 46 WeekDay: "*", 47 Hour: "*", 48 Minute: "0,30", 49 }, 50 baseTime: "2019-05-31 23:59:00", 51 expectTime: "2019-06-01 01:00:00", 52 }, 53 54 { 55 description: "evey hour - next day", 56 at: &AtTime{ 57 WeekDay: "*", 58 Hour: "0", 59 Minute: "*", 60 }, 61 baseTime: "2019-01-01 23:01:01", 62 expectTime: "2019-01-02 00:02:00", 63 }, 64 65 { 66 description: "evey minute", 67 at: &AtTime{ 68 WeekDay: "*", 69 Hour: "*", 70 Minute: "*", 71 }, 72 baseTime: "2019-01-01 01:01:01", 73 expectTime: "2019-01-01 01:02:00", 74 }, 75 76 { 77 description: "evey 30 minute before", 78 at: &AtTime{ 79 WeekDay: "*", 80 Hour: "*", 81 Minute: "30", 82 }, 83 baseTime: "2019-01-01 01:01:01", 84 expectTime: "2019-01-01 01:30:00", 85 }, 86 { 87 description: "evey 30 minute after", 88 at: &AtTime{ 89 WeekDay: "*", 90 Hour: "*", 91 Minute: "30", 92 }, 93 baseTime: "2019-01-01 01:31:01", 94 expectTime: "2019-01-01 02:30:00", 95 }, 96 { 97 description: "evey 10, 30 minute, before", 98 at: &AtTime{ 99 WeekDay: "*", 100 Hour: "*", 101 Minute: "10,30", 102 }, 103 baseTime: "2019-01-01 01:09:01", 104 expectTime: "2019-01-01 01:10:00", 105 }, 106 { 107 description: "evey 10, 30 minute, after first", 108 at: &AtTime{ 109 WeekDay: "*", 110 Hour: "*", 111 Minute: "10,30", 112 }, 113 baseTime: "2019-01-01 01:13:01", 114 expectTime: "2019-01-01 01:30:00", 115 }, 116 { 117 description: "evey 10, 30 minute, after second", 118 at: &AtTime{ 119 WeekDay: "*", 120 Hour: "*", 121 Minute: "10,30", 122 }, 123 baseTime: "2019-01-01 01:33:01", 124 expectTime: "2019-01-01 02:10:00", 125 }, 126 127 { 128 description: "evey *:0 minute", 129 at: &AtTime{ 130 WeekDay: "*", 131 Hour: "*", 132 Minute: "0", 133 }, 134 baseTime: "2019-01-01 01:59:01", 135 expectTime: "2019-01-01 02:00:00", 136 }, 137 138 { 139 description: "evey hour", 140 at: &AtTime{ 141 WeekDay: "*", 142 Hour: "*", 143 Minute: "", 144 }, 145 baseTime: "2019-01-01 01:33:01", 146 expectTime: "2019-01-01 02:00:00", 147 }, 148 { 149 description: "at 13 hour, before", 150 at: &AtTime{ 151 WeekDay: "*", 152 Hour: "13", 153 Minute: "", 154 }, 155 baseTime: "2019-01-01 01:33:01", 156 expectTime: "2019-01-01 13:00:00", 157 }, 158 { 159 description: "at 13 hour, after", 160 at: &AtTime{ 161 WeekDay: "*", 162 Hour: "13", 163 Minute: "", 164 }, 165 baseTime: "2019-01-01 15:33:01", 166 expectTime: "2019-01-02 13:00:00", 167 }, 168 { 169 description: "at midnight", 170 at: &AtTime{ 171 WeekDay: "*", 172 Hour: "0", 173 Minute: "", 174 }, 175 baseTime: "2019-01-01 23:33:01", 176 expectTime: "2019-01-02 00:00:00", 177 }, 178 179 { 180 description: "at midnight weekday 9", 181 at: &AtTime{ 182 WeekDay: "*", 183 Hour: "0", 184 Minute: "", 185 }, 186 baseTime: "2019-01-06 23:33:01", 187 expectTime: "2019-01-07 00:00:00", 188 }, 189 190 { 191 description: "every 0 weekday", 192 at: &AtTime{ 193 WeekDay: "0", 194 Hour: "", 195 Minute: "", 196 }, 197 baseTime: "2019-01-04 23:33:01", 198 expectTime: "2019-01-06 00:00:00", 199 }, 200 201 { 202 description: "every 2 weekday", 203 at: &AtTime{ 204 WeekDay: "2", 205 Hour: "", 206 Minute: "", 207 }, 208 baseTime: "2019-01-04 23:33:01", 209 expectTime: "2019-01-08 00:00:00", 210 }, 211 212 { 213 description: "every 2nd weekday - overlaps with base time", 214 at: &AtTime{ 215 WeekDay: "2", 216 Hour: "", 217 Minute: "", 218 }, 219 baseTime: "2019-01-08 23:33:01", 220 expectTime: "2019-01-15 00:00:00", 221 }, 222 { 223 description: "every 5 weekday in the future", 224 at: &AtTime{ 225 WeekDay: "2,5", 226 Hour: "", 227 Minute: "", 228 }, 229 baseTime: "2019-01-09 23:33:01", 230 expectTime: "2019-01-11 00:00:00", 231 }, 232 { 233 description: "every 5 weekday in the future tz", 234 at: &AtTime{ 235 WeekDay: "2,5", 236 Hour: "", 237 Minute: "", 238 TZ: "America/Los_Angeles", 239 }, 240 baseTime: "2019-01-09 23:33:01", 241 expectTime: "2019-01-11 00:00:00", 242 }, 243 } 244 245 for _, useCase := range useCases { 246 247 err := useCase.at.Init() 248 assert.Nil(t, err) 249 250 var loc *time.Location 251 if useCase.at.TZ != "" { 252 loc, _ = time.LoadLocation(useCase.at.TZ) 253 } 254 var baseTime time.Time 255 if loc != nil { 256 baseTime, err = time.ParseInLocation(timeLayout, useCase.baseTime, loc) 257 assert.Nil(t, err, useCase.description) 258 } else { 259 baseTime, err = time.Parse(timeLayout, useCase.baseTime) 260 assert.Nil(t, err, useCase.description) 261 262 } 263 264 var expectTime time.Time 265 if loc != nil { 266 expectTime, err = time.ParseInLocation(timeLayout, useCase.expectTime, loc) 267 assert.Nil(t, err, useCase.description) 268 } else { 269 expectTime, err = time.Parse(timeLayout, useCase.expectTime) 270 assert.Nil(t, err, useCase.description) 271 272 } 273 actualTime := useCase.at.Next(baseTime) 274 assert.Equal(t, expectTime, actualTime, useCase.description) 275 276 //without tz 277 baseTime, err = time.Parse(timeLayout, useCase.baseTime) 278 actualTime = useCase.at.Next(baseTime) 279 assert.Equal(t, expectTime, actualTime, useCase.description) 280 281 } 282 283 } 284 285 func TestNewDuration(t *testing.T) { 286 287 var useCases = []struct { 288 description string 289 value int 290 unit string 291 expected time.Duration 292 hasError bool 293 }{ 294 { 295 description: "sec test", 296 value: 3, 297 unit: DurationSecond, 298 expected: 3 * time.Second, 299 }, 300 { 301 description: "min test", 302 value: 4, 303 unit: DurationMinute, 304 expected: 4 * time.Minute, 305 }, 306 { 307 description: "hour test", 308 value: 5, 309 unit: DurationHour, 310 expected: 5 * time.Hour, 311 }, 312 { 313 description: "day test", 314 value: 12, 315 unit: DurationDay, 316 expected: 12 * time.Hour * 24, 317 }, 318 { 319 description: "week test", 320 value: 7, 321 unit: DurationWeek, 322 expected: 7 * time.Hour * 24 * 7, 323 }, 324 { 325 description: "error test", 326 value: 4, 327 unit: "abc", 328 hasError: true, 329 }, 330 } 331 332 for _, useCase := range useCases { 333 actual, err := NewDuration(useCase.value, useCase.unit) 334 if useCase.hasError { 335 assert.NotNil(t, err, useCase.description) 336 continue 337 } else if err != nil { 338 assert.Nil(t, err, useCase.description) 339 continue 340 } 341 assert.Equal(t, useCase.expected, actual, useCase.description) 342 343 } 344 345 } 346 347 func TestIdMatcher_Match(t *testing.T) { 348 { 349 ts, err := TimeAt("1 sec ahead") 350 assert.Nil(t, err) 351 assert.EqualValues(t, ts.Unix()-1, time.Now().Unix()) 352 } 353 { //invalid duration unit 354 _, err := TimeAt("1 d ahead") 355 assert.NotNil(t, err) 356 } 357 } 358 359 func TestTimeDiff(t *testing.T) { 360 var useCases = []struct { 361 description string 362 base time.Time 363 expression string 364 exectedDiff time.Duration 365 hasError bool 366 }{ 367 { 368 description: "now test", 369 expression: "now", 370 base: time.Now(), 371 exectedDiff: 0, 372 }, 373 { 374 description: "tomorrow test", 375 expression: "tomorrow", 376 base: time.Now(), 377 exectedDiff: time.Hour * 24, 378 }, 379 { 380 description: "yesterday test", 381 expression: "yesterday", 382 base: time.Now(), 383 exectedDiff: -time.Hour * 24, 384 }, 385 { 386 description: "empty expr error", 387 hasError: true, 388 }, 389 { 390 description: "parsing expr error", 391 expression: "a232", 392 hasError: true, 393 }, 394 { 395 description: "2 days ago test", 396 expression: "2daysago", 397 base: time.Now(), 398 exectedDiff: -time.Hour * 48, 399 }, 400 401 { 402 description: "2 days in the future", 403 expression: "2day in the future", 404 base: time.Now(), 405 exectedDiff: time.Hour * 48, 406 }, 407 408 { 409 description: "days in the future", 410 expression: "day InTheFuture", 411 base: time.Now(), 412 exectedDiff: time.Hour * 24, 413 }, 414 415 { 416 description: "2 hours before", 417 expression: "2hourbefore", 418 base: time.Now(), 419 exectedDiff: -time.Hour * 2, 420 }, 421 { 422 description: "2 hours later", 423 expression: "2 hoursLater", 424 base: time.Now(), 425 exectedDiff: time.Hour * 2, 426 }, 427 { 428 description: "timezone", 429 expression: "nowInUTC", 430 base: time.Now(), 431 exectedDiff: 0, 432 }, 433 434 { 435 description: "invalid timezone error", 436 expression: "nowInBAAA", 437 base: time.Now(), 438 hasError: true, 439 }, 440 441 { 442 description: "day in UTC", 443 expression: "2 days ago in UTC", 444 base: time.Now(), 445 exectedDiff: -time.Hour * 48, 446 }, 447 448 { 449 description: "day in UTC", 450 expression: "weekAheadInUTC", 451 base: time.Now(), 452 exectedDiff: time.Hour * 24 * 7, 453 }, 454 } 455 456 for _, useCase := range useCases { 457 actual, err := TimeDiff(useCase.base, useCase.expression) 458 if useCase.hasError { 459 assert.NotNil(t, err, useCase.description) 460 continue 461 } else if err != nil { 462 assert.Nil(t, err, useCase.description) 463 continue 464 } 465 expected := useCase.base.Add(useCase.exectedDiff) 466 assert.EqualValues(t, expected.Unix(), actual.Unix(), useCase.description) 467 468 } 469 470 } 471 472 func TestDayElapsedInPct(t *testing.T) { 473 474 t0, _ := time.Parse(DateFormatToLayout("yyyy-MM-dd hh:mm:ss"), "2017-01-01 12:00:00") 475 elapsedPct := ElapsedDay(t0) 476 assert.EqualValues(t, 50, math.Round(100*elapsedPct)) 477 478 elapsed, err := ElapsedToday("") 479 assert.Nil(t, err) 480 assert.True(t, elapsed > 0) 481 482 remaining, err := RemainingToday("") 483 assert.Nil(t, err) 484 assert.True(t, remaining > 0) 485 assert.EqualValues(t, int(remaining+elapsed), 1) 486 487 } 488 489 func TestTimeWindow_Range(t *testing.T) { 490 491 var useCaes = []struct { 492 description string 493 window *TimeWindow 494 expectedCount int 495 }{ 496 { 497 description: "empty window", 498 window: &TimeWindow{}, 499 expectedCount: 1, 500 }, 501 { 502 description: "loopback window", 503 window: &TimeWindow{ 504 TimeFormat: "yyyy-MM-dd HH:mm:ss", 505 Loopback: &Duration{Value: 3, Unit: "sec"}, 506 EndDate: "2011-12-01 15:01:01", 507 Interval: &Duration{Value: 1, Unit: "sec"}, 508 }, 509 expectedCount: 4, 510 }, 511 { 512 description: "default loopback with interval window", 513 window: &TimeWindow{ 514 Loopback: &Duration{Value: 3, Unit: "min"}, 515 Interval: &Duration{Value: 1, Unit: "min"}, 516 }, 517 expectedCount: 4, 518 }, 519 { 520 description: "default loopback window", 521 window: &TimeWindow{ 522 Loopback: &Duration{Value: 3, Unit: "min"}, 523 }, 524 expectedCount: 2, 525 }, 526 { 527 description: "date range window", 528 window: &TimeWindow{ 529 TimeFormat: "yyyy-MM-dd HH:mm:ss", 530 StartDate: "2011-12-01 15:01:01", 531 EndDate: "2011-12-01 15:02:01", 532 Interval: &Duration{Value: 10, Unit: "sec"}}, 533 expectedCount: 7, 534 }, 535 } 536 537 for _, useCase := range useCaes { 538 count := 0 539 err := useCase.window.Range(func(time time.Time) (bool, error) { 540 count++ 541 return true, nil 542 }) 543 assert.Nil(t, err, useCase.description) 544 assert.Equal(t, useCase.expectedCount, count, useCase.description) 545 } 546 547 } 548 549 550 func TestN(t *testing.T) { 551 552 553 }