результат форматирования схемы gimp с ведущими нулями

Я пытаюсь получить метку времени для имени файла. Я использую процедуру (время), которая дает текущую временную метку:

(120 11 29 17 32 25)

год-1900 месяц-1 день час минута секунда

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

это почти хорошо, но... если какой-либо из элементов меньше 10 (например, первое января около часа ночи:

(121 0 1 1 2 3)

это дает неправильную временную метку, потому что мне нужны ведущие нули

202111123 должно быть 20210101010203

Интересно, есть ли более простой метод, чем проверка длины элемента и добавление 0


person Tomasz Brzezina    schedule 29.12.2020    source источник


Ответы (2)


Script-Fu основан на Tiny Scheme, которая сама является подмножеством Схема R5RS. В R5RS Scheme нет встроенных функций для форматирования чисел или строк, подобных этому, и, насколько мне известно, они не добавляются в Script-Fu, поэтому вам нужно будет создать для этого свои собственные функции.

Было бы проще работать со строками, и вам, вероятно, все равно нужны строки для добавления метки времени к имени файла.

Вот функция, которая дополняет строку слева нулями. Обратите внимание, что результат имеет длину не менее width символов, но ввод str не обрезается, если он уже длиннее 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)))))

Вы можете использовать эту функцию в функции time-stamp, которая возвращает строку в нужном формате:

(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)))

Здесь вместо cadr, caddr, cadddr и т. д. используется list-ref; это легче читать и менее подвержено ошибкам. Обратите внимание, что list-ref использует отсчет с нуля. индексы в список.

Затем просто вызовите time-stamp, чтобы получить строку, содержащую информацию о текущей метке времени. Вы можете использовать string->number, если вам действительно нужен номер из этого, либо вызывая результат time-stamp, либо вызывая string->number в определении time-stamp до того, как результат будет возвращен:

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

Я провел вышеупомянутый тест в GIMP, поэтому он показывает мое системное время в этот момент. Вот пример использования вашего фиктивного теста:

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

В первой версии time-stamp выше много дублированного кода. Эта версия может показаться более очевидной для тех, кто не знаком с идиомами программирования Scheme, но вот версия в более функциональном стиле, которая устраняет большую часть этого дублирования кода:

(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))))
person ad absurdum    schedule 29.12.2020
comment
ух ты. Я совсем новичок в TinyScheme, я просто попытался применить какой-то скрипт для своих целей. И не знал list-ref и сделал это с car(cdddr( и с if. Но ваше решение абсолютно идеальное... Отличная работа! - person Tomasz Brzezina; 30.12.2020

Наконец, я сделал это с этим:

  (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))

Но я думаю, что ответ @ad absurdum намного лучше.

person Tomasz Brzezina    schedule 29.12.2020