Ein Datum ist in R eine Tageszählung im Kostüm
Um eine Zeichenkette in ein echtes Datum zu verwandeln, nutzt du as.Date(); um heute zu bekommen, Sys.Date(). Hinter beidem steckt ein einfacher Trick: R's Date-Klasse ist bloß eine Zahl - die Anzahl der Tage seit dem 1. Januar 1970 - mit einem Kostüm, das sie wie ein Kalenderdatum ausgeben lässt. Mit unclass() ziehst du das Kostüm aus:
Diese 20672 ist die rohe Tageszählung, und sie ist es, die alles Weitere auf dieser Seite funktionieren lässt: Vergleiche, Subtraktion und Sequenzen sind darunter alle bloß Ganzzahlarithmetik. Das Kostüm ist das, was sie nutzbar macht - dieselbe Zahl gibt sich als Datum aus, formatiert sich als Datum und liegt auf einer Datumsachse.
as.Date() parst das ISO-Layout "YYYY-MM-DD" bereitwillig ohne Hilfe, was einer von mehreren guten Gründen ist, Datumswerte so in deinen Dateien zu speichern. Eine Gewohnheit, die du früh aufbauen solltest: Ein gescheitertes Parsen gibt still NA zurück - keinen Fehler -, wirf also nach dem Parsen von etwas Neuem immer einen Blick auf das Ergebnis.
Zeichenketten, die bloß wie Datumswerte aussehen, sind weiterhin nur Zeichenketten: "2026-08-07" < "2026-11-01" vergleicht zufällig korrekt, weil die ISO-Reihenfolge der alphabetischen entspricht, aber "07/08/2026" sortiert als Unsinn. Erst konvertieren, dann vergleichen.
Andere Layouts parsen mit format =
Die Welt schreibt keine ISO-Datumswerte. Für alles andere nimmt as.Date() ein format =-Argument: ein Rezept, das die eingehende Zeichenkette beschreibt, gebaut aus %-Codes.
Alle drei parsen zum selben Tag. Das Rezept muss exakt zur Zeichenkette passen, Trennzeichen inklusive: "%d/%m/%Y" parst "07-08-2026" nicht. Die Codes, die du tatsächlich nutzen wirst:
| Code | Bedeutung | Beispiel |
|---|---|---|
%Y | 4-stelliges Jahr | 2026 |
%y | 2-stelliges Jahr | 26 |
%m | Monatsnummer | 08 |
%d | Tag des Monats | 07 |
%b | Abgekürzter Monatsname | Aug |
%B | Voller Monatsname | August |
%a | Abgekürzter Wochentag | Fri |
%A | Voller Wochentag | Friday |
%H | Stunde (00-23) | 14 |
%M | Minute | 30 |
%S | Sekunde | 05 |
Der klassische Hinterhalt ist "07/08/2026" selbst: Tag/Monat/Jahr in den meisten Teilen der Welt, Monat/Tag/Jahr in den USA, und R kann nicht raten, was deine Datei meint. Schlimmer noch: Eine falsche Vermutung "funktioniert" oft - beide Lesarten sind gültige Datumswerte -, bis Tag 13 irgendeines Monats kommt und zu NA parst (einen 13. Monat gibt es nicht). Kenne die Konvention deiner Daten, bevor du das Rezept schreibst.
Datumswerte für die Ausgabe formatieren
format() ist das Spiegelbild von as.Date(): dieselben %-Codes, in die Gegenrichtung laufend - Date rein, Zeichenkette raus.
Nutze das für Berichtstitel, Beschriftungen und Dateinamen - format(Sys.Date(), "%Y-%m-%d") erzeugt Namen, die chronologisch sortieren. Zwei Details lohnen es zu wissen: %d füllt mit Null auf ("August 07"), und %B/%A erzeugen Namen gemäß den Spracheinstellungen deines Systems - eine auf Deutsch konfigurierte Sitzung gibt "Freitag" statt "Friday" aus. Halte Formatierung an den Rändern deines Skripts, für Menschen; intern lass Datumswerte Dates sein.
Datumsarithmetik und Sequenzen
Weil ein Date eine Tageszählung ist, funktioniert Arithmetik so, wie man es sich wünscht. Die Subtraktion zweier Datumswerte ergibt ein difftime-Objekt:
Drei Gewohnheiten aus diesem Block. Erstens: Pack eine difftime in as.numeric(), bevor du damit rechnest - difftime trägt ein units-Attribut, das spätere Berechnungen überraschen kann. Zweitens: Zählen die Einheiten, gib sie mit difftime(units = ) an, statt zu akzeptieren, was R wählt. Drittens: Eine schlichte Zahl zu addieren heißt Tage addieren - in Base R gibt es kein + 1 Monat, denn "ein Monat" ist keine feste Anzahl Tage.
Für kalenderbewusstes Schrittweiterzählen nutze seq(), das "day", "week", "month", "quarter" und "year" versteht:
Monatssequenzen sind das Standardwerkzeug für Berichtsperioden und Achsenteilungen. Eine Eigenheit: Startest du eine Monatssequenz am 31., zählt R weiter echte Tage durch Monate, die keinen haben, sodass der "Februar"-Eintrag Anfang März landet. Verankere Monatssequenzen am 1. und leite alles andere davon ab.
Bestandteile eines Datums extrahieren
Base R hat zwei Bequemlichkeits-Extraktoren und ein allgemeines Idiom. weekdays() und months() geben Namen zurück; für Zahlen gehst du den Umweg über format():
Der Zug format()-dann-as.integer() sieht umständlich aus, ist aber das Standardidiom in Base R und vektorisiert - übergib ihm eine ganze Datumsspalte, und du bekommst eine ganze Jahresspalte zurück. Genau das willst du nach dem Import eines datierten Datensatzes aus einer CSV-Datei: die Datumsspalte einmal mit as.Date() parsen und dann Jahres- und Monatsspalten fürs Gruppieren ableiten.
Wenn Tage nicht reichen: POSIXct und lubridate
Date kennt kein Konzept von Stunden. Sobald deine Daten Zeitstempel haben - Logeinträge, Sensormesswerte, "Bestellung um 14:32 aufgegeben" -, brauchst du POSIXct, R's Datum-Zeit-Klasse: Sekunden statt Tage seit 1970, und zeitzonenbewusst.
Alles überträgt sich: Dieselben %-Codes (nun einschließlich %H, %M, %S) funktionieren beim Parsen und bei format(), die Subtraktion liefert difftimes, Sys.time() ist "jetzt". Die neue Last ist die Zeitzone - übergib beim Parsen tz = explizit, denn zwei Sitzungen in verschiedenen Zonen lesen dieselbe Zeichenkette sonst als zwei verschiedene Zeitpunkte. Und widersteh der Versuchung, Kalenderdaten "für alle Fälle" als POSIXct zu speichern: Ein als Mitternacht-in-irgendeiner-Zone gespeicherter Geburtstag kann in einer anderen Zone als Vortag ausgegeben werden - ein wirklich elender Bug zum Aufspüren. Ganze Tage: Date. Zeitpunkte: POSIXct.
Schließlich ist das Paket lubridate das freundlichere Gesicht, das der meiste Tidyverse-Code all dem aufsetzt - lohnend, sobald die Base-Mechanik sitzt:
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() und dmy() ersetzen Formatrezepte durch eine schlichte Angabe der Teilereihenfolge, und floor_date() löst "gruppiere diese Zeitstempel nach Monat" in einem Aufruf. lubridate reitet darunter auf denselben Date-/POSIXct-Klassen - ein besseres Lenkrad, kein anderer Motor.
Was du mitnimmst
- Ein
Dateist eine Tageszählung seit 1970-01-01, verkleidet, damit sie wie ein Datum aussieht;unclass()zeigt die Zahl. as.Date("2026-08-07")parst ISO direkt; alles andere braucht einformat =-Rezept aus%-Codes - und ein gescheitertes Parsen gibt stillNAzurück.format(date, "...")ist die Umkehrung: dieselben Codes, erzeugt Anzeigetexte.- Die Subtraktion liefert eine difftime - setz
units =explizit,as.numeric()vor dem Weiterrechnen.+ naddiert Tage; für Monate nutzeseq(by = "month"). weekdays(),months()und das Idiomas.integer(format(...))holen Bestandteile heraus, vektorisiert.Datefür ganze Tage,POSIXct(mit explizitemtz) für Zeitstempel; lubridate macht beides freundlicher.
Als Nächstes: was zu tun ist, wenn R dich anschreit - Fehlermeldungen lesen und methodisch debuggen.
Häufig gestellte Fragen
Wie wandelt man in R eine Zeichenkette in ein Datum um?
Mit as.Date(). Liegt die Zeichenkette im ISO-Format vor, funktioniert es einfach: as.Date("2026-08-07"). Jedes andere Layout braucht ein format =-Rezept aus %-Codes: as.Date("07/08/2026", format = "%d/%m/%Y"). Ein gescheitertes Parsen gibt NA statt eines Fehlers zurück, prüfe das Ergebnis also.
Wie bekommt man in R das heutige Datum?
Sys.Date() gibt heute als Date-Objekt zurück; Sys.time() gibt den aktuellen Zeitpunkt als POSIXct zurück. Beide stammen aus der Uhr und den Zeitzoneneinstellungen deines Computers.
Wie berechnet man in R die Differenz zwischen zwei Datumswerten?
Subtrahiere sie: as.Date("2026-08-07") - as.Date("2026-01-01") ergibt eine difftime von 218 Tagen. Pack sie in as.numeric(), um die Zahl weiterzurechnen, oder ruf difftime(d1, d2, units = "weeks") auf, um die Einheiten selbst zu wählen, statt R entscheiden zu lassen.
Was ist der Unterschied zwischen Date und POSIXct in R?
Date speichert ganze Tage (intern: Tage seit 1970-01-01) und weiß nichts über Stunden oder Zeitzonen. POSIXct speichert einen Zeitpunkt (Sekunden seit 1970) und ist zeitzonenbewusst. Nutze Date für Kalenderdaten wie Geburtstage und Fristen; nutze POSIXct nur, wenn die Tageszeit zählt, etwa bei Zeitstempeln und Logs.