Salta al contenuto principale

date: data e ora, formati e calcoli

Inviato da tuxsa il

Che ora è? Che giorno sarà tra tre settimane? Quanti giorni mancano a Natale? E come si mette la data nel nome di un file di backup? Tutte queste domande hanno la stessa risposta: date, il comando che mostra la data e l'ora del sistema e le sa formattare e calcolare.

Cos'è

date fa parte delle coreutils GNU, ed è presente su ogni distribuzione Linux. Legge l'orologio del sistema e lo mostra nel formato che vuoi; in più sa interpretare date scritte a parole (come "tomorrow" o "next friday"), convertirle e fare somme e sottrazioni. Con i privilegi di amministratore può anche impostare l'ora, anche se per questo esistono strumenti migliori (vedi più avanti). Gli esempi usano la versione GNU di date, quella di Linux: su macOS e sui sistemi BSD alcune opzioni sono diverse.

Cosa fa

Senza argomenti stampa data e ora attuali, nella lingua e nel fuso orario del sistema. Con un argomento che comincia per + stampa la data nel formato indicato, in cui ogni sequenza %lettera viene sostituita da una parte della data. Con -d invece di "adesso" usa la data che indichi.

Come si usa

$ date [opzioni] [+formato]

Gli esempi sono stati scritti il 26 ottobre 2026, alle 7:25, in un sistema italiano (fuso di Roma). Con un'altra lingua, i nomi dei giorni e dei mesi cambiano.

Esempio 1: data e ora attuali

$ date
lun 26 ott 2026, 07:25:41, CET
$ date -u
lun 26 ott 2026, 06:25:41, UTC
$ LC_ALL=C date
Mon Oct 26 07:25:41 CET 2026

Senza opzioni date stampa giorno della settimana, data, ora e fuso orario (CET è l'ora solare dell'Europa centrale; in estate si vedrebbe CEST). Con -u si ottiene l'ora universale (UTC), quella usata dai server e dai registri per evitare ambiguità. Con LC_ALL=C si forza il formato neutro in inglese, utile quando l'output deve essere uguale su ogni computer.

Esempio 2: scegliere il formato

$ date +%F
2026-10-26
$ date +%T
07:25:41
$ date "+%d/%m/%Y"
26/10/2026
$ date "+%H:%M"
07:25
$ date "+Oggi è %A %d %B %Y, ore %H:%M"
Oggi è lunedì 26 ottobre 2026, ore 07:25

Il formato inizia con + e, se contiene spazi o simboli, si scrive tra virgolette. Le sequenze più usate sono nella tabella qui sotto. %F è la data in formato internazionale anno-mese-giorno (che ha il vantaggio di essere ordinata correttamente anche in ordine alfabetico) e %T l'ora completa.

SequenzaSignificatoEsempio
%Y %m %dAnno, mese, giorno2026 10 26
%H %M %SOre, minuti, secondi07 25 41
%F / %TData completa / ora completa2026-10-26 / 07:25:41
%A / %aGiorno della settimana, esteso / brevelunedì / lun
%B / %bMese, esteso / breveottobre / ott
%uGiorno della settimana (1 = lunedì)1
%jGiorno dell'anno299
%VNumero della settimana (ISO)44
%sSecondi dal 1° gennaio 1970 (UTC)1792995941
%Z / %zFuso orario, nome / scartoCET / +0100
%%Il simbolo di percentuale%

Esempio 3: un nome di file con la data

$ tar czf "backup-$(date +%F).tar.gz" progetto/
$ ls backup-*
backup-2026-10-26.tar.gz
$ cp db.sql "db-$(date +%Y%m%d-%H%M%S).sql"
$ ls db-*
db-20261026-072541.sql
$ date +%F_%H-%M

