Archivi delle etichette: due date

Il termine dell’appalto

Sommario

Calcoleremo la data di termine di un appalto a partire da quella di inizio lavori dal numero di giorni naturali e consecutivi stabiliti dal contratto, utilizzando due linguaggi di programmazione: Lua e Go.

L’occasione

Potevamo utilizzare un banale foglio di calcolo per determinare la data del termine di fine lavori per un contratto d’appalto? No… No perché ci si annoia sempre a fare le stesse cose e sentiamo la necessità di migliorarci.

Calcolo

La descrizione del calcolo che seguiremo è presto fatta: alla data di inizio sommiamo il numero di giorni stabiliti per completare l’opera e togliamo un giorno, per ottenere così la data cercata corrispondente al termine dei lavori.

Infatti, il giorno della consegna conta già uno ai fini del tempo contrattuale. Possiamo vedere la cosa considerando l’istante di tempo della mezzanotte: è al contempo il primo istante del giorno ma anche l’ultimo di quello precedente.
Tuttavia la mezzanotte è sempre interpretato come il primo istante del giorno successivo. Per la data di inizio è corretto ma non per la data di termine.

Lua

In Lua, utilizzando le funzioni della libreria interna “os”, costruiamo la data di inizio lavori che viene gestita come il numero di secondi trascorsi da un certo momento (il classico epoch Unix). Sommiamo poi il numero di secondi corrispondenti alla durata dell’appalto, sottraendovi un secondo per ottenere l’attimo prima della fine dell’ultimo giorno di lavoro.
La funzione termina restituendo la stringa della data formattata eventualmente come specificato nell’ultimo argomento facoltativo.

-- restituisce la data di scadenza dell'appalto
-- nota la data di consegna ed il numero di
-- giorni naturali e consecutivi della durata
-- dei lavori contrattuali

local function endingDate(d,m,y, days, frmt)
    local secsperday = 24*60*60
    local t_start = os.time{day=d,month=m,year=y,hour=0}
    local t_end   = t_start + days*secsperday -1
    frmt = frmt or "%d/%m/%Y"
    return os.date(frmt, t_end)
end

print(endingDate(26,8,2013, 60))

Go

Anche in Go utilizziamo la libreria disponibile con il linguaggio, in particolare il pacchetto “time”, per restituire nello stesso formato precedente la data risultato.

package main

import (
    "time"
    "fmt"
)

func main() {
    fmt.Println(endingDate(2013,8,26, 60))
}

func endingDate(y int, m time.Month, d, days int) string {
    s := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
    e := s.AddDate(0, 0, days).Add(-time.Second)
    return fmt.Sprintf("%d/%02d/%d",e.Day(), e.Month(), e.Year())
}

Finale

Le differenze con Lua possono sembrare ad un primo sguardo minime, ma non è così anche se entrambi hanno feature in comune come il supporto alla concorrenza, le funzioni di prima classe e le closure.

Io, la prima cosa che ho notato è la maggiore precisione della libreria “time” di Go rispetto a Lua (che si riflette nel modo in cui percepiamo le date), e l’uso trasparente in Go di tipi sinonimi di quelli di base come per esempio nella rappresentazione del mese — il tipo time.Month per intenderci.

Penso però che la differenza sostanziale sia nell’importanza che il linguaggio da ai tipi: in Lua la tipizzazione è dinamica come si conviene per un linguaggio di scripting mentre in Go è statica: nel codice occorre sempre definire il tipo di dato e solo rispetto a questa classificazione i dati possono essere elaborati, per esempio da una funzione).

Il risultato è che in Go si è maggiormente portati a pensare concettualmente ai dati come termini del problema, strutturando il codice. Ovvio che questa differenza è la stessa che troviamo confrontando qualsiasi coppia di linguaggi con tipi dinamici e statici (come Python e Java), ma il Go è certamente uno dei linguaggi a tipi statici che si avvicinano di più ai linguaggi a tipi dinamici…

Un saluto.
R.