diff options
-rw-r--r-- | doc/ref/srfi-modules.texi | 5 | ||||
-rw-r--r-- | module/srfi/srfi-19.scm | 22 | ||||
-rw-r--r-- | test-suite/tests/srfi-19.test | 10 |
3 files changed, 37 insertions, 0 deletions
diff --git a/doc/ref/srfi-modules.texi b/doc/ref/srfi-modules.texi index 99967e574..11fa24d68 100644 --- a/doc/ref/srfi-modules.texi +++ b/doc/ref/srfi-modules.texi @@ -2926,6 +2926,11 @@ the date. @tab minute @tab @nicode{date-minute} +@item @nicode{~N} +@tab @nicode{char-numeric?} +@tab nanosecond +@tab @nicode{date-nanosecond} + @item @nicode{~S} @tab @nicode{char-numeric?} @tab second diff --git a/module/srfi/srfi-19.scm b/module/srfi/srfi-19.scm index 46de91a7e..66939f92c 100644 --- a/module/srfi/srfi-19.scm +++ b/module/srfi/srfi-19.scm @@ -1193,6 +1193,24 @@ (lambda (port) (integer-reader upto port))) +;; read an fractional integer upto n characters long on port; upto -> #f if any length +;; +;; The return value is normalized to upto decimal places. For example, if upto is 9 and +;; the string read is "123", the return value is 123000000. +(define (fractional-integer-reader upto port) + (define (accum-int port accum nchars) + (let ((ch (peek-char port))) + (if (or (eof-object? ch) + (not (char-numeric? ch)) + (and upto (>= nchars upto))) + (* accum (expt 10 (- upto nchars))) + (accum-int port (+ (* accum 10) (char->int (read-char port))) (+ nchars 1))))) + (accum-int port 0 0)) + +(define (make-fractional-integer-reader upto) + (lambda (port) + (fractional-integer-reader upto port))) + ;; read *exactly* n characters and convert to integer; could be padded (define (integer-reader-exact n port) (let ((padding-ok #t)) @@ -1305,6 +1323,7 @@ (define read-directives (let ((ireader4 (make-integer-reader 4)) (ireader2 (make-integer-reader 2)) + (fireader9 (make-fractional-integer-reader 9)) (eireader2 (make-integer-exact-reader 2)) (locale-reader-abbr-weekday (make-locale-reader locale-abbr-weekday->index)) @@ -1343,6 +1362,9 @@ (list #\M char-numeric? ireader2 (lambda (val object) (set-date-minute! object val))) + (list #\N char-numeric? fireader9 (lambda (val object) + (set-date-nanosecond! + object val))) (list #\S char-numeric? ireader2 (lambda (val object) (set-date-second! object val))) (list #\y char-fail eireader2 diff --git a/test-suite/tests/srfi-19.test b/test-suite/tests/srfi-19.test index 4d79f1043..256ff74a0 100644 --- a/test-suite/tests/srfi-19.test +++ b/test-suite/tests/srfi-19.test @@ -176,6 +176,16 @@ incomplete numerical tower implementation.)" (equal? "Sun Jun 05 18:33:00+0200 2005" (date->string date)))) + (pass-if "string->date understands nanoseconds (1)" + (time=? (date->time-utc (string->date "2018-12-10 10:53:24.189" + "~Y-~m-~d ~H:~M:~S.~N")) + (date->time-utc (make-date 189000000 24 53 10 10 12 2018 3600)))) + + (pass-if "string->date understands nanoseconds (2)" + (time=? (date->time-utc (string->date "2018-12-10 10:53:24.189654321" + "~Y-~m-~d ~H:~M:~S.~N")) + (date->time-utc (make-date 189654321 24 53 10 10 12 2018 3600)))) + (pass-if "date->string pads small nanoseconds values correctly" (let* ((date (make-date 99999999 5 34 12 26 3 2017 0))) (equal? "099999999" |