È l'uso più comune: $(date +%F) viene sostituito dalla data, e il file prende un nome come backup-2026-10-26.tar.gz. Le date nel formato anno-mese-giorno o annomesegiorno-oraminutisecondi hanno il vantaggio di comparire in ordine cronologico con un semplice ls. Meglio evitare i due punti nei nomi dei file (%T), perché alcuni programmi e sistemi non li accettano. Vedi l'articolo su tar per la parte di archivio.

Esempio 4: date a parole con -d

$ date -d tomorrow +%F
2026-10-27
$ date -d yesterday +%F
2026-10-25
$ date -d "+3 days" +%F
2026-10-29
$ date -d "next friday" +%F
2026-10-30
$ date -d "last friday" +%F
2026-10-23
$ date -d "2 weeks ago" +%F
2026-10-12
$ date -d "2026-12-25 - 1 week" +%F
2026-12-18
$ date -d 2026-12-25 +%A
venerdì

L'opzione -d (date) dice a date di partire da una data descritta a parole invece che dall'ora attuale. Capisce espressioni come tomorrow, yesterday, +3 days, next friday, 2 weeks ago, next month, last year, e si possono combinare con una data di partenza (2026-12-25 - 1 week). Le parole devono essere in inglese: domani non è riconosciuto. Con -d e un formato si ricava anche solo il giorno della settimana di una data qualsiasi.

Esempio 5: quanti giorni mancano?

$ ORA=$(date +%s)
$ NATALE=$(date -d 2026-12-25 +%s)
$ echo $(( (NATALE - ORA) / 86400 ))
59
$ echo "Mancano $(( (NATALE - ORA) / 86400 )) giorni a Natale"
Mancano 59 giorni a Natale

Per fare calcoli tra date si convertono in secondi con %s, si sottraggono e si divide per la durata dell'unità: 60 secondi per i minuti, 3600 per le ore, 86400 per i giorni. L'aritmetica $(( ... )) della shell lavora solo con numeri interi, quindi il risultato è arrotondato per difetto: dal 26 ottobre alle 7:25 al 25 dicembre a mezzanotte passano 59 giorni e 16 ore, che il calcolo riporta come 59.

Esempio 6: convertire da e verso i secondi (epoch)

$ date +%s
1792995941
$ date -d @1792886400
dom 25 ott 2026, 02:00:00, CEST
$ date -u -d @1792886400
dom 25 ott 2026, 00:00:00, UTC
$ date -d "2026-10-25 00:00 UTC" +%s
1792886400

Il numero di secondi dal 1° gennaio 1970, detto epoch o timestamp Unix, è il formato usato da molti programmi, database e registri per memorizzare un istante. date +%s lo stampa; con -d @numero si fa il contrario, per capire a quale data corrisponde. L'ultimo comando mostra la conversione di una data in UTC. Nota che lo stesso istante, alle 00:00 UTC del 25 ottobre, è per l'Italia le 02:00 in ora legale (CEST): quella notte l'ora legale finisce.

Esempio 7: altri fusi orari

$ TZ=America/New_York date
lun 26 ott 2026, 02:25:41, EDT
$ TZ=Asia/Tokyo date +%H:%M
15:25
$ TZ=UTC date -d 'TZ="Europe/Rome" 2026-11-05 15:00'
gio  5 nov 2026, 14:00:00, UTC
$ ls /usr/share/zoneinfo/Europe | head -n 4
Amsterdam
Andorra
Astrakhan
Athens

