From eb84dace85b56ba8366f31e64da0ef01af20ab24 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmin Date: Sat, 6 Jun 2026 17:16:37 +0400 Subject: [PATCH] Parse timestamp strings in heuristicate-types --- src/properties.lisp | 10 +++++++--- src/utils.lisp | 13 +++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/properties.lisp b/src/properties.lisp index 13a9779..efd34a8 100644 --- a/src/properties.lisp +++ b/src/properties.lisp @@ -10,9 +10,13 @@ Often when reading in a data set, the types will be inconsistent in a variable. (let ((name (name df))) (map nil #'(lambda (key) (let* ((data (column df key)) - (col-type (column-type data)) - (sym (find-symbol (symbol-name key) (find-package name)))) - (setf (get sym :type) col-type))) + (col-type (column-type data)) + (sym (find-symbol (symbol-name key) (find-package name)))) + (setf (get sym :type) col-type) + ;; If a column is :temporal, replace strings in it with timestamps. + ;; If local-time fails to parse a value then signal an error without corrupting the dataframe. + (when (eql col-type :temporal) + (setf (column df key) (map 'vector #'local-time:parse-timestring data))))) (keys df)))) (defun set-properties (df property prop-values) diff --git a/src/utils.lisp b/src/utils.lisp index 92ac365..aba53de 100644 --- a/src/utils.lisp +++ b/src/utils.lisp @@ -9,6 +9,17 @@ ;;; cl:type-of is under-constrained and returns implementation ;;; specific results, so we use our own version ;;; See: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node53.html + + +(defun timestamp-string-p (string) + "Return T if STRING can be parsed as a timestamp by LOCAL-TIME." + (and (stringp string) + (when (local-time:parse-timestring string :fail-on-error nil) + t))) + +(deftype timestamp-string () + '(satisfies timestamp-string-p)) + (defun get-type (x) "Return the most specific type symbol for x" (typecase x @@ -22,6 +33,7 @@ ;; (rational 'cl:rational) ;SBCL doesn't recognise this return type ;; (real 'real) ;SBCL doesn't recognise this return type + (timestamp-string 'temporal) (simple-string 'simple-string) (string 'string) @@ -54,6 +66,7 @@ ((member 'fixnum type-list) :fixnum) ((member 'integer type-list) :integer) ((member 'string type-list) :string) + ((member 'temporal type-list) :temporal) ((member 'bit type-list) :bit) ((member 'symbol type-list) :symbol) (t 'string ))))