# Converting seconds into human readable format

Hi,

I am new with Nyquist.
I am looking of method to convert time in seconds (float format) into human readable format “00:00:27.765300”.
Is there (in Nyquist) a method to do it easy or do I need to write a function where I will divide by 60 and count everything by myself?

I may be able to save you some time, I’m sure I wrote a function for that somewhere…
Ah yes, here it is:

``````(defun format-time(sec &optional (n 3))
;; Return time formatted to hh:mm:ss + n decimal places.
(unless (and (numberp sec) (numberp n))
(error "format-time arguments must be numbers."))
(flet ((pad (x) (if (< x 10) (format nil "0~a" x) x)))
(let* ((hh (truncate (/ sec 3600)))
(mm (truncate (/ sec 60)))
(ss (- sec (* mm 60)))
(old-format *float-format*)
rslt)
(setf mm (- mm (* hh 60)))
(setf *float-format* (format nil "%.~af" n))
(setf *float-format* old-format)
rslt)))
``````

That’s great! Thanks a lot Steve, it works perfect.

Did you manage to work out how to set the number of decimal places for fractional seconds?

Yes, it is easy, I use

``````(format-time (first data-1) 4)
``````

but default=3 is good for my use case. I have spent a couple of hours to understand Lisp’s syntax Based on “Export labels” script, I wrote a version for my use case. I have found comma2dot function on this forum that I transformed to dot2comma and use in my script.

``````(defun dot2comma (txt)
;; Replace dot with comma if only one dot
(let ((c (string-search "." txt)))
(if c
(let ((rest (subseq txt (1+ c))))
(if (string-search "." rest)
txt
(strcat (subseq txt 0 c) "," rest)))
txt)))

(defun format-time(sec &optional (n 3))
;; Return time formatted to hh:mm:ss + n decimal places.
(unless (and (numberp sec) (numberp n))
(error "format-time arguments must be numbers."))
(flet ((pad (x) (if (< x 10) (format nil "0~a" x) x)))
(let* ((hh (truncate (/ sec 3600)))
(mm (truncate (/ sec 60)))
(ss (- sec (* mm 60)))
(old-format *float-format*)
rslt)
(setf mm (- mm (* hh 60)))
(setf *float-format* (format nil "%.~af" n))
(setf *float-format* old-format)
(setf rslt-comma (dot2comma rslt))
rslt-comma)))

(defun format-data (tracknum trackname data-1 data-2)
;; Return formatted label data for one label.
(setf trk-time-data
(format nil "~a~a~a~a"
tracknum
trackname
(if (= hastimes 0) ;data-1 times
(format nil "~a~a~a" (format-time (first data-1)) sep (format-time (second data-1)))
"")
(if (= hastimes 0) ;data-2 times
(format nil "~a~a~a~a" sep (format-time (first data-2)) sep (format-time (second data-2)))
"")))

(if (= haslabel 0)
(strcat trk-time-data (format nil "~a~s~a~s~%" sep (third data-1) sep (third data-2)))
(strcat trk-time-data "~%"))
)

(defun export-labels ()
;; Main function.
(let ((info (aud-get-info "labels"))
(tracknames (track-names))
(trackname "")
(tracknum "")
label-string
(output ""))
(dolist (trk info)
(when (= hasnumber 0)
(setf tracknum (format nil "~a~a" (1+ (first trk)) sep)))
(when (= hasname 0)
(setf trackname (format nil "~s~a" (nth (first trk) tracknames) sep)))
(setq trklabels (second trk))
(if (> (rem (length trklabels) 2) 0)
(return-from export-labels (format nil "Error: Not even number of labels.")))
(dotimes (i (/ (length trklabels) 2))
(setq indx (* i 2))
(setq label-1 (nth indx trklabels))
(setq label-2 (nth (1+ indx) trklabels))
(setf label-string (format-data tracknum trackname label-1 label-2))
(setf output (strcat output label-string))))
(write output filename)))
``````

Without track name/num and label strings the script prints times in format (two labels times in one line):

``````0:01:04,850	0:01:07,250	0:01:15,910	0:01:19,900
0:01:25,480	0:01:27,750	0:01:32,620	0:01:34,700
``````

Thanks of that I can export labels times from Audacity and import to Excel in a few mouse clicks.

Digging in forum about decimal separator I found that audacity developers decided to use always dot as a decimal separator. So I want to replace dot2comma function with more “generic” version but I got error in “if”:

``````error: bad argument type - #\,
Function: #<Subr-=: #000002BC90D90E88>
Arguments:
#\,
"."
Function: #<FSubr-IF: #000002BC90D8FAA8>
Arguments:
(= *DECIMAL-SEPARATOR* ".")
(RETURN TXT)
Function: #<Closure-STR-CONVERT-DECIMAL-SEP: #000002BC90CAB898>
``````

function is

``````(defun str-convert-decimal-sep (txt)
;; Replace dot with decimal separator if only one dot
(if (= *decimal-separator* ".") (return txt))
(let ((c (string-search "." txt)))
(if c
(let ((rest (subseq txt (1+ c))))
(if (string-search "." rest)
txt
(strcat (subseq txt 0 c) *decimal-separator* rest)))
txt)))
``````

Why decimal-separator is “#,” or “#.” and how to fix that error?
I will be grateful for your help.

In XLISP / Nyquist, “characters” and “strings” are different data types.
(See: XLISP: An Object-oriented Lisp)

decimal-separator is type “char” (a character).
“.” is a string (type “string”).

The equality operator “=” is for comparing numeric types.
For comparing other types, you need to use the appropriate comparison function: string=, string-equal, char=, char-equal.
You can’t compare apples to oranges, or strings to chars.

One way to compare a string and a char is to compare the string representation of the char:

``````(print (string= (format nil "~a" *decimal-separator*) "."))  ; True
``````

or you could compare decimal-separator with the character #\.

``````(print (char= *decimal-separator* #\.))  ; True
``````

The functions mentioned in this post are all documented in the XLISP manual: XLISP Language Reference

(DECIMAL-SEPARATOR is not standard to Nyquist or XLISP, but is specific to Audacity’s version of Nyquist.)

thank you for in-depth explanation.