Robitex's Blog

Ideas in the web

Differenza tra due date con LuaTeX


Il problema

Alcune volte ci troviamo a dover calcolare la differenza in giorni che intercorre tra due date. Se stiamo lavorando in un Word processor occorre rivolgersi ad uno strumento esterno come un foglio di calcolo, mentre con gli strumenti di tipografia asincrona (LaTeX e compagnia), linguaggi naturalmente estensibili, una macro risolverebbe brillantemente questo problema.

Una soluzione in Lua

I linguaggi come LaTeX o ConTeXt sono attualmente basati su TeX, il motore di composizione di Donald Knuth, perfetti per produrre documenti di elevata qualità, ma proprio per questo, non così facili da programmare.

Da qualche tempo il mondo TeX si sta preparando ad accogliere un nuovo motore di composizione basato sia su TeX stesso sia su Lua, un efficiente linguaggio di scripting portabile ed estensibile a sua volta: luatex.

Attualmente luatex è in fase di sviluppo, ma se sul vostro sistema è installata una distribuzione recente di LaTeX come la TeX Live 2009, probabilmente è già a vostra disposizione.

Utilizziamo la funzione os.time() della operating system library di Lua per tradurre le date in un unico valore numerico, il numero di secondi trascorsi da un certo epoch. A questo punto basta fare la differenza ed esprimere il risultato in giorni anziché in secondi ed il gioco è fatto. Ecco il frammento di codice:

local date1 = os.time({day=1,month=1,year=2010})
local date2 = os.time({day=28,month=7,year=2010})
local secperdays = 24*60*60
local daysdiff = (date2 - date1) / secperdays
print("Days difference: " .. daysdiff)

La funzione os.time() accetta una tabella con le tre chiavi day, month ed year. Nel codice abbiamo dunque racchiuso tra parentesi graffe la tabella nella constructor expression prevista dal linguaggio Lua.

Una soluzione in luatex

In luatex scriveremo dunque una macro utilizzando il classico comando \def per cui si prevede due argomenti: la data precedente e poi quella successiva dell’intervallo temporale:

\def\datediff#1#2{\directlua{
    local date1 = os.time({#1})
    local date2 = os.time({#2})
    local secperdays = 24*60*60
    local daysdiff = (date2 - date1) / secperdays

    tex.print(math.floor(daysdiff))}}

% inizio documento
Dalla mia nascita ad oggi sono trascorsi esattamente
\datediff{year=1900,month=1,day=1}{year=2010,month=1,day=10}
giorni.

Eppure mi pare un numero del tutto privo di emozioni...
\end

Salvate il codice in un file con estensione .tex e compilate il tutto con il comando:

luatex nomefile.tex

Nella directory trovere il file pdf di output con il risultato.
Le funzioni della libreria standard di Lua sono facili da usare e generalmente il codice è compatto ed efficiente. Così è facile prevedere una stagione ancora più ricca per gli utenti di LaTeX e compagnia.

Alla prossima. Gulp.

6 risposte a “Differenza tra due date con LuaTeX

  1. a.ledda 12/01/2010 alle 21:50

    Ciao Roberto,
    ieri ho provato il codice, ma non ho ottenuto quanto sperato.

    Nel pc ho la TeX Live 2009 e in seguito alla compilazione del codice (che si interrompe e che faccio riprendere con un “Invio”), il documento in .pdf prodotto non riporta la differenza tra le due date.

    Ecco il .log:
    This is LuaTeX, Version beta-0.40.6-2009110118 (Web2C 2009) (format=luatex 2009.11.28) 11 JAN 2010 22:54
    **test.tex
    (test.tex
    ! LuaTeX error :1: attempt to perform arithmetic on local ‘date1’
    (a nil value)
    stack traceback:
    :1: in main chunk.
    \datediff …\par tex.print(math.floor(daysdiff))}

    l.11 …0,month=1,day=1}{year=2010,month=1,day=10}

    ?
    [1{c:/texlive/2009/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] )
    Output written on test.pdf (1 page, 14611 bytes).
    PDF statistics:
    10 PDF objects out of 1000 (max. 8388607)
    0 named destinations out of 1000 (max. 131072)
    1 words of extra memory for PDF output out of 10000 (max. 10000000)

    Ti è mai capitato? Ho provato anche il codice che hai “postato” sul forum del GuIT. In quel caso, noto il problema della differenza tra le date, solo in una riga. Per il resto, va bene. Sono quasi sicuro che la causa di ciò sia nel mio computer. Se risolvo ti faccio sapere.

    Ah, dimenticavo: ho fatto anche una prova con ConTeXt (minimals); stesso risultato. Ecco il .log:
    (test3.tex

    ConTeXt ver: 2010.01.11 14:57 MKIV fmt: 2010.1.11 int: english/english

    system : cont-new loaded
    (C:/context/tex/texmf-context/tex/context/base/cont-new.tex
    systems : beware: some patches loaded from cont-new.tex
    (C:/context/tex/texmf-context/tex/context/base/cont-new.mkiv))
    system : cont-fil loaded
    (C:/context/tex/texmf-context/tex/context/base/cont-fil.tex
    loading : ConTeXt File Synonyms
    )
    system : cont-sys.rme loaded
    (C:/context/tex/texmf-context/tex/context/user/cont-sys.rme (C:/context/tex/texmf-context/tex/context/base/type-lua.tex) (C:/context/tex/texmf-context/tex/context/base/type-tmf.tex (C:/context/tex/texmf-context/tex/context/base/type-tmf.mkiv)) (C:/context/tex/texmf-context/tex/context/base/type-siz.tex (C:/context/tex/texmf-context/tex/context/base/type-siz.mkiv)) (C:/context/tex/texmf-context/tex/context/base/type-otf.tex (C:/context/tex/texmf-context/tex/context/base/type-otf.mkiv)))
    system : test3.top loaded
    %
    % begin of optionfile
    %
    % % runtime options files (command line driven)
    % \unprotect
    % % special commands, mostly for the ctx development team
    % % feedback and basic job control
    % % handy for special styles
    % \startluacode
    % document = document or { }
    % document.arguments={
    % }
    % document.files={
    % “test3.tex”,
    % }
    % \stopluacode
    % % process info
    % \setupsystem[inputfile=test3.tex]
    % \setupsystem[\c!n=1,\c!m=1]
    % % modes
    % % options (not that important)
    % \startsetups *runtime:options
    % \setupoutput[pdftex]
    % \stopsetups
    % % styles and modules
    % \startsetups *runtime:modules
    % \stopsetups
    % % done
    % \protect \endinput
    %
    % end of optionfile
    %
    (test3.top)
    fonts : preloading latin modern fonts
    bodyfont : 12pt rm is loaded
    language : language en is active
    ! LuaTeX error :1: attempt to perform arithmetic on local ‘date1’ (a nil value)
    stack traceback:
    :1: in main chunk.
    \datediff …\par tex.print(math.floor(daysdiff))}

    l.19 …09,year=1950}{day=12, month=12, year=1996}
    giorni.
    ?
    system : cont-err loaded
    (C:/context/tex/texmf-context/tex/context/base/cont-err.tex
    systems : no file ‘cont-sys.tex’, using ‘cont-sys.rme’ instead
    )
    fonts : resetting map file list
    {C:/context/tex/texmf-context/fonts/map/pdftex/context/original-empty.map}
    fonts : using map file: original-base
    {C:/context/tex/texmf-context/fonts/map/pdftex/context/original-base.map}
    fonts : using map file: original-ams-base
    {C:/context/tex/texmf-context/fonts/map/pdftex/context/original-ams-base.map}
    fonts : using map file: original-ams-euler
    {C:/context/tex/texmf-context/fonts/map/pdftex/context/original-ams-euler.map}
    fonts : using map file: original-public-lm
    {C:/context/tex/texmf-context/fonts/map/pdftex/context/original-public-lm.map}
    fonts : using map file: lm-math
    {C:/context/tex/texmf/fonts/map/dvips/lm/lm-math.map}
    fonts : using map file: lm-rm
    {C:/context/tex/texmf/fonts/map/dvips/lm/lm-rm.map}
    !pages : flushing page
    )
    mkiv lua stats : used config path – C:/context/tex/texmf/web2c/texmf.cnf
    mkiv lua stats : used cache path – C:/context/tex/texmf-cache
    mkiv lua stats : input load time – 0.047 seconds
    mkiv lua stats : stored bytecode data – 200 modules, 48 tables, 248 chunks
    mkiv lua stats : node list callback tasks – 4 unique tasks, 3 created, 22 calls
    mkiv lua stats : cleaned up reserved nodes – 25 nodes, 9 lists of 1408
    mkiv lua stats : node memory usage – 20 glue_spec, 1 dir
    mkiv lua stats : used backend – pdf (backend for directly generating pdf output)
    mkiv lua stats : loaded patterns – en:us:pat:exc:2
    mkiv lua stats : startup time – 0.906 seconds (including runtime option file processing)
    mkiv lua stats : callbacks – direct: 469, indirect: 3679, total: 4148
    mkiv lua stats : lxml preparation time – 0.000 seconds, 0 nodes, 12 lpath calls, 0 cached calls
    mkiv lua stats : result saved in file – test3.pdf
    mkiv lua stats : loaded fonts – 32 files: lmmono12-regular.otf lmmono8-regular.otf lmmono9-regular.otf lmroman12-bold.otf lmroman12-regular.otf lmroman7-bold.otf lmroman7-regular.otf lmroman9-bold.otf lmroman9-regular.otf lmsans12-regular.otf lmsans8-regular.otf lmsans9-regular.otf eufb10.tfm eufb7.tfm eufm10.tfm eufm7.tfm msam10.tfm msam7.tfm msbm10.tfm msbm7.tfm lmex10.tfm lmmi12.tfm lmmi7.tfm lmmi9.tfm lmmib10.tfm lmmib7.tfm lmsy10.tfm lmsy7.tfm lmsy9.tfm rm-lmr12.tfm rm-lmr7.tfm rm-lmr9.tfm
    mkiv lua stats : fonts load time – 0.531 seconds
    mkiv lua stats : luatex banner – this is luatex, version beta-0.50.0-2009122521
    mkiv lua stats : control sequences – 29732 of 165536
    mkiv lua stats : current memory usage – 31 MB (ctx: 32 MB)
    mkiv lua stats : runtime – 3.906 seconds, 0 processed pages, 1 shipped pages, 0.256 pages/second

    Ciao,
    Antonio

  2. a.ledda 12/01/2010 alle 21:56

    Scusa, il secondo .log è relativo al codice “postato” sul forum; la sostanza è comunque quella.

    Ciao,
    Antonio

  3. robitex 13/01/2010 alle 09:53

    Ciao Antonio, innanzi tutto Buon Anno, spero che sia proprio un buon anno.

    Il problema che hai riscontrato è dovuto all’uso di date precedenti all’epoch del 1 gennaio 1970 in Windows.

    Lua restituisce un valore nil per date1. Questo comportamento è diverso per i sistemi Unix dove (vado a memoria ma stasera posso verificarlo) se la data è precedente all’epoch la funzione os.time() restituisce un numero negativo (come uno si aspetterebbe).

    Ciao a presto.

  4. a.ledda 13/01/2010 alle 21:10

    Roberto,
    grazie per gli auguri, che ricambio con molto piacere.

    Per quanto riguarda il problema, hai perfettamente ragione: se imposto

    \datediff{year=1970,month=1,day=1}{year=2010,month=1,day=10}

    tutto fila liscio. Sono sorpreso da questo fatto; non mi pare di averne mai sentito parlare. Google stavolta non mi è stato amico (o forse non ho cercato bene).😦

    Grazie mille per la spiegazione.

    Ciao,
    Antonio

    • robitex 13/01/2010 alle 23:36

      Per saperne di più sull’epoch di Unix consulta il link http://en.wikipedia.org/wiki/Unix_time .
      Comunque si dovrebbe approfondire l’uso delle funzioni Lua os.time() ed os.date().
      Questa era una specie di esempio.
      Alla prossima. Ciao.

      • a.ledda 14/01/2010 alle 00:20

        Non avevo cercato bene e, in realtà, non sapevo esattamente cosa cercare. Grazie per il link; ne sto già leggendo il contenuto.

        Ciao,
        Antonio

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger cliccano Mi Piace per questo: