1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
|
#include <library/cpp/cron_expression/cron_expression.h>
#include <util/datetime/base.h>
#include <library/cpp/testing/unittest/registar.h>
namespace {
void TestNext(const TStringBuf cron, const TStringBuf date, const TStringBuf ans) {
TInstant ansTI = TInstant::ParseIso8601(ans);
TInstant dateTI = TInstant::ParseIso8601(date);
NDatetime::TCivilSecond ansTZ = NDatetime::Convert(ansTI, "UTC");
NDatetime::TCivilSecond dateTZ = NDatetime::Convert(dateTI, "UTC");
TCronExpression cronConverter(cron);
UNIT_ASSERT_VALUES_EQUAL(cronConverter.CronNext(dateTZ), ansTZ);
}
void TestPrev(const TStringBuf cron, const TStringBuf date, const TStringBuf ans) {
TInstant ansTI = TInstant::ParseIso8601(ans);
TInstant dateTI = TInstant::ParseIso8601(date);
NDatetime::TCivilSecond ansTZ = NDatetime::Convert(ansTI, "UTC");
NDatetime::TCivilSecond dateTZ = NDatetime::Convert(dateTI, "UTC");
TCronExpression cronConverter(cron);
UNIT_ASSERT_VALUES_EQUAL(cronConverter.CronPrev(dateTZ), ansTZ);
}
void TestNextCron(TCronExpression* cron, const TStringBuf date, const TStringBuf ans) {
TInstant ansTI = TInstant::ParseIso8601(ans);
TInstant dateTI = TInstant::ParseIso8601(date);
NDatetime::TCivilSecond ansTZ = NDatetime::Convert(ansTI, "UTC");
NDatetime::TCivilSecond dateTZ = NDatetime::Convert(dateTI, "UTC");
UNIT_ASSERT_VALUES_EQUAL(cron->CronNext(dateTZ), ansTZ);
}
void TestPrevCron(TCronExpression* cron, const TStringBuf date, const TStringBuf ans) {
TInstant ansTI = TInstant::ParseIso8601(ans);
TInstant dateTI = TInstant::ParseIso8601(date);
NDatetime::TCivilSecond ansTZ = NDatetime::Convert(ansTI, "UTC");
NDatetime::TCivilSecond dateTZ = NDatetime::Convert(dateTI, "UTC");
UNIT_ASSERT_VALUES_EQUAL(cron->CronPrev(dateTZ), ansTZ);
}
void TestNextCronBadRequest(TCronExpression* cron, const TStringBuf date) {
TInstant dateTI = TInstant::ParseIso8601(date);
NDatetime::TCivilSecond dateTZ = NDatetime::Convert(dateTI, "UTC");
UNIT_ASSERT_EXCEPTION(cron->CronNext(dateTZ), yexception);
}
void TestPrevCronBadRequest(TCronExpression* cron, const TStringBuf date) {
TInstant dateTI = TInstant::ParseIso8601(date);
NDatetime::TCivilSecond dateTZ = NDatetime::Convert(dateTI, "UTC");
UNIT_ASSERT_EXCEPTION(cron->CronPrev(dateTZ), yexception);
}
Y_UNIT_TEST_SUITE(TestNext) {
Y_UNIT_TEST(Basic) {
TestNext("* * * * * *", "2022-12-29T23:59:59Z", "2022-12-30T00:00:00Z");
TestNext("* * * * * *", "2022-12-30T08:10:23Z", "2022-12-30T08:10:24Z");
TestNext("* * * * * *", "2100-01-01T15:12:42Z", "2100-01-01T15:12:43Z");
TestNext("* * * * * *", "2198-01-01T15:12:42Z", "2198-01-01T15:12:43Z");
TestNext("* * * * * *", "2199-01-01T15:12:42Z", "2199-01-01T15:12:43Z");
TestNext("* * * 1 * *", "2024-02-03T15:12:42Z", "2024-03-01T00:00:00Z");
TestNext("* * * 1 1 * *", "1970-01-01T15:12:42Z", "1970-01-01T15:12:43Z");
TestNext("* * * 1 1 * 1970,2100,2193,2199", "1970-01-01T15:12:42Z", "1970-01-01T15:12:43Z");
TestNext("* * * 1 1 * 1970,2100,2193,2199", "1971-01-01T15:12:42Z", "2100-01-01T00:00:00Z");
TestNext("* * * 1 1 * 1970,2100,2193,2199", "2195-01-01T15:12:42Z", "2199-01-01T00:00:00Z");
TestNext("* * * 1 1 * 2020", "2011-02-02T15:12:42Z", "2020-01-01T00:00:00Z");
}
Y_UNIT_TEST(WorkingDays) {
TestNext("* * * 1W * *", "2011-01-01T15:12:42Z", "2011-01-03T00:00:00Z");
TestNext("* * * 31W * *", "2010-01-01T15:12:42Z", "2010-01-29T00:00:00Z");
TestNext("* * * LW * *", "2010-01-01T15:12:42Z", "2010-01-29T00:00:00Z");
TestNext("* * * LW * *", "2010-02-03T15:12:42Z", "2010-02-26T00:00:00Z");
TestNext("* * * LW * *", "2010-03-06T15:12:42Z", "2010-03-31T00:00:00Z");
TestNext("* * * LW * *", "2010-04-09T15:12:42Z", "2010-04-30T00:00:00Z");
TestNext("* * * LW * *", "2010-05-12T15:12:42Z", "2010-05-31T00:00:00Z");
TestNext("* * * LW * *", "2010-06-15T15:12:42Z", "2010-06-30T00:00:00Z");
TestNext("* * * LW * *", "2010-07-18T15:12:42Z", "2010-07-30T00:00:00Z");
TestNext("* * * LW * *", "2010-08-21T15:12:42Z", "2010-08-31T00:00:00Z");
TestNext("* * * LW * *", "2010-09-24T15:12:42Z", "2010-09-30T00:00:00Z");
TestNext("* * * LW * *", "2010-10-27T15:12:42Z", "2010-10-29T00:00:00Z");
TestNext("* * * LW * *", "2010-11-30T15:12:42Z", "2010-11-30T15:12:43Z");
TestNext("* * * LW * *", "2010-12-31T15:12:42Z", "2010-12-31T15:12:43Z");
TestNext("* * * 15W * *", "2010-01-01T15:12:42Z", "2010-01-15T00:00:00Z");
TestNext("* * * 15W * *", "2010-02-03T15:12:42Z", "2010-02-15T00:00:00Z");
TestNext("* * * 15W * *", "2010-03-06T15:12:42Z", "2010-03-15T00:00:00Z");
TestNext("* * * 15W * *", "2010-04-09T15:12:42Z", "2010-04-15T00:00:00Z");
TestNext("* * * 15W * *", "2010-05-12T15:12:42Z", "2010-05-14T00:00:00Z");
TestNext("* * * 15W * *", "2010-06-15T15:12:42Z", "2010-06-15T15:12:43Z");
TestNext("* * * 15W * *", "2010-07-18T15:12:42Z", "2010-08-16T00:00:00Z");
TestNext("* * * 15W * *", "2010-08-21T15:12:42Z", "2010-09-15T00:00:00Z");
TestNext("* * * 15W * *", "2010-09-24T15:12:42Z", "2010-10-15T00:00:00Z");
TestNext("* * * 15W * *", "2010-10-27T15:12:42Z", "2010-11-15T00:00:00Z");
TestNext("* * * 15W * *", "2010-11-30T15:12:42Z", "2010-12-15T00:00:00Z");
TestNext("* * * 15W * *", "2010-12-31T15:12:42Z", "2011-01-14T00:00:00Z");
}
Y_UNIT_TEST(LastDaysOfMonth) {
TestNext("* * * L-3 * *", "2010-01-01T15:12:42Z", "2010-01-28T00:00:00Z");
TestNext("* * * L-1 * *", "2010-01-01T15:12:42Z", "2010-01-30T00:00:00Z");
TestNext("* * * L-1 * *", "2010-02-03T15:12:42Z", "2010-02-27T00:00:00Z");
TestNext("* * * L-1 * *", "2010-03-06T15:12:42Z", "2010-03-30T00:00:00Z");
TestNext("* * * L-1 * *", "2010-04-09T15:12:42Z", "2010-04-29T00:00:00Z");
TestNext("* * * L-1 * *", "2010-05-12T15:12:42Z", "2010-05-30T00:00:00Z");
TestNext("* * * L-1 * *", "2010-06-15T15:12:42Z", "2010-06-29T00:00:00Z");
TestNext("* * * L-1 * *", "2010-07-18T15:12:42Z", "2010-07-30T00:00:00Z");
TestNext("* * * L-1 * *", "2010-08-21T15:12:42Z", "2010-08-30T00:00:00Z");
TestNext("* * * L-1 * *", "2010-09-24T15:12:42Z", "2010-09-29T00:00:00Z");
TestNext("* * * L-1 * *", "2010-10-27T15:12:42Z", "2010-10-30T00:00:00Z");
TestNext("* * * L-1 * *", "2010-11-30T15:12:42Z", "2010-12-30T00:00:00Z");
TestNext("* * * L-1 * *", "2010-12-31T15:12:42Z", "2011-01-30T00:00:00Z");
TestNext("* * * L * *", "2010-01-01T15:12:42Z", "2010-01-31T00:00:00Z");
TestNext("* * * L * *", "2010-02-03T15:12:42Z", "2010-02-28T00:00:00Z");
TestNext("* * * L * *", "2010-03-06T15:12:42Z", "2010-03-31T00:00:00Z");
TestNext("* * * L * *", "2010-04-09T15:12:42Z", "2010-04-30T00:00:00Z");
TestNext("* * * L * *", "2010-05-12T15:12:42Z", "2010-05-31T00:00:00Z");
TestNext("* * * L * *", "2010-06-15T15:12:42Z", "2010-06-30T00:00:00Z");
TestNext("* * * L * *", "2010-07-18T15:12:42Z", "2010-07-31T00:00:00Z");
TestNext("* * * L * *", "2010-08-21T15:12:42Z", "2010-08-31T00:00:00Z");
TestNext("* * * L * *", "2010-09-24T15:12:42Z", "2010-09-30T00:00:00Z");
TestNext("* * * L * *", "2010-10-27T15:12:42Z", "2010-10-31T00:00:00Z");
TestNext("* * * L * *", "2010-11-30T15:12:42Z", "2010-11-30T15:12:43Z");
TestNext("* * * L * *", "2010-12-31T15:12:42Z", "2010-12-31T15:12:43Z");
}
Y_UNIT_TEST(Everys) {
TestNext("* * * * * 1#-5", "2010-09-03T15:12:42Z", "2010-11-01T00:00:00Z");
TestNext("* * * * * 1#-4", "2010-09-03T15:12:42Z", "2010-09-06T00:00:00Z");
TestNext("* * * * * 1#-3", "2010-09-03T15:12:42Z", "2010-09-13T00:00:00Z");
TestNext("* * * * * 1#-2", "2010-09-03T15:12:42Z", "2010-09-20T00:00:00Z");
TestNext("* * * * * 1#1", "2010-09-03T15:12:42Z", "2010-09-06T00:00:00Z");
TestNext("* * * * * 1#2", "2010-09-03T15:12:42Z", "2010-09-13T00:00:00Z");
TestNext("* * * * * 1#3", "2010-09-03T15:12:42Z", "2010-09-20T00:00:00Z");
TestNext("* * * * * 1#4", "2010-09-03T15:12:42Z", "2010-09-27T00:00:00Z");
TestNext("* * * * * 1#5", "2010-09-03T15:12:42Z", "2010-11-29T00:00:00Z");
TestNext("* * * * * 2#-5", "2010-09-03T15:12:42Z", "2010-11-02T00:00:00Z");
TestNext("* * * * * 2#-4", "2010-09-03T15:12:42Z", "2010-09-07T00:00:00Z");
TestNext("* * * * * 2#-3", "2010-09-03T15:12:42Z", "2010-09-14T00:00:00Z");
TestNext("* * * * * 2#-2", "2010-09-03T15:12:42Z", "2010-09-21T00:00:00Z");
TestNext("* * * * * 2#1", "2010-09-03T15:12:42Z", "2010-09-07T00:00:00Z");
TestNext("* * * * * 2#2", "2010-09-03T15:12:42Z", "2010-09-14T00:00:00Z");
TestNext("* * * * * 2#3", "2010-09-03T15:12:42Z", "2010-09-21T00:00:00Z");
TestNext("* * * * * 2#4", "2010-09-03T15:12:42Z", "2010-09-28T00:00:00Z");
TestNext("* * * * * 2#5", "2010-09-03T15:12:42Z", "2010-11-30T00:00:00Z");
TestNext("* * * * * 3#-5", "2010-09-03T15:12:42Z", "2010-12-01T00:00:00Z");
TestNext("* * * * * 3#-4", "2010-09-03T15:12:42Z", "2010-09-08T00:00:00Z");
TestNext("* * * * * 3#-3", "2010-09-03T15:12:42Z", "2010-09-15T00:00:00Z");
TestNext("* * * * * 3#-2", "2010-09-03T15:12:42Z", "2010-09-22T00:00:00Z");
TestNext("* * * * * 3#1", "2010-09-03T15:12:42Z", "2010-10-06T00:00:00Z");
TestNext("* * * * * 3#2", "2010-09-03T15:12:42Z", "2010-09-08T00:00:00Z");
TestNext("* * * * * 3#3", "2010-09-03T15:12:42Z", "2010-09-15T00:00:00Z");
TestNext("* * * * * 3#4", "2010-09-03T15:12:42Z", "2010-09-22T00:00:00Z");
TestNext("* * * * * 3#5", "2010-09-03T15:12:42Z", "2010-09-29T00:00:00Z");
TestNext("* * * * * 4#-5", "2010-09-03T15:12:42Z", "2010-12-02T00:00:00Z");
TestNext("* * * * * 4#-4", "2010-09-03T15:12:42Z", "2010-09-09T00:00:00Z");
TestNext("* * * * * 4#-3", "2010-09-03T15:12:42Z", "2010-09-16T00:00:00Z");
TestNext("* * * * * 4#-2", "2010-09-03T15:12:42Z", "2010-09-23T00:00:00Z");
TestNext("* * * * * 4#1", "2010-09-03T15:12:42Z", "2010-10-07T00:00:00Z");
TestNext("* * * * * 4#2", "2010-09-03T15:12:42Z", "2010-09-09T00:00:00Z");
TestNext("* * * * * 4#3", "2010-09-03T15:12:42Z", "2010-09-16T00:00:00Z");
TestNext("* * * * * 4#4", "2010-09-03T15:12:42Z", "2010-09-23T00:00:00Z");
TestNext("* * * * * 4#5", "2010-09-03T15:12:42Z", "2010-09-30T00:00:00Z");
TestNext("* * * * * 5#-5", "2010-09-03T15:12:42Z", "2010-10-01T00:00:00Z");
TestNext("* * * * * 5#-4", "2010-09-03T15:12:42Z", "2010-09-03T15:12:43Z");
TestNext("* * * * * 5#-3", "2010-09-03T15:12:42Z", "2010-09-10T00:00:00Z");
TestNext("* * * * * 5#-2", "2010-09-03T15:12:42Z", "2010-09-17T00:00:00Z");
TestNext("* * * * * 5#1", "2010-09-03T15:12:42Z", "2010-09-03T15:12:43Z");
TestNext("* * * * * 5#2", "2010-09-03T15:12:42Z", "2010-09-10T00:00:00Z");
TestNext("* * * * * 5#3", "2010-09-03T15:12:42Z", "2010-09-17T00:00:00Z");
TestNext("* * * * * 5#4", "2010-09-03T15:12:42Z", "2010-09-24T00:00:00Z");
TestNext("* * * * * 5#5", "2010-09-03T15:12:42Z", "2010-10-29T00:00:00Z");
TestNext("* * * * * 6#-5", "2010-09-03T15:12:42Z", "2010-10-02T00:00:00Z");
TestNext("* * * * * 6#-4", "2010-09-03T15:12:42Z", "2010-09-04T00:00:00Z");
TestNext("* * * * * 6#-3", "2010-09-03T15:12:42Z", "2010-09-11T00:00:00Z");
TestNext("* * * * * 6#-2", "2010-09-03T15:12:42Z", "2010-09-18T00:00:00Z");
TestNext("* * * * * 6#1", "2010-09-03T15:12:42Z", "2010-09-04T00:00:00Z");
TestNext("* * * * * 6#2", "2010-09-03T15:12:42Z", "2010-09-11T00:00:00Z");
TestNext("* * * * * 6#3", "2010-09-03T15:12:42Z", "2010-09-18T00:00:00Z");
TestNext("* * * * * 6#4", "2010-09-03T15:12:42Z", "2010-09-25T00:00:00Z");
TestNext("* * * * * 6#5", "2010-09-03T15:12:42Z", "2010-10-30T00:00:00Z");
TestNext("* * * * * 7#-5", "2010-09-03T15:12:42Z", "2010-10-03T00:00:00Z");
TestNext("* * * * * 7#-4", "2010-09-03T15:12:42Z", "2010-09-05T00:00:00Z");
TestNext("* * * * * 7#-3", "2010-09-03T15:12:42Z", "2010-09-12T00:00:00Z");
TestNext("* * * * * 7#-2", "2010-09-03T15:12:42Z", "2010-09-19T00:00:00Z");
TestNext("* * * * * 7#1", "2010-09-03T15:12:42Z", "2010-09-05T00:00:00Z");
TestNext("* * * * * 7#2", "2010-09-03T15:12:42Z", "2010-09-12T00:00:00Z");
TestNext("* * * * * 7#3", "2010-09-03T15:12:42Z", "2010-09-19T00:00:00Z");
TestNext("* * * * * 7#4", "2010-09-03T15:12:42Z", "2010-09-26T00:00:00Z");
TestNext("* * * * * 7#5", "2010-09-03T15:12:42Z", "2010-10-31T00:00:00Z");
}
Y_UNIT_TEST(LastWeekdays) {
TestNext("* * * * * 1L", "2010-09-30T15:12:42Z", "2010-10-25T00:00:00Z");
TestNext("* * * * * 2L", "2010-09-30T15:12:42Z", "2010-10-26T00:00:00Z");
TestNext("* * * * * 3L", "2010-09-30T15:12:42Z", "2010-10-27T00:00:00Z");
TestNext("* * * * * 4L", "2010-09-30T15:12:42Z", "2010-09-30T15:12:43Z");
TestNext("* * * * * 5L", "2010-09-30T15:12:42Z", "2010-10-29T00:00:00Z");
TestNext("* * * * * 6L", "2010-09-30T15:12:42Z", "2010-10-30T00:00:00Z");
TestNext("* * * * * 7L", "2010-09-30T15:12:42Z", "2010-10-31T00:00:00Z");
TestNext("* * * * * 1L", "2010-10-27T15:12:42Z", "2010-11-29T00:00:00Z");
TestNext("* * * * * 2L", "2010-10-27T15:12:42Z", "2010-11-30T00:00:00Z");
TestNext("* * * * * 3L", "2010-10-27T15:12:42Z", "2010-10-27T15:12:43Z");
TestNext("* * * * * 4L", "2010-10-27T15:12:42Z", "2010-10-28T00:00:00Z");
TestNext("* * * * * 5L", "2010-10-27T15:12:42Z", "2010-10-29T00:00:00Z");
TestNext("* * * * * 6L", "2010-10-27T15:12:42Z", "2010-10-30T00:00:00Z");
TestNext("* * * * * 7L", "2010-10-27T15:12:42Z", "2010-10-31T00:00:00Z");
TestNext("* * * * * 1L", "2010-10-30T15:12:42Z", "2010-11-29T00:00:00Z");
TestNext("* * * * * 2L", "2010-10-30T15:12:42Z", "2010-11-30T00:00:00Z");
TestNext("* * * * * 3L", "2010-10-30T15:12:42Z", "2010-11-24T00:00:00Z");
TestNext("* * * * * 4L", "2010-10-30T15:12:42Z", "2010-11-25T00:00:00Z");
TestNext("* * * * * 5L", "2010-10-30T15:12:42Z", "2010-11-26T00:00:00Z");
TestNext("* * * * * 6L", "2010-10-30T15:12:42Z", "2010-10-30T15:12:43Z");
TestNext("* * * * * 7L", "2010-10-30T15:12:42Z", "2010-10-31T00:00:00Z");
TestNext("* * * * * 1L", "2010-11-27T15:12:42Z", "2010-11-29T00:00:00Z");
TestNext("* * * * * 2L", "2010-11-27T15:12:42Z", "2010-11-30T00:00:00Z");
TestNext("* * * * * 3L", "2010-11-27T15:12:42Z", "2010-12-29T00:00:00Z");
TestNext("* * * * * 4L", "2010-11-27T15:12:42Z", "2010-12-30T00:00:00Z");
TestNext("* * * * * 5L", "2010-11-27T15:12:42Z", "2010-12-31T00:00:00Z");
TestNext("* * * * * 6L", "2010-11-27T15:12:42Z", "2010-11-27T15:12:43Z");
TestNext("* * * * * 7L", "2010-11-27T15:12:42Z", "2010-11-28T00:00:00Z");
}
Y_UNIT_TEST(ComplicatedCases) {
TestNext("10-45/3 30-50/7 10,12,13,14,22,23 */2 * 1-5", "2024-04-23T09:42:45Z", "2024-04-23T10:30:10Z");
TestNext("10-45/3 30-50/7 10,12,13,14,22,23 */2 * 1-5", "2024-04-22T09:42:45Z", "2024-04-23T10:30:10Z");
TestNext("10-45/3 30-50/7 10,12,13,14,22,23 */2 * 1-5", "2024-04-20T04:30:13Z", "2024-04-23T10:30:10Z");
TestNext("10-45/3 30-50/7 10,12,13,14,22,23 */2 * 1-5", "2024-04-23T11:32:00Z", "2024-04-23T12:30:10Z");
TestNext("10-45/3 30-50/7 10,12,13,14,22,23 */2 * 1-5", "2024-04-23T12:32:17Z", "2024-04-23T12:37:10Z");
TestNext("10-45/3 30-50/7 10,12,13,14,22,23 30 * 1#5", "2024-04-23T12:32:17Z", "2024-09-30T10:30:10Z");
TestNext("10-45/3 30-50/7 10,12,13,14,22,23 L * 1", "2024-04-23T10:31:11Z", "2024-09-30T10:30:10Z");
TestNext("* * 10 L * 5", "2024-04-23T10:31:11Z", "2024-05-31T10:00:00Z");
TestNext("* * 10 L-1 * 4", "2024-04-23T10:31:11Z", "2024-05-30T10:00:00Z");
TestNext("* * 10 L-2 * 3", "2024-04-23T10:31:11Z", "2024-05-29T10:00:00Z");
TestNext("* * 10 L-3 * 2", "2024-04-23T10:31:11Z", "2024-05-28T10:00:00Z");
TestNext("* * 10 L-4 * 1", "2024-04-23T10:31:11Z", "2024-05-27T10:00:00Z");
TestNext("* * 10 L-5 * 0", "2024-04-23T10:31:11Z", "2024-05-26T10:00:00Z");
TestNext("* * 10 L-6 * 6", "2024-04-23T10:31:11Z", "2024-05-25T10:00:00Z");
}
Y_UNIT_TEST(DifferentCases) {
TestNext("10-45/3 * * * * *", "2012-12-01T09:42:19Z", "2012-12-01T09:42:22Z");
TestNext("10-45/3 * * * * *", "2012-12-01T09:42:45Z", "2012-12-01T09:43:10Z");
TestNext("* * 19/2 * * *", "2012-12-01T09:42:45Z", "2012-12-01T19:00:00Z");
TestNext("* * 19/2 * * *", "2012-12-01T19:42:45Z", "2012-12-01T19:42:46Z");
TestNext("37 * 19/2 * * *", "2012-12-01T19:42:45Z", "2012-12-01T19:43:37Z");
TestNext("37 * 19/2 * * *", "2012-12-01T19:59:45Z", "2012-12-01T21:00:37Z");
TestNext("37 * 19/2 * * *", "2012-12-01T19:59:37Z", "2012-12-01T21:00:37Z");
TestNext("37 * 18/2 * * *", "2012-12-01T23:00:00Z", "2012-12-02T18:00:37Z");
TestNext("37 * 18/2 * * *", "2012-12-01T22:59:37Z", "2012-12-02T18:00:37Z");
TestNext("0 0 7 W * *", "2009-09-26T00:42:55Z", "2009-09-28T07:00:00Z");
TestNext("0 0 7 W * *", "2009-09-28T07:00:00Z", "2009-09-29T07:00:00Z");
TestNext("* * * * * L", "2010-10-25T15:12:42Z", "2010-10-31T00:00:00Z");
TestNext("* * * * * L", "2010-10-20T15:12:42Z", "2010-10-24T00:00:00Z");
TestNext("* * * * * L", "2010-10-27T15:12:42Z", "2010-10-31T00:00:00Z");
TestNext("* 15 11 * * *", "2019-03-09T11:43:00Z", "2019-03-10T11:15:00Z");
TestNext("*/15 * 1-4 * * *", "2012-07-01T09:53:50Z", "2012-07-02T01:00:00Z");
TestNext("*/15 * 1-4 * * *", "2012-07-01T09:53:00Z", "2012-07-02T01:00:00Z");
TestNext("3,15,30,45 * 1,2,3,4 * * *", "2012-07-01T01:53:00Z", "2012-07-01T01:53:03Z");
TestNext("3,15,30,45 10 * * * *", "2012-07-01T09:53:10Z", "2012-07-01T10:10:03Z");
TestNext("3,15,30,45 * 1,2,3,4 * * *", "2012-07-01T09:53:10Z", "2012-07-02T01:00:03Z");
TestNext("10,20 1,2,3,4 1,2,3,6 * *", "2012-07-01T09:15:00Z", "2012-07-02T01:10:00Z");
TestNext("0 */2 1-4 * * *", "2012-07-01T09:00:00Z", "2012-07-02T01:00:00Z");
TestNext("0 */2 * * * *", "2012-07-01T09:00:00Z", "2012-07-01T09:02:00Z");
TestNext("0 */2 * * * *", "2013-07-01T09:00:00Z", "2013-07-01T09:02:00Z");
TestNext("0 */2 * * * *", "2018-09-14T14:24:00Z", "2018-09-14T14:26:00Z");
TestNext("0 */2 * * * *", "2018-09-14T14:25:00Z", "2018-09-14T14:26:00Z");
TestNext("0 */20 * * * *", "2018-09-14T14:24:00Z", "2018-09-14T14:40:00Z");
TestNext("* * * * * *", "2012-07-01T09:00:00Z", "2012-07-01T09:00:01Z");
TestNext("* * * * * *", "2012-12-01T09:00:58Z", "2012-12-01T09:00:59Z");
TestNext("10 * * * * *", "2012-12-01T09:42:09Z", "2012-12-01T09:42:10Z");
TestNext("11 * * * * *", "2012-12-01T09:42:10Z", "2012-12-01T09:42:11Z");
TestNext("10 * * * * *", "2012-12-01T09:42:10Z", "2012-12-01T09:43:10Z");
TestNext("10-15 * * * * *", "2012-12-01T09:42:09Z", "2012-12-01T09:42:10Z");
TestNext("10-15 * * * * *", "2012-12-01T21:42:14Z", "2012-12-01T21:42:15Z");
TestNext("0 * * * * *", "2012-12-01T21:10:42Z", "2012-12-01T21:11:00Z");
TestNext("0 * * * * *", "2012-12-01T21:11:00Z", "2012-12-01T21:12:00Z");
TestNext("0 11 * * * *", "2012-12-01T21:10:42Z", "2012-12-01T21:11:00Z");
TestNext("0 10 * * * *", "2012-12-01T21:11:00Z", "2012-12-01T22:10:00Z");
TestNext("0 0 * * * *", "2012-09-30T11:01:00Z", "2012-09-30T12:00:00Z");
TestNext("0 0 * * * *", "2012-09-30T12:00:00Z", "2012-09-30T13:00:00Z");
TestNext("0 0 * * * *", "2012-09-10T23:01:00Z", "2012-09-11T00:00:00Z");
TestNext("0 0 * * * *", "2012-09-11T00:00:00Z", "2012-09-11T01:00:00Z");
TestNext("0 0 0 * * *", "2012-09-01T14:42:43Z", "2012-09-02T00:00:00Z");
TestNext("0 0 0 * * *", "2012-09-02T00:00:00Z", "2012-09-03T00:00:00Z");
TestNext("* * * 10 * *", "2012-10-09T15:12:42Z", "2012-10-10T00:00:00Z");
TestNext("* * * 10 * *", "2012-10-11T15:12:42Z", "2012-11-10T00:00:00Z");
TestNext("0 0 0 * * *", "2012-09-30T15:12:42Z", "2012-10-01T00:00:00Z");
TestNext("0 0 0 * * *", "2012-10-01T00:00:00Z", "2012-10-02T00:00:00Z");
TestNext("0 0 0 * * *", "2012-08-30T15:12:42Z", "2012-08-31T00:00:00Z");
TestNext("0 0 0 * * *", "2012-08-31T00:00:00Z", "2012-09-01T00:00:00Z");
TestNext("0 0 0 * * *", "2012-10-30T15:12:42Z", "2012-10-31T00:00:00Z");
TestNext("0 0 0 * * *", "2012-10-31T00:00:00Z", "2012-11-01T00:00:00Z");
TestNext("0 0 0 1 * *", "2012-10-30T15:12:42Z", "2012-11-01T00:00:00Z");
TestNext("0 0 0 1 * *", "2012-11-01T00:00:00Z", "2012-12-01T00:00:00Z");
TestNext("0 0 0 1 * *", "2010-12-31T15:12:42Z", "2011-01-01T00:00:00Z");
TestNext("0 0 0 1 * *", "2011-01-01T00:00:00Z", "2011-02-01T00:00:00Z");
TestNext("0 0 0 31 * *", "2011-10-30T15:12:42Z", "2011-10-31T00:00:00Z");
TestNext("0 0 0 1 * *", "2011-10-30T15:12:42Z", "2011-11-01T00:00:00Z");
TestNext("* * * * * 2", "2010-10-25T15:12:42Z", "2010-10-26T00:00:00Z");
TestNext("* * * * * 2", "2010-10-20T15:12:42Z", "2010-10-26T00:00:00Z");
TestNext("* * * * * 2", "2010-10-27T15:12:42Z", "2010-11-02T00:00:00Z");
TestNext("55 5 * * * *", "2010-10-27T15:04:54Z", "2010-10-27T15:05:55Z");
TestNext("55 5 * * * *", "2010-10-27T15:05:55Z", "2010-10-27T16:05:55Z");
TestNext("55 * 10 * * *", "2010-10-27T09:04:54Z", "2010-10-27T10:00:55Z");
TestNext("55 * 10 * * *", "2010-10-27T10:00:55Z", "2010-10-27T10:01:55Z");
TestNext("* 5 10 * * *", "2010-10-27T09:04:55Z", "2010-10-27T10:05:00Z");
TestNext("* 5 10 * * *", "2010-10-27T10:05:00Z", "2010-10-27T10:05:01Z");
TestNext("55 * * 3 * *", "2010-10-02T10:05:54Z", "2010-10-03T00:00:55Z");
TestNext("55 * * 3 * *", "2010-10-03T00:00:55Z", "2010-10-03T00:01:55Z");
TestNext("* * * 3 11 *", "2010-10-02T14:42:55Z", "2010-11-03T00:00:00Z");
TestNext("* * * 3 11 *", "2010-11-03T00:00:00Z", "2010-11-03T00:00:01Z");
TestNext("0 0 0 29 2 *", "2007-02-10T14:42:55Z", "2008-02-29T00:00:00Z");
TestNext("0 0 0 29 2 *", "2008-02-29T00:00:00Z", "2012-02-29T00:00:00Z");
TestNext("0 0 7 ? * MON-FRI", "2009-09-26T00:42:55Z", "2009-09-28T07:00:00Z");
TestNext("0 0 7 ? * MON-FRI", "2009-09-28T07:00:00Z", "2009-09-29T07:00:00Z");
TestNext("0 0 7 ? * 6-0", "2024-05-02T15:37:04Z", "2024-05-04T07:00:00Z");
TestNext("0 30 23 30 1/3 ?", "2010-12-30T00:00:00Z", "2011-01-30T23:30:00Z");
TestNext("0 30 23 30 1/3 ?", "2011-01-30T23:30:00Z", "2011-04-30T23:30:00Z");
TestNext("0 30 23 30 1/3 ?", "2011-04-30T23:30:00Z", "2011-07-30T23:30:00Z");
TestNext("* * * * * *", "2020-12-31T23:59:59Z", "2021-01-01T00:00:00Z");
TestNext("0 0 * * * *", "2020-02-28T23:00:00Z", "2020-02-29T00:00:00Z");
TestNext("0 0 0 * * *", "2020-02-29T01:02:03Z", "2020-03-01T00:00:00Z");
TestNext("0 0 0 ? 11-12 *", "2022-05-31T00:00:00Z", "2022-11-01T00:00:00Z");
TestNext("0 0 0 ? 11-12 *", "2022-07-31T00:00:00Z", "2022-11-01T00:00:00Z");
TestNext("0 0 0 ? 11-12 *", "2022-08-31T00:00:00Z", "2022-11-01T00:00:00Z");
TestNext("0 0 0 ? 11-12 *", "2022-10-31T00:00:00Z", "2022-11-01T00:00:00Z");
TestNext("0 0 0 ? 6-7 *", "2022-05-31T00:00:00Z", "2022-06-01T00:00:00Z");
TestNext("0 0 0 ? 8-9 *", "2022-07-31T00:00:00Z", "2022-08-01T00:00:00Z");
TestNext("0 0 0 ? 9-10 *", "2022-08-31T00:00:00Z", "2022-09-01T00:00:00Z");
TestNext("0 0 0 ? 2-3 *", "2022-01-31T00:00:00Z", "2022-02-01T00:00:00Z");
TestNext("0 0 0 ? 4-5 *", "2022-03-31T00:00:00Z", "2022-04-01T00:00:00Z");
TestNext("* * * 29 2 *", "2021-12-07T12:00:00Z", "2024-02-29T00:00:00Z");
}
Y_UNIT_TEST(TypedDates) {
TestNext("@annually", "2021-12-07T12:00:00Z", "2022-01-01T00:00:00Z");
TestNext("@yearly", "2021-12-07T12:00:00Z", "2022-01-01T00:00:00Z");
TestNext("@monthly", "2021-11-07T12:23:00Z", "2021-12-01T00:00:00Z");
TestNext("@weekly", "2024-04-22T16:05:32Z", "2024-04-28T00:00:00Z");
TestNext("@daily", "2024-04-22T16:05:32Z", "2024-04-23T00:00:00Z");
TestNext("@hourly", "2021-12-07T12:20:07Z", "2021-12-07T13:00:00Z");
TestNext("@minutely", "2024-04-22T16:05:32Z", "2024-04-22T16:06:00Z");
TestNext("@secondly", "2021-12-07T12:00:00Z", "2021-12-07T12:00:01Z");
}
}
Y_UNIT_TEST_SUITE(TestPrev) {
Y_UNIT_TEST(DifferentCases) {
TestPrev("* 15 11 * * *", "2019-03-09T11:43:00Z", "2019-03-09T11:15:59Z");
TestPrev("*/15 * 1-4 * * *", "2012-07-01T09:53:50Z", "2012-07-01T04:59:45Z");
TestPrev("*/15 * 1-4 * * *", "2012-07-01T01:00:14Z", "2012-07-01T01:00:00Z");
TestPrev("*/15 * 1-4 * * *", "2012-07-01T01:00:00Z", "2012-06-30T04:59:45Z");
TestPrev("* * * * * *", "2012-07-01T09:00:00Z", "2012-07-01T08:59:59Z");
TestPrev("* * * * * *", "2021-01-01T00:00:00Z", "2020-12-31T23:59:59Z");
TestPrev("0 0 * * * *", "2020-02-29T00:00:00Z", "2020-02-28T23:00:00Z");
TestPrev("0 0 0 * * *", "2020-03-01T00:00:00Z", "2020-02-29T00:00:00Z");
TestPrev("0 0 * * * *", "2020-03-01T00:00:00Z", "2020-02-29T23:00:00Z");
TestPrev("* * * 29 2 *", "2021-12-07T12:00:00Z", "2020-02-29T23:59:59Z");
TestPrev("* * * 1 2 *", "2023-11-01T00:00:00Z", "2023-02-01T23:59:59Z");
TestPrev("* * * 2 2 *", "2023-11-01T00:00:00Z", "2023-02-02T23:59:59Z");
TestPrev("* * * 3 2 *", "2023-11-01T00:00:00Z", "2023-02-03T23:59:59Z");
TestPrev("* * * 4 2 *", "2023-11-01T00:00:00Z", "2023-02-04T23:59:59Z");
TestPrev("* * * 1 4 *", "2023-10-01T00:00:00Z", "2023-04-01T23:59:59Z");
TestPrev("* * * 2 4 *", "2023-10-01T00:00:00Z", "2023-04-02T23:59:59Z");
TestPrev("* * * 3 4 *", "2023-10-01T00:00:00Z", "2023-04-03T23:59:59Z");
TestPrev("* * * 4 4 *", "2023-10-01T00:00:00Z", "2023-04-04T23:59:59Z");
TestPrev("0 0 20 1 2 *", "2022-12-30T08:10:23Z", "2022-02-01T20:00:00Z");
TestPrev("0 0 20 2 2 *", "2022-12-30T08:10:23Z", "2022-02-02T20:00:00Z");
TestPrev("0 0 20 3 2 *", "2022-12-30T08:10:23Z", "2022-02-03T20:00:00Z");
TestPrev("0 0 20 1 2 *", "2022-12-31T08:10:23Z", "2022-02-01T20:00:00Z");
TestPrev("0 0 20 2 2 *", "2022-12-31T08:10:23Z", "2022-02-02T20:00:00Z");
TestPrev("0 0 20 3 2 *", "2022-12-31T08:10:23Z", "2022-02-03T20:00:00Z");
TestPrev("0 0 20 1 2 *", "2023-01-01T08:10:23Z", "2022-02-01T20:00:00Z");
TestPrev("0 0 20 2 2 *", "2023-01-01T08:10:23Z", "2022-02-02T20:00:00Z");
TestPrev("0 0 20 3 2 *", "2023-01-01T08:10:23Z", "2022-02-03T20:00:00Z");
TestPrev("0 0 17 * 2 2-4", "2023-08-31T18:00:00Z", "2023-02-28T17:00:00Z");
TestPrev("0 0 17 * 2 2-4", "2023-09-01T18:00:00Z", "2023-02-28T17:00:00Z");
TestPrev("0 0 17 * 2 2-4", "2023-09-02T18:00:00Z", "2023-02-28T17:00:00Z");
TestPrev("0 0 17 * 2 2-4", "2023-09-03T18:00:00Z", "2023-02-28T17:00:00Z");
TestPrev("0 0 17 * 2 2-4", "2023-09-04T18:00:00Z", "2023-02-28T17:00:00Z");
TestPrev("0 0 17 * 2 2-4", "2023-09-05T18:00:00Z", "2023-02-28T17:00:00Z");
TestPrev("0 0 17 * 3 1-5", "2023-03-02T17:00:00Z", "2023-03-01T17:00:00Z");
TestPrev("0 0 17 * 3 1-5", "2023-03-02T17:00:01Z", "2023-03-02T17:00:00Z");
TestPrev("0 0 17 * 3 1-5", "2023-03-02T18:00:00Z", "2023-03-02T17:00:00Z");
TestPrev("0 0 17 * 3 1-5", "2023-03-03T18:00:00Z", "2023-03-03T17:00:00Z");
TestPrev("0 0 17 * 3 1-5", "2023-03-04T18:00:00Z", "2023-03-03T17:00:00Z");
TestPrev("0 0 17 * 3 1-5", "2023-03-05T18:00:00Z", "2023-03-03T17:00:00Z");
TestPrev("0 0 17 * 3 1-5", "2023-03-06T18:00:00Z", "2023-03-06T17:00:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-05T18:00:00Z", "2023-04-29T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-06T09:29:59Z", "2023-04-29T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-06T09:30:00Z", "2023-04-29T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-06T09:30:01Z", "2024-04-06T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-06T18:00:00Z", "2024-04-06T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-07T18:00:00Z", "2024-04-06T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-26T18:00:00Z", "2024-04-20T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-27T18:00:00Z", "2024-04-27T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-04-28T18:00:00Z", "2024-04-27T09:30:00Z");
TestPrev("0 30 9 * 4 6", "2024-05-01T18:00:00Z", "2024-04-27T09:30:00Z");
TestPrev("0 30 11 * * 6", "2020-02-27T10:00:00Z", "2020-02-22T11:30:00Z");
TestPrev("0 30 11 * * 6", "2020-02-28T10:00:00Z", "2020-02-22T11:30:00Z");
TestPrev("0 30 11 * * 6", "2020-02-29T10:00:00Z", "2020-02-22T11:30:00Z");
TestPrev("0 30 11 * * 6", "2020-02-29T11:31:00Z", "2020-02-29T11:30:00Z");
TestPrev("0 30 11 * * 6", "2020-03-01T10:00:00Z", "2020-02-29T11:30:00Z");
TestPrev("0 30 11 * * 6", "2020-03-01T12:00:00Z", "2020-02-29T11:30:00Z");
TestPrev("0 0 10 * * *", "2020-02-29T09:59:59Z", "2020-02-28T10:00:00Z");
TestPrev("0 0 10 * * *", "2020-02-29T10:00:00Z", "2020-02-28T10:00:00Z");
TestPrev("0 0 10 * * *", "2020-02-29T10:00:01Z", "2020-02-29T10:00:00Z");
TestPrev("0 0 10 * * *", "2022-02-28T09:59:59Z", "2022-02-27T10:00:00Z");
TestPrev("0 0 10 * * *", "2022-02-28T10:00:00Z", "2022-02-27T10:00:00Z");
TestPrev("0 0 10 * * *", "2022-02-28T10:00:01Z", "2022-02-28T10:00:00Z");
TestPrev("0 0 10 * * *", "2022-12-31T09:59:59Z", "2022-12-30T10:00:00Z");
TestPrev("0 0 10 * * *", "2022-12-31T10:00:00Z", "2022-12-30T10:00:00Z");
TestPrev("0 0 10 * * *", "2022-12-31T10:00:01Z", "2022-12-31T10:00:00Z");
TestPrev("0 0 10 * * *", "2022-12-31T23:59:59Z", "2022-12-31T10:00:00Z");
TestPrev("0 0 10 * * *", "2023-01-01T00:00:00Z", "2022-12-31T10:00:00Z");
TestPrev("0 0 10 * * *", "2023-01-01T00:00:01Z", "2022-12-31T10:00:00Z");
TestPrev("0 0 10 * * *", "2023-01-01T09:59:59Z", "2022-12-31T10:00:00Z");
TestPrev("0 0 10 * * *", "2023-01-01T10:00:00Z", "2022-12-31T10:00:00Z");
TestPrev("0 0 10 * * *", "2023-01-01T10:00:01Z", "2023-01-01T10:00:00Z");
TestPrev("30 50 23 20,21,22 * *", "2023-07-01T12:34:56Z", "2023-06-22T23:50:30Z");
TestPrev("30 50 23 20,21,22 * *", "2023-07-19T12:34:56Z", "2023-06-22T23:50:30Z");
TestPrev("30 50 23 20,21,22 * *", "2023-07-20T12:34:56Z", "2023-06-22T23:50:30Z");
TestPrev("30 50 23 20,21,22 * *", "2023-07-21T12:34:56Z", "2023-07-20T23:50:30Z");
TestPrev("30 50 23 20,21,22 * *", "2023-07-22T12:34:56Z", "2023-07-21T23:50:30Z");
TestPrev("30 50 23 20,21,22 * *", "2023-07-23T12:34:56Z", "2023-07-22T23:50:30Z");
}
}
Y_UNIT_TEST_SUITE(AliceBasicUsageExamples) {
Y_UNIT_TEST(First) {
TCronExpression cronConverter("*/10 * * * *");
TestNextCron(&cronConverter, "2023-07-20T12:34:56Z", "2023-07-20T12:40:00Z");
TestNextCron(&cronConverter, "2023-07-20T12:40:00Z", "2023-07-20T12:50:00Z");
TestNextCron(&cronConverter, "2023-07-20T23:50:00Z", "2023-07-21T00:00:00Z");
TestPrevCron(&cronConverter, "2023-07-20T23:50:00Z", "2023-07-20T23:40:00Z");
TestPrevCron(&cronConverter, "2023-07-20T00:00:01Z", "2023-07-20T00:00:00Z");
TestPrevCron(&cronConverter, "2023-07-20T00:00:00Z", "2023-07-19T23:50:00Z");
}
Y_UNIT_TEST(Second) {
TCronExpression cronConverter("0 6 * * 7");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-28T06:00:00Z");
TestNextCron(&cronConverter, "2024-04-21T16:05:32Z", "2024-04-28T06:00:00Z");
TestNextCron(&cronConverter, "2024-04-21T01:01:32Z", "2024-04-21T06:00:00Z");
TestPrevCron(&cronConverter, "2024-04-30T23:50:00Z", "2024-04-28T06:00:00Z");
TestPrevCron(&cronConverter, "2024-04-28T06:00:00Z", "2024-04-21T06:00:00Z");
TestPrevCron(&cronConverter, "2024-04-21T06:00:01Z", "2024-04-21T06:00:00Z");
}
Y_UNIT_TEST(Third) {
TCronExpression cronConverter("0 0 1 1 *");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2025-01-01T00:00:00Z");
TestNextCron(&cronConverter, "2024-01-01T00:00:00Z", "2025-01-01T00:00:00Z");
TestNextCron(&cronConverter, "2024-12-31T23:59:59Z", "2025-01-01T00:00:00Z");
TestPrevCron(&cronConverter, "2025-04-22T16:05:32Z", "2025-01-01T00:00:00Z");
TestPrevCron(&cronConverter, "2025-01-01T00:00:01Z", "2025-01-01T00:00:00Z");
TestPrevCron(&cronConverter, "2026-01-01T00:00:00Z", "2025-01-01T00:00:00Z");
}
Y_UNIT_TEST(Fourth) {
TCronExpression cronConverter("30 15 * * 1-5");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-23T15:30:00Z");
TestNextCron(&cronConverter, "2024-04-20T16:05:32Z", "2024-04-22T15:30:00Z");
TestNextCron(&cronConverter, "2024-03-30T11:05:32Z", "2024-04-01T15:30:00Z");
TestPrevCron(&cronConverter, "2024-04-23T16:05:32Z", "2024-04-23T15:30:00Z");
TestPrevCron(&cronConverter, "2024-04-28T16:05:32Z", "2024-04-26T15:30:00Z");
TestPrevCron(&cronConverter, "2024-04-02T11:05:32Z", "2024-04-01T15:30:00Z");
}
Y_UNIT_TEST(Fifth) {
TCronExpression cronConverter("0 22 * * *");
TestNextCron(&cronConverter, "2024-04-20T16:05:32Z", "2024-04-20T22:00:00Z");
TestNextCron(&cronConverter, "2024-12-31T22:00:00Z", "2025-01-01T22:00:00Z");
TestNextCron(&cronConverter, "2024-04-20T00:05:32Z", "2024-04-20T22:00:00Z");
TestPrevCron(&cronConverter, "2024-04-21T16:05:32Z", "2024-04-20T22:00:00Z");
TestPrevCron(&cronConverter, "2025-01-01T22:00:00Z", "2024-12-31T22:00:00Z");
TestPrevCron(&cronConverter, "2024-04-20T23:05:32Z", "2024-04-20T22:00:00Z");
}
Y_UNIT_TEST(Sixth) {
TCronExpression cronConverter("0 12 L * *");
TestNextCron(&cronConverter, "2024-04-20T16:05:32Z", "2024-04-30T12:00:00Z");
TestNextCron(&cronConverter, "2024-02-20T12:05:43Z", "2024-02-29T12:00:00Z");
TestNextCron(&cronConverter, "2021-02-01T22:05:32Z", "2021-02-28T12:00:00Z");
TestPrevCron(&cronConverter, "2024-05-20T16:05:32Z", "2024-04-30T12:00:00Z");
TestPrevCron(&cronConverter, "2024-03-20T12:05:43Z", "2024-02-29T12:00:00Z");
TestPrevCron(&cronConverter, "2021-03-01T22:05:32Z", "2021-02-28T12:00:00Z");
}
Y_UNIT_TEST(Seventh) {
TCronExpression cronConverter("0 8 * * 1-5");
TestNextCron(&cronConverter, "2024-04-22T07:59:59Z", "2024-04-22T08:00:00Z");
TestNextCron(&cronConverter, "2024-04-20T07:59:59Z", "2024-04-22T08:00:00Z");
TestNextCron(&cronConverter, "2024-04-22T14:29:54Z", "2024-04-23T08:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T08:00:01Z", "2024-04-22T08:00:00Z");
TestPrevCron(&cronConverter, "2024-04-23T07:59:59Z", "2024-04-22T08:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T06:29:54Z", "2024-04-19T08:00:00Z");
}
Y_UNIT_TEST(Eigths) {
TCronExpression cronConverter("0 */2 * * 7");
TestNextCron(&cronConverter, "2024-04-21T07:59:59Z", "2024-04-21T08:00:00Z");
TestNextCron(&cronConverter, "2024-04-21T14:59:59Z", "2024-04-21T16:00:00Z");
TestNextCron(&cronConverter, "2024-04-16T21:03:25Z", "2024-04-21T00:00:00Z");
}
Y_UNIT_TEST(Ninth) {
TCronExpression cronConverter("45 21 5 * *");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-05-05T21:45:00Z");
TestNextCron(&cronConverter, "2024-04-05T22:05:32Z", "2024-05-05T21:45:00Z");
TestNextCron(&cronConverter, "2024-04-05T16:05:32Z", "2024-04-05T21:45:00Z");
TestPrevCron(&cronConverter, "2024-05-22T16:05:32Z", "2024-05-05T21:45:00Z");
TestPrevCron(&cronConverter, "2024-05-05T22:05:32Z", "2024-05-05T21:45:00Z");
TestPrevCron(&cronConverter, "2024-05-05T16:05:32Z", "2024-04-05T21:45:00Z");
}
Y_UNIT_TEST(Tenth) {
TCronExpression cronConverter("0 3 * * 1-6");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-23T03:00:00Z");
TestNextCron(&cronConverter, "2024-04-23T02:05:32Z", "2024-04-23T03:00:00Z");
TestNextCron(&cronConverter, "2024-04-21T02:05:32Z", "2024-04-22T03:00:00Z");
TestNextCron(&cronConverter, "2024-04-20T12:05:32Z", "2024-04-22T03:00:00Z");
TestPrevCron(&cronConverter, "2024-04-23T16:05:32Z", "2024-04-23T03:00:00Z");
TestPrevCron(&cronConverter, "2024-04-23T02:05:32Z", "2024-04-22T03:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T02:05:32Z", "2024-04-20T03:00:00Z");
TestPrevCron(&cronConverter, "2024-04-21T12:05:32Z", "2024-04-20T03:00:00Z");
}
Y_UNIT_TEST(Eleventh) {
TCronExpression cronConverter("0 17 * * 3");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-24T17:00:00Z");
TestNextCron(&cronConverter, "2024-04-27T16:05:32Z", "2024-05-01T17:00:00Z");
TestNextCron(&cronConverter, "2024-04-24T17:00:00Z", "2024-05-01T17:00:00Z");
TestNextCron(&cronConverter, "2023-12-28T19:45:32Z", "2024-01-03T17:00:00Z");
TestPrevCron(&cronConverter, "2024-05-01T16:05:32Z", "2024-04-24T17:00:00Z");
TestPrevCron(&cronConverter, "2024-05-01T18:05:32Z", "2024-05-01T17:00:00Z");
TestPrevCron(&cronConverter, "2024-05-01T17:00:00Z", "2024-04-24T17:00:00Z");
TestPrevCron(&cronConverter, "2024-01-02T19:45:32Z", "2023-12-27T17:00:00Z");
}
Y_UNIT_TEST(Twelvth) {
TCronExpression cronConverter("0 10,22 * * *");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-22T22:00:00Z");
TestNextCron(&cronConverter, "2024-04-22T22:05:32Z", "2024-04-23T10:00:00Z");
TestNextCron(&cronConverter, "2024-04-30T23:05:32Z", "2024-05-01T10:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T23:05:32Z", "2024-04-22T22:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T21:05:32Z", "2024-04-22T10:00:00Z");
TestPrevCron(&cronConverter, "2024-05-01T06:05:32Z", "2024-04-30T22:00:00Z");
}
Y_UNIT_TEST(Thirteenth) {
TCronExpression cronConverter("* * 1-5 * *");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-05-01T00:00:00Z");
TestNextCron(&cronConverter, "2024-04-04T16:05:32Z", "2024-04-04T16:06:00Z");
TestNextCron(&cronConverter, "2024-04-04T16:05:00Z", "2024-04-04T16:06:00Z");
TestNextCron(&cronConverter, "2024-04-05T23:59:21Z", "2024-05-01T00:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-05T23:59:00Z");
TestPrevCron(&cronConverter, "2024-04-04T16:05:32Z", "2024-04-04T16:05:00Z");
TestPrevCron(&cronConverter, "2024-04-04T16:05:00Z", "2024-04-04T16:04:00Z");
TestPrevCron(&cronConverter, "2024-04-01T00:00:00Z", "2024-03-05T23:59:00Z");
}
Y_UNIT_TEST(Fourteenth) {
TCronExpression cronConverter("*/15 * * * 1-5");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-22T16:15:00Z");
TestNextCron(&cronConverter, "2024-04-22T16:15:00Z", "2024-04-22T16:30:00Z");
TestNextCron(&cronConverter, "2024-04-20T16:05:32Z", "2024-04-22T00:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-22T16:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T16:15:00Z", "2024-04-22T16:00:00Z");
TestPrevCron(&cronConverter, "2024-04-20T16:05:32Z", "2024-04-19T23:45:00Z");
}
Y_UNIT_TEST(Fifteenth) {
TCronExpression cronConverter("0 0 * * 6");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-27T00:00:00Z");
TestNextCron(&cronConverter, "2024-04-27T00:00:00Z", "2024-05-04T00:00:00Z");
TestNextCron(&cronConverter, "2024-04-27T16:05:32Z", "2024-05-04T00:00:00Z");
TestPrevCron(&cronConverter, "2024-05-02T16:05:32Z", "2024-04-27T00:00:00Z");
TestPrevCron(&cronConverter, "2024-05-04T00:00:00Z", "2024-04-27T00:00:00Z");
TestPrevCron(&cronConverter, "2024-04-27T16:05:32Z", "2024-04-27T00:00:00Z");
}
Y_UNIT_TEST(Sixteenth) {
TCronExpression cronConverter("20 14 * * 0-5");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-23T14:20:00Z");
TestNextCron(&cronConverter, "2024-04-22T11:05:32Z", "2024-04-22T14:20:00Z");
TestNextCron(&cronConverter, "2024-04-20T02:05:32Z", "2024-04-21T14:20:00Z");
TestNextCron(&cronConverter, "2024-04-19T14:20:00Z", "2024-04-21T14:20:00Z");
TestPrevCron(&cronConverter, "2024-04-24T11:05:32Z", "2024-04-23T14:20:00Z");
TestPrevCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-22T14:20:00Z");
TestPrevCron(&cronConverter, "2024-04-21T02:05:32Z", "2024-04-19T14:20:00Z");
TestPrevCron(&cronConverter, "2024-04-21T14:20:00Z", "2024-04-19T14:20:00Z");
}
Y_UNIT_TEST(Seventeenth) {
TCronExpression cronConverter("0 9,18 * * *");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-22T18:00:00Z");
TestNextCron(&cronConverter, "2024-04-22T22:05:32Z", "2024-04-23T09:00:00Z");
TestNextCron(&cronConverter, "2024-04-30T23:05:32Z", "2024-05-01T09:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T18:00:00Z", "2024-04-22T09:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T08:05:32Z", "2024-04-21T18:00:00Z");
TestPrevCron(&cronConverter, "2024-05-01T06:05:32Z", "2024-04-30T18:00:00Z");
}
Y_UNIT_TEST(Eighteenth) {
TCronExpression cronConverter("*/5 10 * * *");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-23T10:00:00Z");
TestNextCron(&cronConverter, "2024-04-22T10:05:32Z", "2024-04-22T10:10:00Z");
TestNextCron(&cronConverter, "2024-04-22T10:15:00Z", "2024-04-22T10:20:00Z");
TestNextCron(&cronConverter, "2024-04-22T10:55:23Z", "2024-04-23T10:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-22T10:55:00Z");
TestPrevCron(&cronConverter, "2024-04-22T10:10:32Z", "2024-04-22T10:10:00Z");
TestPrevCron(&cronConverter, "2024-04-22T10:25:00Z", "2024-04-22T10:20:00Z");
TestPrevCron(&cronConverter, "2024-04-23T08:55:23Z", "2024-04-22T10:55:00Z");
}
Y_UNIT_TEST(Nineteenth) {
TCronExpression cronConverter("30 7 * * 2,4");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-23T07:30:00Z");
TestNextCron(&cronConverter, "2024-04-23T16:05:32Z", "2024-04-25T07:30:00Z");
TestNextCron(&cronConverter, "2024-04-25T16:05:32Z", "2024-04-30T07:30:00Z");
TestNextCron(&cronConverter, "2024-04-23T04:05:32Z", "2024-04-23T07:30:00Z");
TestPrevCron(&cronConverter, "2024-04-24T16:05:32Z", "2024-04-23T07:30:00Z");
TestPrevCron(&cronConverter, "2024-04-29T16:05:32Z", "2024-04-25T07:30:00Z");
TestPrevCron(&cronConverter, "2024-04-30T16:05:32Z", "2024-04-30T07:30:00Z");
TestPrevCron(&cronConverter, "2024-04-23T04:05:32Z", "2024-04-18T07:30:00Z");
}
Y_UNIT_TEST(Twentieth) {
TCronExpression cronConverter("0 0 1,15 * *");
TestNextCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-05-01T00:00:00Z");
TestNextCron(&cronConverter, "2024-04-15T00:00:00Z", "2024-05-01T00:00:00Z");
TestNextCron(&cronConverter, "2024-04-30T23:59:59Z", "2024-05-01T00:00:00Z");
TestPrevCron(&cronConverter, "2024-04-22T16:05:32Z", "2024-04-15T00:00:00Z");
TestPrevCron(&cronConverter, "2024-04-15T00:00:00Z", "2024-04-01T00:00:00Z");
TestPrevCron(&cronConverter, "2024-04-02T00:00:00Z", "2024-04-01T00:00:00Z");
}
}
Y_UNIT_TEST_SUITE(InvalidTests) {
Y_UNIT_TEST(InvalidFieldsAmount) {
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression(""), yexception, "Invalid empty expression");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression(" "), yexception, "Invalid number of fields, expression must consist of 5-7 fields but has: 0");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression("* * * * * * * *"), yexception, "Invalid number of fields, expression must consist of 5-7 fields but has: 8");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression("1 1 1 "), yexception, "Invalid number of fields, expression must consist of 5-7 fields but has: 3");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression(" C S K A "), yexception, "Invalid number of fields, expression must consist of 5-7 fields but has: 4");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression(" chemp i on "), yexception, "Invalid number of fields, expression must consist of 5-7 fields but has: 3");
}
Y_UNIT_TEST(InvalidTypedCrons) {
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression("@@@@"), yexception, "Unknown typed cron");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression("@ */2 * * 3 *"), yexception, "Unknown typed cron");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression("@everyfriday13"), yexception, "Unknown typed cron");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression("@milisecondly"), yexception, "Unknown typed cron");
UNIT_ASSERT_EXCEPTION_CONTAINS(TCronExpression("@reboot"), yexception, "@reboot not implemented");
}
Y_UNIT_TEST(InvalidCrons) {
UNIT_ASSERT_EXCEPTION(TCronExpression("1- * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("-4/3 * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("1-100 * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("-5-30/4 * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * * fRi-MO"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * * FR"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("0 0 1,15 * W"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("0 W 1,15 * W"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("W * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* W * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * W * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * W *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * * W"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("L * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* L * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * L * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * L *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * 13 *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("77 * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * -1 * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * 32 2 * 2020"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * * 8"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * * * 1969"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("0 0 1,15 * 20492049"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("5-2 0 1,15 * W"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * * * 2021-2019"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * -4 *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* */-2 * * W *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("*/0.5 * * * W *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * LW-1 * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("radio goo goo radio gaa gaa"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * 23-28 * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("*/0 1 * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("/5 * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* 1 1 0 * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * * * 3050"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("60 * * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* 60 * * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * 24 * * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * 32 * * *"), yexception);
UNIT_ASSERT_EXCEPTION(TCronExpression("* * * * 13 * *"), yexception);
}
Y_UNIT_TEST(InvalidRequestInPastOrFuture) {
TCronExpression cronConverter("0 0 1,15 * * * 2020");
TestNextCronBadRequest(&cronConverter, "2030-02-22T16:05:32Z");
TestNextCronBadRequest(&cronConverter, "2020-12-31T15:00:00Z");
TestPrevCronBadRequest(&cronConverter, "2020-01-01T01:00:00Z");
TestPrevCronBadRequest(&cronConverter, "1970-02-22T16:05:32Z");
}
Y_UNIT_TEST(InvalidRequestDoesNotExist) {
TCronExpression cronConverter("0 0 7 30 2 * *");
TestNextCronBadRequest(&cronConverter, "2030-02-22T16:05:32Z");
}
}
} // namespace
|