In R una data è un conteggio di giorni travestito
Per trasformare una stringa in una vera data usa as.Date(); per ottenere la data di oggi usa Sys.Date(). Dietro entrambe c'è un trucco semplice: la classe Date di R è solo un numero, il conteggio dei giorni trascorsi dal 1° gennaio 1970, con addosso un costume che lo fa stampare come una data di calendario. Puoi togliere il costume con unclass():
Quel 20672 è il conteggio grezzo dei giorni, ed è ciò che fa funzionare tutto il resto di questa pagina: confronti, sottrazioni e sequenze sono tutti, sotto sotto, semplici calcoli con interi. Il costume è ciò che lo rende utilizzabile: lo stesso numero si stampa come data, si formatta come data e si disegna su un asse di date.
as.Date() interpreta senza problemi il formato ISO "YYYY-MM-DD" senza alcun aiuto, ed è uno dei tanti buoni motivi per salvare le date così nei tuoi file. Un'abitudine da prendere subito: un parsing fallito restituisce NA in silenzio, non un errore, quindi dai sempre un'occhiata al risultato dopo aver interpretato qualcosa di nuovo.
Le stringhe che si limitano a sembrare date restano semplici stringhe: "2026-08-07" < "2026-11-01" si confronta correttamente per caso, perché l'ordine ISO coincide con l'ordine alfabetico, ma "07/08/2026" si ordina in modo insensato. Prima converti, poi confronta.
Interpretare altri formati con format =
Il mondo non scrive le date in formato ISO. Per tutto il resto, as.Date() accetta un argomento format =: una ricetta che descrive la stringa in arrivo, costruita con i codici %.
Tutte e tre diventano lo stesso giorno. La ricetta deve corrispondere esattamente alla stringa, separatori compresi: "%d/%m/%Y" non interpreterà "07-08-2026". I codici che userai davvero:
| Codice | Significato | Esempio |
|---|---|---|
%Y | Anno a 4 cifre | 2026 |
%y | Anno a 2 cifre | 26 |
%m | Numero del mese | 08 |
%d | Giorno del mese | 07 |
%b | Nome del mese abbreviato | Aug |
%B | Nome del mese completo | August |
%a | Giorno della settimana abbreviato | Fri |
%A | Giorno della settimana completo | Friday |
%H | Ora (00-23) | 14 |
%M | Minuto | 30 |
%S | Secondo | 05 |
L'imboscata classica è proprio "07/08/2026": giorno/mese/anno in gran parte del mondo, mese/giorno/anno negli Stati Uniti, e R non può indovinare quale intende il tuo file. Peggio ancora, un'ipotesi sbagliata spesso "funziona", perché entrambe le letture sono date valide, finché non arriva il giorno 13 di un mese che diventa NA (non esiste un tredicesimo mese). Conosci la convenzione dei tuoi dati prima di scrivere la ricetta.
Formattare le date in output
format() è l'immagine speculare di as.Date(): gli stessi codici %, ma nella direzione opposta, cioè una Date in ingresso e una stringa in uscita.
Usalo per titoli di report, etichette e nomi di file: format(Sys.Date(), "%Y-%m-%d") crea nomi che si ordinano cronologicamente. Due dettagli da sapere: %d aggiunge uno zero iniziale ("August 07"), e %B/%A producono nomi nella lingua impostata sul sistema, per cui una sessione configurata in italiano stampa "venerdì" invece di "Friday". Tieni la formattazione ai margini del tuo script, per le persone; internamente lascia le date come Date.
Calcoli e sequenze con le date
Siccome una Date è un conteggio di giorni, l'aritmetica funziona come ti aspetteresti. Sottrarre due date dà un oggetto difftime:
Tre abitudini da prendere da quel blocco. Primo, avvolgi un difftime in as.numeric() prima di farci dei calcoli: il difftime porta con sé un attributo di unità che può riservare sorprese nei calcoli successivi. Secondo, quando le unità contano, dichiarale con difftime(units = ) invece di accettare quelle che sceglie R. Terzo, aggiungere un numero semplice significa aggiungere giorni: in R base non esiste + 1 month, perché "un mese" non è un numero fisso di giorni.
Per avanzare seguendo il calendario usa seq(), che capisce "day", "week", "month", "quarter" e "year":
Le sequenze mensili sono lo strumento standard per i periodi dei report e le suddivisioni degli assi. Una stranezza: se inizi una sequenza mensile il giorno 31, R continua a contare giorni reali attraverso i mesi che non ce l'hanno, così la voce di "febbraio" finisce ai primi di marzo. Ancora le sequenze mensili al giorno 1 e ricava tutto il resto da lì.
Estrarre parti di una data
R base ha due estrattori comodi e un idioma generale. weekdays() e months() restituiscono dei nomi; per i numeri, fai un giro passando da format():
La mossa format() seguita da as.integer() sembra contorta, ma è l'idioma standard di R base ed è vettoriale: dagli un'intera colonna di date e ottieni un'intera colonna di anni. È esattamente ciò che vuoi dopo aver importato un dataset con date da un file CSV: interpreta la colonna delle date una volta con as.Date(), poi ricava le colonne di anno e mese per raggruppare.
Quando i giorni non bastano: POSIXct e lubridate
Date non ha il concetto di ore. Appena i tuoi dati hanno dei timestamp, voci di log, letture di sensori, "ordine effettuato alle 14:32", ti serve POSIXct, la classe data-ora di R: secondi dal 1970 invece di giorni, con gestione del fuso orario.
Tutto si trasferisce: gli stessi codici % (ora anche %H, %M, %S) funzionano per il parsing e per format(), la sottrazione dà dei difftime, Sys.time() è "adesso". Il nuovo peso è il fuso orario: passa tz = esplicitamente durante il parsing, perché altrimenti due sessioni in fusi diversi leggeranno la stessa stringa come due istanti diversi. E resisti alla tentazione di salvare dati di calendario come POSIXct "per sicurezza": un compleanno salvato come mezzanotte in un certo fuso può essere stampato come il giorno prima in un altro fuso, un bug davvero penoso da rintracciare. Giorni interi: Date. Istanti: POSIXct.
Infine, il pacchetto lubridate è il volto più amichevole che la maggior parte del codice tidyverse dà a tutto quanto sopra, e vale la pena adottarlo una volta capiti i meccanismi di base:
library(lubridate)
ymd("2026-08-07") # order-based parsing: no format string
mdy("08/07/2026") # ...you just say which order the parts come in
dmy("7 August 2026")
floor_date(Sys.Date(), "month") # snap to the start of the period
ymd(), mdy() e dmy() sostituiscono le ricette di formato con una semplice indicazione dell'ordine delle parti, e floor_date() risolve "raggruppa questi timestamp per mese" in una chiamata. Sotto, lubridate usa le stesse classi Date/POSIXct: un volante migliore, non un motore diverso.
Cosa ti porti a casa
- Una
Dateè un conteggio di giorni dal 1970-01-01 vestito in modo da stamparsi come una data;unclass()mostra il numero. as.Date("2026-08-07")interpreta direttamente il formato ISO; tutto il resto richiede una ricettaformat =di codici%, e un parsing fallito restituisceNA, in silenzio.format(date, "...")fa il contrario: gli stessi codici, per produrre stringhe da mostrare.- La sottrazione dà un difftime: imposta
units =esplicitamente e usaas.numeric()prima dei calcoli.+ naggiunge giorni; per i mesi usaseq(by = "month"). weekdays(),months()e l'idiomaas.integer(format(...))estraggono le parti, in modo vettoriale.Dateper i giorni interi,POSIXct(con untzesplicito) per i timestamp; lubridate rende entrambi più amichevoli.
Prossimo passo: cosa fare quando R ti urla contro, cioè leggere i messaggi di errore e fare debug con metodo.
Domande frequenti
Come si converte una stringa in una data in R?
Con as.Date(). Se la stringa è in formato ISO funziona e basta: as.Date("2026-08-07"). Qualsiasi altra disposizione richiede una ricetta format = costruita con i codici %: as.Date("07/08/2026", format = "%d/%m/%Y"). Un parsing fallito restituisce NA invece di un errore, quindi controlla il risultato.
Come si ottiene la data di oggi in R?
Sys.Date() restituisce la data di oggi come oggetto Date; Sys.time() restituisce la data e l'ora correnti come POSIXct. Entrambe vengono dall'orologio e dal fuso orario impostati sul tuo computer.
Come si calcola la differenza tra due date in R?
Sottraile: as.Date("2026-08-07") - as.Date("2026-01-01") dà un difftime di 218 giorni. Avvolgilo in as.numeric() per usare il numero nei calcoli, oppure chiama difftime(d1, d2, units = "weeks") per scegliere tu le unità invece di lasciarle decidere a R.
Qual è la differenza tra Date e POSIXct in R?
Date memorizza giorni interi (internamente: giorni dal 1970-01-01) e non sa nulla di ore o fusi orari. POSIXct memorizza un istante nel tempo (secondi dal 1970) e tiene conto del fuso orario. Usa Date per dati di calendario come compleanni e scadenze; usa POSIXct solo quando conta l'ora del giorno, come per timestamp e log.