Alle anderen Fragen im SE-Netzwerk beziehen sich auf Szenarien, in denen entweder das Datum als now
( Q ) angenommen wird oder nur ein Datum angegeben wird ( Q ).
Ich möchte ein Datum und eine Uhrzeit angeben und dann eine Uhrzeit davon abziehen.
Folgendes habe ich zuerst versucht:
date -d "2018-12-10 00:00:00 - 5 hours - 20 minutes - 5 seconds"
Dies führt zu 2018-12-10 06:39:55
- Es wurden 7 Stunden hinzugefügt. Dann werden 20:05 Minuten abgezogen.
Nachdem ich die man
und info
Seite von gelesen hatte date
, dachte ich, ich hätte es folgendermaßen behoben:
date -d "2018-12-10T00:00:00 - 5 hours - 20 minutes - 5 seconds"
Aber das gleiche Ergebnis. Woher kommen die 7 Stunden überhaupt?
Ich habe auch andere Daten ausprobiert, weil ich dachte, wir hätten an diesem Tag vielleicht 7200 Schaltsekunden, wer weiß, lol. Aber die gleichen Ergebnisse.
Noch ein paar Beispiele:
$ date -d "2018-12-16T00:00:00 - 24 hours" +%Y-%m-%d_%H:%M:%S
2018-12-17_02:00:00
$ date -d "2019-01-19T05:00:00 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-19_08:55:00
Aber hier wird es interessant. Wenn ich die Zeit bei der Eingabe weglasse, funktioniert es gut:
$ date -d "2018-12-16 - 24 hours" +%Y-%m-%d_%H:%M:%S
2018-12-15_00:00:00
$ date -d "2019-01-19 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-18_21:55:00
$ date --version
date (GNU coreutils) 8.30
Was vermisse ich?
Update: Ich habe ein Z
am Ende hinzugefügt , und es hat das Verhalten geändert:
$ date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_04:00:00
Ich bin immer noch verwirrt. Darüber gibt es auf der GNU-Infoseite zum Datum nicht viel .
Ich vermute, dies ist ein Problem mit der Zeitzone, zitiere aber das Kalender-Wiki zu ISO 8601 :
Wenn keine UTC-Beziehungsinformationen mit einer Zeitdarstellung angegeben werden, wird angenommen, dass die Zeit in Ortszeit ist.
Welches ist, was ich will. Meine Ortszeit ist auch richtig eingestellt. Ich bin nicht sicher, warum Datum mit der Zeitzone in diesem einfachen Fall, in dem ich eine Datums- / Uhrzeitangabe liefere und etwas davon subtrahieren möchte, in Konflikt geraten würde. Sollte es nicht zuerst die Stunden vom Datumsstring subtrahieren? Auch wenn es es zuerst in ein Datum konvertiert und dann die Subtraktion durchführt, bekomme ich genau das, was ich will, wenn ich keine Subtraktionen auslasse:
$ date -d "2019-01-19T05:00:00" +%Y-%m-%d_%H:%M:%S
2019-01-19_05:00:00
So IF dies wirklich eine Zeitzone Frage ist, woher kommt der Wahnsinn gekommen?
Antworten:
Das letzte Beispiel hätte die Dinge für Sie klarstellen sollen: Zeitzonen .
Da die Ausgabe je nach Zeitzone deutlich variiert, würde ich vermuten, dass für eine Zeitzeichenfolge ohne Zeitzone ein nicht offensichtlicher Standardwert verwendet wurde. Wenn ich ein paar Werte teste, scheint es UTC-05: 00 zu sein , obwohl ich nicht sicher bin, was das ist.
Es wird nur verwendet, wenn Datumsarithmetik ausgeführt wird.
Es scheint , das hier Problem ist , dass
- 2 hours
sich nicht als arithmetisches genommen, sondern als eine Zeitzone Spezifizierer :Es wird also nicht nur keine Arithmetik ausgeführt, es scheint auch eine
Sommerzeitumstellung von1 Stunde für die Zeit zu geben, was für uns zu einer etwas unsinnigen Zeit führt.Dies gilt auch für die Ergänzung:
Wenn Sie ein bisschen mehr debuggen, scheint das Parsing wie folgt zu sein:
2019-01-19T05:00:00 - 2
(-2
als Zeitzone) undhours
(= 1 Stunde), mit einem impliziten Zusatz. Es wird einfacher zu erkennen, ob Sie stattdessen Minuten verwenden:Nun, es wird gerade eine Datumsberechnung durchgeführt, nur nicht die, nach der wir gefragt haben. ¯ \ (ツ) / ¯
quelle
TZ=UTC date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
vsTZ=UTC date -d "2019-01-19T05:00:00 - 2 hours" +%Y-%m-%d_%H:%M:%S
) verwendetdate
gemäß der Norm ISO 8601 sein, wenn keine Zeitzone angegeben wird, sollte die Ortszeit (Zone) angenommen werden, was im Falle einer arithmetischen Operation nicht der Fall ist. Sehr seltsames Problem für mich.- 2 hours
wird hier als Zeitzonenbezeichner verwendet.--debug
Option des Datums erfahren ! Tolle Erklärung.Es funktioniert korrekt, wenn Sie das Eingabedatum zuerst in ISO 8601 konvertieren:
quelle
date
dies zu Problemen führen würde, da ohne Subtraktionen die Zeitzone unangetastet bleibt und auch alles wie erwartet ist, ohne dass eine angegeben werden muss Zeitzoneninformationen oder Konvertierung.date -I
auch der Zeitzonenspezifizierer (z. B.2018-12-10T00:00:00+02:00
) ausgegeben wird, derTLDR: Dies ist kein Fehler. Sie haben gerade eines der subtilen, aber dokumentierten Verhaltensweisen von gefunden
date
. Wenn mit der Zeit Arithmetikdate
, verwenden Sie eine Zeitzone unabhängigen Format (wie Unix Zeit) oder lesen sehr sorgfältig in der Dokumentation zu wissen , wie man richtig diesen Befehl verwenden.GNU
date
verwendet Ihre Systemeinstellungen (dieTZ
Umgebungsvariable oder, falls nicht festgelegt, die Standardeinstellungen des Systems), um die Zeitzone sowohl des mit der Option-d
/--date
eingegebenen Datums als auch des vom+format
Argument angegebenen Datums zu bestimmen . Mit der--date
Option können Sie auch die Zeitzone für ein eigenes Optionsargument außer Kraft setzen, aber die Zeitzone von wird nicht außer Kraft gesetzt+format
. Das ist die Wurzel der Verwirrung, IMHO.Wenn meine Zeitzone UTC-6 ist, vergleichen Sie die folgenden Befehle:
Der erste verwendet meine Zeitzone für beide
-d
und+format
. Die zweite verwendet UTC für-d
aber meine Zeitzone für+format
. Der dritte verwendet UTC für beide.Vergleichen Sie nun die folgenden einfachen Operationen:
Auch wenn mir die Unix-Zeit dasselbe sagt, unterscheidet sich die "normale" Zeit aufgrund meiner eigenen Zeitzone.
Wenn ich den gleichen Vorgang ausführen möchte, aber ausschließlich meine Zeitzone benutze:
quelle
-08:00
), hängen Sie dies einfach an die Eingabe der Datums- / Uhrzeit an. Beispiel:date -d '2019-02-28 14:05:36-08:00 +2 days 4 hours 3 seconds' +'local: %F %T'
gibt local: 2019-03-02 18:05:36+format
Argument bereitgestellten Informationen falsch aussehen . Auf meinem System wird zum Beispiel derselbe Befehl ausgegeben:local: 2019-03-02 20:05:39
(Wenn ich ihn hinzufüge%:z
,+format
wird es offensichtlich, dass die Informationen korrekt sind und die Diskrepanz auf die Zeitzonen zurückzuführen ist.)-d
und /+format
oder Unix-Zeit zu verwenden, wie ich in der Antwort sagte, um unerwartete Ergebnisse zu vermeiden.GNU
date
unterstützt einfache Datumsberechnungen, obwohl Berechnungen der Epochenzeit, wie in @sudodus 'Antwort gezeigt, manchmal klarer (und portabler) sind.Die Verwendung von +/-, wenn im Zeitstempel keine Zeitzone angegeben ist, löst den Versuch aus, als Nächstes eine Zeitzone zuzuordnen, bevor etwas anderes analysiert wird.
Hier ist eine Möglichkeit, dies zu tun: Verwenden Sie "ago" anstelle von "-":
oder
(Obwohl Sie "Z" nicht willkürlich verwenden können, funktioniert es in meiner Zone, aber das macht es zu einem UTC / GMT-Zonen-Zeitstempel. Verwenden Sie Ihre eigene Zone oder% z /% Z, indem Sie
${TZ:-$(date +%z)}
stattdessen den Zeitstempel anhängen .)Durch Hinzufügen zusätzlicher Zeitbegriffe für diese Formulare wird die Zeit angepasst:
Viele komplexe Anpassungen, in beliebiger Reihenfolge, können verwendet werden (obwohl relative und variable Begriffe wie "14 Wochen ab dem letzten Montag" Probleme bereiten ;-)
(Es gibt auch hier eine andere kleine Bärenfalle,
date
die immer ein gültiges Datumdate -d "2019-01-31 1 month"
angibt, also gibt sie 2019-03-03 an, ebenso wie "nächsten Monat".)Angesichts der Vielzahl der unterstützten Zeit- und Datumsformate ist das Parsen von Zeitzonen zwangsläufig schlampig: Es kann sich um ein Einzel- oder Mehrfachbuchstaben-Suffix, einen Stunden- oder Stunden-Minuten-Versatz, einen Namen "America / Denver" (oder sogar einen Dateinamen) handeln im Fall der
TZ
Variablen).Ihre
2018-12-10T00:00:00
Version funktioniert nicht, weil "T" nur ein Begrenzer und keine Zeitzone ist. Wenn Sie am Ende "Z" hinzufügen, funktioniert dies (abhängig von der Richtigkeit der ausgewählten Zone) ebenfalls wie erwartet.Siehe: https://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html und insbesondere Abschnitt 7.7.
quelle
date -d "2018-12-10 00:00:00 now -5 hours
odertoday
oder0 hour
stattnow
, irgendetwas , das sagt ,date
dass das Token nach der Zeit ist keine Zeitzone gegenüber .Diese Lösung ist leicht zu verstehen, aber etwas komplizierter, weshalb ich sie als Shellscript zeige.
date
KommandozeileShell-Skript:
quelle