Tomasz Brzezina
Tomasz Brzezina

Reputation: 1534

gimp scheme formatting result with leading zeroes

I'm trying to get timestamp for filename. I use procedure (time) which gives current timestamp:

(120 11 29 17 32 25)

year-1900 month-1 day hour minute second

(+ 1900 (car (time)) )(+ 1 (cadr (time)))(caddr(time))(cadddr(time))(cadr(cdddr(time)))(caddr(cdddr(time)))

this is almost good but... if any of element is lesser then 10 (e.g. first of january about 1 a.m.:

(121 0 1 1 2 3)

it gaves incorrect timestamp, because I need leading zeroes

202111123 should be 20210101010203

I wonder if there's a simplier method than checking the length of element and adding "0"

Upvotes: 1

Views: 157

Answers (2)

ad absurdum
ad absurdum

Reputation: 21367

Script-Fu is based on Tiny Scheme, which is itself a subset of R5RS Scheme. There is no built-in functionality in R5RS Scheme to format numbers or strings like this, and none added to Script-Fu as far as I know, so you will need to create your own functions for this.

It would be easiest to work with strings, and you probably want strings anyway for adding a timestamp to a filename.

Here is a function that left-pads a string with zeroes. Note that the result is at least width characters in length, but the input str is not trimmed if it is already longer than width:

(define (left-pad str width pad)
  (let add-padding ((s str))
    (if (< (- width (string-length s)) 1)
        s
        (add-padding (string-append pad s)))))

You can use this function in a time-stamp function that returns a string in the desired format:

(define (time-stamp)
  (let* ((curr (time))
         (year (number->string (+ 1900 (list-ref curr 0))))
         (month (left-pad (number->string (+ 1 (list-ref curr 1))) 2 "0"))
         (day (left-pad (number->string (list-ref curr 2)) 2 "0"))
         (hour (left-pad (number->string (list-ref curr 3)) 2 "0"))
         (minute (left-pad (number->string (list-ref curr 4)) 2 "0"))
         (second (left-pad (number->string (list-ref curr 5)) 2 "0")))
    (string-append year month day hour minute second)))

Here, list-ref is used instead of cadr, caddr, cadddr, etc.; this is easier to read and less error-prone. Note that list-ref uses zero-based indices into a list.

Then just call time-stamp to get a string containing the current time-stamp information. You can use string->number if you really want a number from this, either calling on the result of time-stamp, or calling string->number in the definition of time-stamp before the result is returned:

> (time-stamp)
"20201229133118"
> (string->number (time-stamp))
20201229133150

I ran the above test in GIMP, so it is showing my system time at that moment. Here is an example using your mock test:

> (define (time) '(121 0 1 1 2 3))
> (time-stamp)
"20210101010203"
> (string->number (time-stamp))
20210101010203

There is a lot of code duplication in the first version of time-stamp above. That version may look more obvious to someone not familiar with Scheme programming idioms, but here is a version in a more functional style that removes a lot of that code duplication:

(define (time-stamp)
  (let* ((curr (time))
         (y (+ 1900 (car curr)))
         (m (+ 1 (cadr curr)))
         (tstamp-nums (apply list y m (cddr curr))))
    (apply string-append
           (map (lambda (x) (left-pad (number->string x) 2 "0"))
                tstamp-nums))))

Upvotes: 2

Tomasz Brzezina
Tomasz Brzezina

Reputation: 1534

Finally I did this with that:

  (define year (+ 1900 (car (time))))
  (define month (+ 1 (cadr (time))))
  (define day (caddr(time)))
  (define hour (cadddr(time)))
  (define minute (cadr(cdddr(time))))
  (define second (caddr(cdddr(time))))

  (set! newFileName (string-append inDir pathchar inFileName
        (number->string year)
        (if (< month 10) (string-append "0" (number->string month)) (number->string month))
        (if (< day 10) (string-append "0" (number->string day)) (number->string day))
        (if (< hour 10) (string-append "0" (number->string hour)) (number->string hour))
        (if (< minute 10) (string-append "0" (number->string minute)) (number->string minute))
        (if (< second 10) (string-append "0" (number->string second)) (number->string second))
             saveString))

But I think that @ad absurdum answer is much better.

Upvotes: 1

Related Questions