8
8
"math"
9
9
"os"
10
10
"regexp"
11
+ "strconv"
12
+ "time"
11
13
12
14
"github.com/foxglove/mcap/go/cli/mcap/utils"
13
15
"github.com/foxglove/mcap/go/mcap"
@@ -22,6 +24,8 @@ type filterFlags struct {
22
24
endSec uint64
23
25
startNano uint64
24
26
endNano uint64
27
+ start string
28
+ end string
25
29
includeMetadata bool
26
30
includeAttachments bool
27
31
outputCompression string
@@ -41,20 +45,51 @@ type filterOpts struct {
41
45
chunkSize int64
42
46
}
43
47
48
+ // parseDateOrNanos parses a string containing either an RFC3339-formatted date with timezone
49
+ // or a decimal number of nanoseconds. It returns a uint64 timestamp in nanoseconds.
50
+ func parseDateOrNanos (dateOrNanos string ) (uint64 , error ) {
51
+ intNanos , err := strconv .ParseUint (dateOrNanos , 10 , 64 )
52
+ if err == nil {
53
+ return intNanos , nil
54
+ }
55
+ date , err := time .Parse (time .RFC3339 , dateOrNanos )
56
+ if err != nil {
57
+ return 0 , err
58
+ }
59
+ return uint64 (date .UnixNano ()), nil
60
+ }
61
+
62
+ // parseTimestampArgs implements the semantics for setting start and end times in the CLI.
63
+ // a non-default value in `dateOrNanos` overrides `nanoseconds`, which overrides `seconds`.
64
+ func parseTimestampArgs (dateOrNanos string , nanoseconds uint64 , seconds uint64 ) (uint64 , error ) {
65
+ if dateOrNanos != "" {
66
+ return parseDateOrNanos (dateOrNanos )
67
+ }
68
+ if nanoseconds != 0 {
69
+ return nanoseconds , nil
70
+ }
71
+ return seconds * 1e9 , nil
72
+ }
73
+
44
74
func buildFilterOptions (flags * filterFlags ) (* filterOpts , error ) {
45
75
opts := & filterOpts {
46
76
output : flags .output ,
47
77
includeMetadata : flags .includeMetadata ,
48
78
includeAttachments : flags .includeAttachments ,
49
79
}
50
- opts .start = flags .startNano
51
80
if flags .startSec > 0 {
52
81
opts .start = flags .startSec * 1e9
53
82
}
54
- opts . end = flags .endNano
55
- if flags . endSec > 0 {
56
- opts . end = flags . endSec * 1e9
83
+ start , err := parseTimestampArgs ( flags .start , flags . startNano , flags . startSec )
84
+ if err != nil {
85
+ return nil , fmt . Errorf ( "invalid start: %w" , err )
57
86
}
87
+ opts .start = start
88
+ end , err := parseTimestampArgs (flags .end , flags .endSec , flags .endNano )
89
+ if err != nil {
90
+ return nil , fmt .Errorf ("invalid end: %w" , err )
91
+ }
92
+ opts .end = end
58
93
if opts .end == 0 {
59
94
opts .end = math .MaxUint64
60
95
}
@@ -392,30 +427,43 @@ usage:
392
427
[]string {},
393
428
"messages with topic names matching this regex will be excluded, can be supplied multiple times" ,
394
429
)
430
+ start := filterCmd .PersistentFlags ().StringP (
431
+ "start" ,
432
+ "S" ,
433
+ "" ,
434
+ "only include messages logged at or after this time. Accepts integer nanoseconds or RFC3339-formatted date." ,
435
+ )
395
436
startSec := filterCmd .PersistentFlags ().Uint64P (
396
437
"start-secs" ,
397
438
"s" ,
398
439
0 ,
399
- "messages with log times after or equal to this timestamp will be included." ,
440
+ "only include messages logged at or after this time. Accepts integer seconds." +
441
+ "Ignored if `--start` or `--start-nsecs` are used." ,
442
+ )
443
+ startNano := filterCmd .PersistentFlags ().Uint64 (
444
+ "start-nsecs" ,
445
+ 0 ,
446
+ "deprecated, use --start. Only include messages logged at or after this time. Accepts integer nanoseconds." ,
447
+ )
448
+ end := filterCmd .PersistentFlags ().StringP (
449
+ "end" ,
450
+ "E" ,
451
+ "" ,
452
+ "Only include messages logged before this time. Accepts integer nanoseconds or RFC3339-formatted date." ,
400
453
)
401
454
endSec := filterCmd .PersistentFlags ().Uint64P (
402
455
"end-secs" ,
403
456
"e" ,
404
457
0 ,
405
- "messages with log times before timestamp will be included." ,
458
+ "only include messages logged before this time. Accepts integer seconds." +
459
+ "Ignored if `--end` or `--end-nsecs` are used." ,
406
460
)
407
- startNano := filterCmd .PersistentFlags ().Uint64P (
408
- "start-nsecs" ,
409
- "S" ,
410
- 0 ,
411
- "messages with log times after or equal to this nanosecond-precision timestamp will be included." ,
412
- )
413
- endNano := filterCmd .PersistentFlags ().Uint64P (
461
+ endNano := filterCmd .PersistentFlags ().Uint64 (
414
462
"end-nsecs" ,
415
- "E" ,
416
463
0 ,
417
- "messages with log times before nanosecond-precision timestamp will be included ." ,
464
+ "(Deprecated, use --end) Only include messages logged before this time. Accepts integer nanosconds ." ,
418
465
)
466
+
419
467
filterCmd .MarkFlagsMutuallyExclusive ("start-secs" , "start-nsecs" )
420
468
filterCmd .MarkFlagsMutuallyExclusive ("end-secs" , "end-nsecs" )
421
469
chunkSize := filterCmd .PersistentFlags ().Int64P ("chunk-size" , "" , 4 * 1024 * 1024 , "chunk size of output file" )
@@ -439,9 +487,11 @@ usage:
439
487
output : * output ,
440
488
includeTopics : * includeTopics ,
441
489
excludeTopics : * excludeTopics ,
490
+ start : * start ,
442
491
startSec : * startSec ,
443
- endSec : * endSec ,
444
492
startNano : * startNano ,
493
+ end : * end ,
494
+ endSec : * endSec ,
445
495
endNano : * endNano ,
446
496
chunkSize : * chunkSize ,
447
497
includeMetadata : * includeMetadata ,
0 commit comments