Con la variabile TZ davanti al comando (vedi l'articolo su export) si mostra l'ora in un altro fuso orario, senza cambiare nulla nel sistema. I nomi dei fusi sono nella cartella /usr/share/zoneinfo, nella forma Continente/Città. Il terzo esempio converte un orario di Roma in UTC, indicando il fuso dentro la data con TZ="...": comodo per organizzare un incontro con persone in altri paesi.

Esempio 8: formati standard e data di un file

$ date -Iseconds
2026-10-26T07:25:41+01:00
$ date -R
Mon, 26 Oct 2026 07:25:41 +0100
$ date -r backup-2026-10-26.tar.gz
lun 26 ott 2026, 07:20:11, CET
$ date -r /etc/passwd +%F
2026-09-03

-I (ISO 8601, con seconds per includere i secondi) e -R (RFC 5322, il formato delle email e delle intestazioni HTTP) stampano la data nei formati standard, non ambigui e interpretabili da altri programmi. -r file mostra la data di ultima modifica di un file. Per vedere tutte le date di un file (modifica, accesso, cambio) si usa stat.

Esempio 9: il registro di ieri

$ IERI=$(LC_ALL=C date -d yesterday +%d/%b/%Y)
$ echo "$IERI"
25/Oct/2026
$ grep "$IERI" /var/log/nginx/access.log | wc -l
8421
$ date -d yesterday +%d/%b/%Y
25/ott/2026

I registri di nginx e Apache scrivono la data con il mese in inglese (25/Oct/2026). In un sistema italiano date +%b darebbe ott, e grep non troverebbe niente. La soluzione è LC_ALL=C davanti a date, che forza i nomi in inglese. Un classico trucco per estrarre dai registri solo le righe di una giornata (vedi gli articoli su grep e wc).

Esempio 10: cambiare l'ora del sistema, e il modo giusto

$ timedatectl
               Local time: lun 2026-10-26 07:25:41 CET
           Universal time: lun 2026-10-26 06:25:41 UTC
                Time zone: Europe/Rome (CET, +0100)
System clock synchronized: yes
              NTP service: active
$ sudo timedatectl set-timezone Europe/Rome
$ sudo timedatectl set-ntp true
$ sudo date -s "2026-10-26 07:30:00"

Sui sistemi con systemd, lo strumento giusto è timedatectl: mostra data, fuso orario e se l'orologio è sincronizzato, e permette di impostare il fuso (set-timezone) e la sincronizzazione automatica con server di riferimento via rete (set-ntp true, protocollo NTP). Su un server non si imposta l'ora a mano: si lascia a NTP. L'ultimo comando, date -s, imposta l'orologio a mano e richiede sudo: serve solo in casi particolari, come un computer isolato dalla rete o una macchina virtuale di prova.

Esempio 11: uso negli script

#!/bin/bash
LOG="$HOME/backup.log"
INIZIO=$(date +%s)

echo "$(date '+%F %T') inizio backup" >> "$LOG"
tar czf "$HOME/backup-$(date +%F).tar.gz" "$HOME/documenti"

FINE=$(date +%s)
DURATA=$((FINE - INIZIO))
printf '%s fine backup (%02d:%02d:%02d)\n' "$(date '+%F %T')" \
    $((DURATA / 3600)) $((DURATA % 3600 / 60)) $((DURATA % 60)) >> "$LOG"

find "$HOME" -maxdepth 1 -name 'backup-*.tar.gz' -mtime +30 -delete

Un piccolo script di backup che usa date in tre modi: per mettere un orario nel registro ('%F %T'), per nominare l'archivio con la data del giorno e per misurare la durata, sottraendo due letture di %s. L'ultima riga elimina con find i backup più vecchi di 30 giorni (-mtime +30), con -delete: provala prima con -print al posto di -delete. Se lo script gira con cron, si può programmare con crontab.

Opzioni utili

  • +formato: stampa nel formato indicato (%Y, %m, %d, %H, %M, %S, %F, %T, %s…).
  • -d "descrizione": usa la data descritta (in inglese) invece di "adesso"; -d @secondi parte da un timestamp.
  • -u: ora universale (UTC); TZ=Fuso date: un altro fuso orario.
  • -I[specificatore]: formato ISO 8601 (-Idate, -Iseconds); -R: formato RFC 5322.
  • -r file: data di ultima modifica di un file.
  • -f file: legge una data per riga da un file e le converte tutte.
  • -s "data": imposta l'orologio (richiede sudo).
  • LC_ALL=C date: nomi in inglese e formato neutro.
  • timedatectl: data, fuso orario e sincronizzazione NTP; cal: calendario del mese (pacchetto ncal o bsdmainutils su alcune distribuzioni).

Attenzione a

  • Le date con la barra sono ambigue: date -d "10/11/2026" viene letto in formato americano, cioè 11 ottobre e non 10 novembre. Per evitare errori usa sempre il formato 2026-11-10 (anno-mese-giorno).
  • Le parole vanno in inglese: domani, ieri e lunedì prossimo non funzionano. Si usa tomorrow, yesterday, next monday.
  • I mesi non sono tutti uguali: date -d "2026-01-31 +1 month" dà 2026-03-03, perché il 31 febbraio non esiste e il calcolo trabocca nel mese dopo. Lo stesso vale per last month a fine mese. Per calcoli sui mesi, parti dal giorno 1 o dal 15.
  • Il formato dentro virgolette: se contiene spazi, date "+%F %T" va scritto tra virgolette, altrimenti la shell lo spezza in due parole e date dà errore. Il + iniziale è obbligatorio.
  • Il carattere % in crontab: dentro una riga di crontab il % è un a capo, e $(date +%F) va scritto $(date +\%F). Nel file dello script non serve (vedi l'articolo su crontab).
  • La lingua cambia l'output: i nomi dei mesi e dei giorni dipendono da LANG e da LC_ALL. Se il risultato serve a un altro programma (come un registro, un nome di file da confrontare o un confronto con grep), blocca la lingua con LC_ALL=C.
  • L'ora legale: due volte all'anno una "giornata" dura 23 o 25 ore, e i calcoli con i secondi (/86400) possono sbagliare di un giorno, soprattutto se uno dei due orari è a mezzanotte. Per calcoli di giorni è più sicuro usare le 12:00 come orario, o l'ora UTC.
  • Non cambiare l'ora a mano sui server: un salto dell'orologio può confondere cron, i registri, i certificati e le sessioni, e dopo poco NTP la corregge. Usa timedatectl set-ntp true e, se serve, chrony o systemd-timesyncd.
  • Orologio hardware e fuso orario: nei sistemi con doppio avvio (Linux e Windows) l'orologio può risultare sfasato di un'ora o due, perché i due sistemi interpretano diversamente l'orologio della scheda madre. Si risolve con timedatectl set-local-rtc oppure impostando Windows su UTC.
  • Un solo secondo di differenza: se chiami date più volte per ricostruire una stringa ($(date +%F) e poi $(date +%T)), tra le due chiamate l'ora può cambiare, e a mezzanotte anche il giorno. Se serve la coerenza, salva il valore in una variabile e riusalo (ORA=$(date +%F_%T)).
  • GNU contro BSD: -d con le espressioni a parole esiste solo nella versione GNU. Su macOS e BSD si usa -v (date -v+1d) e le conversioni sono diverse. Gli script portabili vanno testati sul sistema di destinazione.
  • Il timestamp Unix è in UTC: %s è lo stesso in tutto il mondo, mentre le altre sequenze dipendono dal fuso orario. Per confrontare istanti diversi, il timestamp è il modo più affidabile.

Riepilogo

ComandoCosa fa
dateData e ora attuali
date +%FData nel formato 2026-10-26
date "+%F %T"Data e ora, per i registri
date +%Y%m%d-%H%M%SMarca temporale per nomi di file
date -d tomorrow +%FLa data di domani
date -d "next friday" +%FLa data del prossimo venerdì
date -d "2026-12-25 - 1 week" +%FCalcola una data a partire da un'altra
date +%sSecondi dal 1° gennaio 1970 (UTC)
date -d @1792886400Converte un timestamp in data
date -uOra universale (UTC)
TZ=Asia/Tokyo dateOra in un altro fuso orario
date -IsecondsFormato ISO 8601
date -r fileData di ultima modifica di un file
LC_ALL=C date -d yesterday +%d/%b/%YData di ieri nel formato dei registri web
timedatectlStato di data, fuso orario e sincronizzazione