Parsing YouTube timestamps pasted by wasamasa on Tue Dec 1 22:20:07 2015
(use (only srfi-14 char-set:digit) comparse) (define digit (in char-set:digit)) (define (as-number parser) (bind (as-string parser) (lambda (s) (result (string->number s))))) (define digits (as-number (one-or-more digit))) (define timestamp-hours (followed-by digits (is #\h))) (define timestamp-minutes (followed-by digits (is #\m))) (define timestamp-seconds (followed-by digits (is #\s))) (define (maybe* parser) (any-of parser item)) (define timestamp (sequence* ((hours (maybe timestamp-hours)) (minutes (maybe timestamp-minutes)) (seconds timestamp-seconds)) (result (list (or hours 0) (or minutes 0) seconds)))) ;; expected: (0 0 1) ;; actual: (0 0 1) (parse timestamp "1s") ;; expected: (0 1 2) ;; actual: #f (parse timestamp "1m2s") ;; expected: (1 2 3) ;; actual: #f (parse timestamp "1h2m3s")
Fixed version pasted by wasamasa on Tue Dec 1 23:03:59 2015
(use (only srfi-14 char-set:digit) comparse) (define digit (in char-set:digit)) (define (as-number parser) (bind (as-string parser) (lambda (s) (result (string->number s))))) (define digits (as-number (one-or-more digit))) (define timestamp-hours (sequence* ((hours digits) (_ (is #\h))) (result hours))) (define timestamp-minutes (sequence* ((minutes digits) (_ (is #\m))) (result minutes))) (define timestamp-seconds (sequence* ((seconds digits) (_ (is #\s))) (result seconds))) (define timestamp (sequence* ((hours (maybe timestamp-hours)) (minutes (maybe timestamp-minutes)) (seconds timestamp-seconds)) (result (list (or hours 0) (or minutes 0) seconds)))) (define (parse-timestamp input) (parse (followed-by timestamp end-of-input) input)) (parse-timestamp "1s") ;=> (0 0 1) (parse-timestamp "1m2s") ;=> (0 1 2) (parse-timestamp "1h2m3s") ;=> (1 2 3)
Cleaned up version pasted by wasamasa on Tue Dec 1 23:16:21 2015
(define digit (in char-set:digit)) (define (as-number parser) (bind (as-string parser) (lambda (s) (result (string->number s))))) (define digits (as-number (one-or-more digit))) (define (number-unit suffix) (sequence* ((number digits) (_ (is suffix))) (result number))) (define timestamp-hours (number-unit #\h)) (define timestamp-minutes (number-unit #\m)) (define timestamp-seconds (number-unit #\s)) (define timestamp (sequence* ((hours (maybe timestamp-hours 0)) (minutes (maybe timestamp-minutes 0)) (seconds timestamp-seconds)) (result (list hours minutes seconds)))) (define (parse-timestamp input) (parse (followed-by timestamp end-of-input) input)) (parse-timestamp "1s") ;=> (0 0 1) (parse-timestamp "1m2s") ;=> (0 1 2) (parse-timestamp "1h2m3s") ;=> (1 2 3) (define (timestamp-to-seconds timestamp) (if timestamp (+ (* (car timestamp) 60 60) (* (cadr timestamp) 60) (list-ref timestamp 2)) 0)) (timestamp-to-seconds (parse-timestamp "1y")) ;=> 0 (timestamp-to-seconds (parse-timestamp "1s")) ;=> 1 (timestamp-to-seconds (parse-timestamp "1m2s")) ;=> 62 (timestamp-to-seconds (parse-timestamp "1h2m3s")) ;=> 3723
wasamasa: functional timestamp->seconds :-) pasted by DerGuteMoritz on Wed Dec 2 11:12:50 2015
(define (timestamp->seconds timestamp)
(fold + 0 (map * (or timestamp '()) '(3600 60 1))))
if you really like it functional ;-) pasted by florz on Wed Dec 2 12:15:07 2015
(define (parse-timestamp input)
(parse
(bind
(followed-by
(sequence
(map
(lambda (suffix p)
(maybe
(sequence* ((number (as-string (one-or-more (in char-set:digit))))
(_ (char-seq (symbol->string suffix))))
(result (* (string->number number) (expt 60 p))))
0))
'(h m s)
(reverse (iota 3))))
end-of-input)
(o result (cut fold + 0 <>)))
input))
or maybe slightly cleaner pasted by florz on Wed Dec 2 12:19:18 2015
(define (parse-timestamp input)
(let ((units '(h m s)))
(parse
(bind
(followed-by
(sequence
(map
(lambda (suffix p)
(maybe
(sequence* ((number (as-string (one-or-more (in char-set:digit))))
(_ (char-seq (symbol->string suffix))))
(result (* (string->number number) (expt 60 p))))
0))
units
(reverse (iota (length units)))))
end-of-input)
(o result (cut fold + 0 <>)))
input)))
Just match it pasted by wasamasa on Wed Dec 2 12:23:50 2015
(define timestamp->seconds
(match-lambda*
((#f) 0)
(((hours minutes seconds))
(+ (* hours 3600)
(* minutes 60)
seconds))))
use type checking (at runtime) pasted by C-Keen on Wed Dec 2 12:41:25 2015
(define timestamp->seconds
(match-lambda*
((#f) 0)
(((and (hours minutes seconds)
(? (lambda (l) (every number? l)))))
(+ (* hours 3600)
(* minutes 60)
seconds))))
using match-lambda and another way to do runtime type checks in a pattern added by DerGuteMoritz on Wed Dec 2 12:57:45 2015
(define timestamp->seconds
(match-lambda
(#f 0)
(((? number? hours) (? number? minutes) (? number? seconds))
(+ (* hours 3600)
(* minutes 60)
seconds))))