ts
ist eine Datums- und Uhrzeitbibliothek für Emacs. Es soll praktischer sein als Muster wie (string-to-number (format-time-string "%Y"))
indem es einfache Zugriffsfunktionen wie (ts-year (ts-now))
bereitstellt.
Um die Leistung (erheblich) zu verbessern, werden formatierte Datumsteile verzögert berechnet und nicht erst, wenn ein Zeitstempelobjekt instanziiert wird. Die berechneten Teile werden dann für den späteren Zugriff ohne Neuberechnung zwischengespeichert. Hinter den Kulissen werden dadurch unnötige (string-to-number (format-time-string...
-Aufrufe vermieden, die überraschend teuer sind.
Teile des aktuellen Datums abrufen:
; ; When the current date is 2018-12-08 23:09:14 -0600:
(ts-year (ts-now)) ; => 2018
(ts-month (ts-now)) ; => 12
(ts-day (ts-now)) ; => 8
(ts-hour (ts-now)) ; => 23
(ts-minute (ts-now)) ; => 9
(ts-second (ts-now)) ; => 14
(ts-tz-offset (ts-now)) ; => "-0600"
(ts-dow (ts-now)) ; => 6
(ts-day-abbr (ts-now)) ; => "Sat"
(ts-day-name (ts-now)) ; => "Saturday"
(ts-month-abbr (ts-now)) ; => "Dec"
(ts-month-name (ts-now)) ; => "December"
(ts-tz-abbr (ts-now)) ; => "CST"
Erhöhen Sie das aktuelle Datum:
; ; By 10 years:
( list :now (ts-format)
:future (ts-format (ts-adjust 'year 10 (ts-now))))
; ;=> ( :now "2018-12-15 22:00:34 -0600"
; ; :future "2028-12-15 22:00:34 -0600")
; ; By 10 years, 2 months, 3 days, 5 hours, and 4 seconds:
( list :now (ts-format)
:future (ts-format
(ts-adjust 'year 10 'month 2 'day 3
'hour 5 'second 4
(ts-now))))
; ;=> ( :now "2018-12-15 22:02:31 -0600"
; ; :future "2029-02-19 03:02:35 -0600")
Welcher Wochentag war vor 2 Tagen?
(ts-day-name (ts-dec 'day 2 (ts-now))) ; => "Thursday"
; ; Or, with threading macros:
( thread-last (ts-now) (ts-dec 'day 2 ) ts-day-name) ; => "Thursday"
(-> > (ts-now) (ts-dec 'day 2 ) ts-day-name) ; => "Thursday"
Holen Sie sich den Zeitstempel für diese Zeit letzte Woche:
(ts-unix (ts-adjust 'day -7 (ts-now)))
; ;=> 1543728398.0
; ; To confirm that the difference really is 7 days:
( / ( - (ts-unix (ts-now))
(ts-unix (ts-adjust 'day -7 (ts-now))))
86400 )
; ;=> 7.000000567521762
; ; Or human-friendly as a list:
(ts-human-duration
(ts-difference (ts-now)
(ts-dec 'day 7 (ts-now))))
; ;=> (:years 0 :days 7 :hours 0 :minutes 0 :seconds 0)
; ; Or as a string:
(ts-human-format-duration
(ts-difference (ts-now)
(ts-dec 'day 7 (ts-now))))
; ;=> "7 days"
; ; Or confirm by formatting:
( list :now (ts-format)
:last-week (ts-format (ts-dec 'day 7 (ts-now))))
; ;=> ( :now "2018-12-08 23:31:37 -0600"
; ; :last-week "2018-12-01 23:31:37 -0600")
Einige Accessoren haben Aliase, die format-time-string
Konstruktoren ähneln:
(ts-hour (ts-now)) ; => 0
(ts-H (ts-now)) ; => 0
(ts-minute (ts-now)) ; => 56
(ts-min (ts-now)) ; => 56
(ts-M (ts-now)) ; => 56
(ts-second (ts-now)) ; => 38
(ts-sec (ts-now)) ; => 38
(ts-S (ts-now)) ; => 38
(ts-year (ts-now)) ; => 2018
(ts-Y (ts-now)) ; => 2018
(ts-month (ts-now)) ; => 12
(ts-m (ts-now)) ; => 12
(ts-day (ts-now)) ; => 9
(ts-d (ts-now)) ; => 9
Analysieren Sie eine Zeichenfolge in ein Zeitstempelobjekt und formatieren Sie es neu:
(ts-format (ts-parse " sat dec 8 2018 12:12:12 " )) ; => "2018-12-08 12:12:12 -0600"
; ; With a threading macro:
(-> > " sat dec 8 2018 12:12:12 "
ts-parse
ts-format) ; ;=> "2018-12-08 12:12:12 -0600"
Formatieren Sie die Differenz zwischen zwei Zeitstempeln:
(ts-human-format-duration
(ts-difference (ts-now)
(ts-adjust 'day -400
'hour -2 'minute -1 'second -5
(ts-now))))
; ; => "1 years, 35 days, 2 hours, 1 minutes, 5 seconds"
; ; Abbreviated:
(ts-human-format-duration
(ts-difference (ts-now)
(ts-adjust 'day -400
'hour -2 'minute -1 'second -5
(ts-now)))
'abbr )
; ; => "1y35d2h1m5s"
Analysieren Sie ein Org-Zeitstempelelement direkt aus org-element-context
und finden Sie den Unterschied zwischen ihm und jetzt:
( with-temp-buffer
( org-mode )
( save-excursion
( insert " <2015-09-24 Thu .+1d> " ))
(ts-human-format-duration
(ts-difference (ts-now)
(ts-parse-org-element ( org-element-context )))))
; ;=> "3 years, 308 days, 2 hours, 24 minutes, 21 seconds"
Analysieren Sie eine Org-Zeitstempelzeichenfolge (die einen Repeater hat) und formatieren Sie Jahr und Monat:
; ; Note the use of `format' rather than `concat' , because `ts-year'
; ; returns the year as a number rather than a string.
( let* ((ts (ts-parse-org " <2015-09-24 Thu .+1d> " )))
( format " %s , %s " (ts-month-name ts) (ts-year ts)))
; ;=> "September, 2015"
; ; Or, using dash.el:
(-- > (ts-parse-org " <2015-09-24 Thu .+1d> " )
( format " %s , %s " (ts-month-name it) (ts-year it)))
; ;=> "September, 2015"
; ; Or, if you remember the format specifiers:
(ts-format " %B, %Y " (ts-parse-org " <2015-09-24 Thu .+1d> " ))
; ;=> "September, 2015"
Wie lange ist dieses Datum im Jahr 1970 her?
( let* ((now (ts-now))
(then (ts-apply :year 1970 now)))
( list (ts-format then)
(ts-human-format-duration
(ts-difference now then))))
; ;=> ("1970-08-04 07:07:10 -0500"
; ; "49 years, 12 days")
Wie lange ist es her, dass die Epoche begann?
(ts-human-format-duration
(ts-diff (ts-now) (make-ts :unix 0 )))
; ;=> "49 years, 227 days, 12 hours, 12 minutes, 30 seconds"
In welchem der letzten 100 Jahre war Weihnachten ein Samstag?
( let ((ts (ts-parse " 2019-12-25 " ))
(limit ( - (ts-year (ts-now)) 100 )))
( cl-loop while ( >= (ts-year ts) limit)
when ( string= " Saturday " (ts-day-name ts))
collect (ts-year ts)
do (ts-decf (ts-year ts))))
; ;=> (2010 2004 1999 1993 1982 1976 1971 1965 1954 1948 1943 1937 1926 1920)
Ein interessanteres Beispiel: Fällt ein Zeitstempel in die vorherige Kalenderwoche?
; ; First, define a function to return the range of the previous calendar week.
( defun last-week-range ()
" Return timestamps (BEG . END) spanning the previous calendar week. "
( let* ( ; ; Bind `now' to the current timestamp to ensure all calculations
; ; begin from the same timestamp. (In the unlikely event that
; ; the execution of this code spanned from one day into the next,
; ; that would cause a wrong result.)
(now (ts-now))
; ; We start by calculating the offsets for the beginning and
; ; ending timestamps using the current day of the week. Note
; ; that the `ts-dow' slot uses the "%w" format specifier, which
; ; counts from Sunday to Saturday as a number from 0 to 6.
(adjust-beg-day ( - ( + 7 (ts-dow now))))
(adjust-end-day ( - ( - 7 ( - 6 (ts-dow now)))))
; ; Make beginning/end timestamps based on `now' , with adjusted
; ; day and hour/minute/second values. These functions return
; ; new timestamps, so `now' is unchanged.
(beg ( thread-last now
; ; `ts-adjust' makes relative adjustments to timestamps.
(ts-adjust 'day adjust-beg-day)
; ; `ts-apply' applies absolute values to timestamps.
(ts-apply :hour 0 :minute 0 :second 0 )))
(end ( thread-last now
(ts-adjust 'day adjust-end-day)
(ts-apply :hour 23 :minute 59 :second 59 ))))
( cons beg end)))
(-let* ( ; ; Bind the default format string for `ts-format' , so the
; ; results are easy to understand.
(ts-default-format " %a, %Y-%m-%d %H:%M:%S %z " )
; ; Get the timestamp for 3 days before now.
(check-ts (ts-adjust 'day -3 (ts-now)))
; ; Get the range for the previous week from the function we defined.
((beg . end) (last-week-range)))
( list :last-week-beg (ts-format beg)
:check-ts (ts-format check-ts)
:last-week-end (ts-format end)
:in-range-p (ts-in beg end check-ts)))
; ;=> (:last-week-beg "Sun, 2019-08-04 00:00:00 -0500"
; ; :check-ts "Fri, 2019-08-09 10:00:34 -0500"
; ; :last-week-end "Sat, 2019-08-10 23:59:59 -0500"
; ; :in-range-p t)
ts-B (STRUCT)
ts
Struktur STRUCT
.ts-H (STRUCT)
ts
-Struktur STRUCT
.ts-M (STRUCT)
ts
-Struktur STRUCT
.ts-S (STRUCT)
ts
struct STRUCT
.ts-Y (STRUCT)
ts
Struktur STRUCT
.ts-b (STRUCT)
ts
Struktur STRUCT
.ts-d (STRUCT)
ts
-Struktur STRUCT
.ts-day (STRUCT)
ts
-Struktur STRUCT
.ts-day-abbr (STRUCT)
ts
Struktur STRUCT
.ts-day-name (STRUCT)
ts
struct STRUCT
.ts-day-of-month-num (STRUCT)
ts
-Struktur STRUCT
.ts-day-of-week-abbr (STRUCT)
ts
Struktur STRUCT
.ts-day-of-week-name (STRUCT)
ts
struct STRUCT
.ts-day-of-week-num (STRUCT)
ts
-Struktur STRUCT
.ts-day-of-year (STRUCT)
ts
-Struktur STRUCT
.ts-dom (STRUCT)
ts
-Struktur STRUCT
.ts-dow (STRUCT)
ts
-Struktur STRUCT
.ts-doy (STRUCT)
ts
-Struktur STRUCT
.ts-hour (STRUCT)
ts
-Struktur STRUCT
.ts-internal (STRUCT)
ts
struct STRUCT
. Slot stellt einen Emacs-internen Zeitwert dar (z. B. wie von current-time
zurückgegeben).ts-m (STRUCT)
ts
struct STRUCT
.ts-min (STRUCT)
ts
-Struktur STRUCT
.ts-minute (STRUCT)
ts
-Struktur STRUCT
.ts-month (STRUCT)
ts
struct STRUCT
.ts-month-abbr (STRUCT)
ts
Struktur STRUCT
.ts-month-name (STRUCT)
ts
Struktur STRUCT
.ts-month-num (STRUCT)
ts
struct STRUCT
.ts-moy (STRUCT)
ts
struct STRUCT
.ts-sec (STRUCT)
ts
struct STRUCT
.ts-second (STRUCT)
ts
struct STRUCT
.ts-tz-abbr (STRUCT)
ts
Struktur STRUCT
.ts-tz-offset (STRUCT)
ts
struct STRUCT
.ts-unix (STRUCT)
ts
struct STRUCT
.ts-week (STRUCT)
ts
-Struktur STRUCT
.ts-week-of-year (STRUCT)
ts
-Struktur STRUCT
.ts-woy (STRUCT)
ts
-Struktur STRUCT
.ts-year (STRUCT)
ts
Struktur STRUCT
. ts-apply (&rest SLOTS TS)
TS
mit neuen Slot-Werten zurück. Füllen Sie Zeitstempel-Slots, überschreiben Sie gegebene Slot-Werte und geben Sie einen neuen Zeitstempel mit dem aus neuen Slot-Werten abgeleiteten Unix-Zeitstempelwert zurück. SLOTS
ist eine Liste abwechselnder Schlüssel-Wert-Paare, wie sie an make-ts
übergeben werden.ts-adjust (&rest ADJUSTMENTS)
ADJUSTMENTS
auf TS
angewendet wurden. ADJUSTMENTS
sollten eine Reihe abwechselnder SLOTS
und VALUES
sein, anhand derer sie angepasst werden können. Dieses Formular gibt beispielsweise einen neuen Zeitstempel zurück, der 47 Stunden in der Zukunft liegt: (ts-adjust 'hour -1 'day +2 (ts-now))
Da das Zeitstempelargument das letzte ist, eignet es sich für die Verwendung in einem Threading-Makro.
ts-dec (SLOT VALUE TS)
TS
zurück, dessen SLOT
um VALUE
dekrementiert wird. SLOT
sollte als einfaches Symbol und nicht als Schlüsselwort angegeben werden.ts-inc (SLOT VALUE TS)
TS
zurück, dessen SLOT
um VALUE
erhöht ist. SLOT
sollte als einfaches Symbol und nicht als Schlüsselwort angegeben werden.ts-update (TS)
TS
zurück, nachdem er seinen Unix-Zeitstempel von seinen anderen Slots aktualisiert hat. Zerstörungsfrei. Zu verwenden nach dem Setzen von Slots mit z. B. ts-fill
.Zerstörerisch
ts-adjustf (TS &rest ADJUSTMENTS)
TS
zurück, nachdem ADJUSTMENTS
angewendet wurden. Diese Funktion ist destruktiv, da sie setf
auf TS
aufruft. ADJUSTMENTS
sollten eine Reihe abwechselnder SLOTS
und VALUES
sein, anhand derer sie angepasst werden können. Dieses Formular passt beispielsweise einen Zeitstempel auf 47 Stunden in der Zukunft an:
(let ((ts (ts-now))) (ts-adjustf ts 'hour -1 'day +2))
ts-decf (PLACE &optional (VALUE 1))
PLACE
um VALUE
(Standard 1), aktualisieren Sie seinen Unix-Zeitstempel und geben Sie den neuen Wert von PLACE
zurück.ts-incf (PLACE &optional (VALUE 1))
PLACE
um VALUE
(Standard 1), aktualisieren Sie seinen Unix-Zeitstempel und geben Sie den neuen Wert von PLACE
zurück. ts-in (BEG END TS)
TS
im Bereich BEG
bis END
(einschließlich) liegt. Alle Argumente sollten ts
Strukturen sein.ts< (AB)
A
kleiner als Zeitstempel B
ist.ts<= (AB)
A
<= Zeitstempel B
ist.ts= (AB)
A
mit Zeitstempel B
übereinstimmt. Vergleicht nur die unix
-Slots der Zeitstempel. Beachten Sie, dass der Unix-Slot eines Zeitstempels ein Float ist und sich um weniger als eine Sekunde unterscheiden kann, was dazu führt, dass sie ungleich sind, selbst wenn alle formatierten Teile des Zeitstempels gleich sind.ts> (AB)
A
größer als Zeitstempel B
ist.ts>= (AB)
A
>= Zeitstempel B
ist. ts-human-duration (SECONDS)
SECONDS
in Jahren, Tagen, Stunden, Minuten und Sekunden beschreibt. Dies ist eine einfache Berechnung, die keine Schaltjahre, Schaltsekunden usw. berücksichtigt.ts-human-format-duration (SECONDS &optional ABBREVIATE)
SECONDS
beschreibt. Wenn SECONDS
kleiner als 1 ist, wird "0 seconds"
zurückgegeben. Wenn ABBREVIATE
ungleich Null ist, wird eine kürzere Version ohne Leerzeichen zurückgegeben. Dies ist eine einfache Berechnung, die keine Schaltjahre, Schaltsekunden usw. berücksichtigt. ts-format (&optional TS-OR-FORMAT-STRING TS)
format-time-string
. Wenn TS-OR-FORMAT-STRING
ein Zeitstempel oder Null ist, verwenden Sie den Wert von ts-default-format
. Wenn sowohl TS-OR-FORMAT-STRING
als auch TS
Null sind, verwenden Sie die aktuelle Zeit. ts-parse (STRING)
ts
Struktur zurück und analysieren Sie STRING
mit parse-time-string
.ts-parse-fill (FILL STRING)
ts
Struktur zurück und analysieren Sie STRING
mit parse-time-string
. Leere Stunden-/Minuten-/Sekundenwerte werden gemäß FILL
gefüllt: wenn begin
, mit 0; wenn end
, wird die Stunde mit 23 und die Minute/Sekunde mit 59 gefüllt; Bei Null kann ein Fehler gemeldet werden, wenn die Zeitwerte leer sind. Beachten Sie, dass, wenn FILL
end
ist, ein Zeitwert wie „12:12“ auf „12:12:00“ und nicht auf „12:12:59“ aufgefüllt wird.ts-parse-org (ORG-TS-STRING)
ORG-TS-STRING
zurück. Beachten Sie, dass die Funktion org-parse-time-string
aufgerufen wird, die vor dem Aufruf dieser Funktion geladen werden sollte.ts-parse-org-fill (FILL ORG-TS-STRING)
ORG-TS-STRING
zurück. Beachten Sie, dass die Funktion org-parse-time-string
aufgerufen wird, die vor dem Aufruf dieser Funktion geladen werden sollte. Stunden-/Minuten-/Sekundenwerte werden gemäß FILL
gefüllt: wenn begin
, mit 0; Bei end
wird die Stunde mit 23 und die Minute/Sekunde mit 59 gefüllt. Beachten Sie, dass org-parse-time-string
keine Zeitstempel unterstützt, die Sekunden enthalten.ts-parse-org-element (ELEMENT)
ELEMENT
zurück. Das Element sollte einem von org-element
analysierten Element ähneln, dessen erstes Element timestamp
ist. Geht davon aus, dass der Zeitstempel kein Bereich ist. copy-ts (TS)
TS
zurück.ts-difference (AB)
A
und B
zurück.ts-diff
ts-difference
.ts-fill (TS &optional ZONE)
TS
zurück, nachdem er alle Slots seines Unix-Zeitstempels gefüllt hat. Dies ist zerstörungsfrei. ZONE
wird an format-time-string
übergeben, was zu sehen ist.ts-now
ts
Struktur zurück.ts-p (STRUCT)
ts-reset (TS)
TS
mit allen gelöschten Slots außer unix
zurück. Zerstörungsfrei. Das Gleiche wie: (make-ts :unix (ts-unix ts))
ts-defstruct (&rest ARGS)
cl-defstruct
, aber mit zusätzlichen Slot-Optionen.Zusätzliche Slot-Optionen und -Werte:
:accessor-init
: ein Sexp, der den Slot im Accessor initialisiert, wenn der Slot null ist. Die struct
wird an die aktuelle Struktur gebunden. Der Accessor wird definiert, nachdem die Struktur vollständig definiert ist, sodass er auf die Strukturdefinition verweisen kann (z. B. mithilfe des cl-struct
pcase
Makros).
:aliases
: A
Liste von Symbolen, die dem Slot-Accessor als Alias zugewiesen werden, mit vorangestelltem Strukturnamen (z. B. würde eine Struktur ts
mit Slot year
und Alias y
einen Alias ts-y
erstellen).
ts-human-format-duration
vs. format-seconds
Emacs verfügt über eine integrierte Funktion, format-seconds
, die eine ähnliche Ausgabe wie ts-human-format-duration
erzeugt. Seine Ausgabe ist auch mit einem Formatstring steuerbar. Wenn jedoch die Ausgabe von ts-human-format-duration
ausreicht, ist die Leistung deutlich besser als bei format-seconds
. Dieser einfache Benchmark, der 100.000 Mal ausgeführt wird, zeigt, dass er viel schneller läuft und weniger Müll erzeugt:
(bench-multi-lexical :times 100000
:forms (( " ts-human-format-duration " (ts-human-format-duration 15780.910933971405 t ))
( " format-seconds " ( format-seconds " %yy%dd%hh%mm%ss%z " 15780.910933971405 ))))
Bilden | x schneller als nächste | Gesamtlaufzeit | Anzahl der GCs | Gesamte GC-Laufzeit |
---|---|---|---|---|
ts-human-format-duration | 5,82 | 0,832945 | 3 | 0,574929 |
Format-Sekunden | am langsamsten | 4.848253 | 17 | 3.288799 |
(Informationen zum bench-multi-lexical
Makro finden Sie im Emacs Package Developer's Handbook.)
Hinzugefügt
ts-fill
akzeptiert ein ZONE
-Argument, wie es an format-time-string
übergeben wird, siehe. Behoben
ts-human-format-duration
hat für eine Dauer von weniger als 1 Sekunde eine leere Zeichenfolge zurückgegeben (gibt jetzt "0 seconds"
zurück). Hinzugefügt
ts-parse-fill
und ts-parse-org-fill
.ts-in
.Geändert
ts-now
ist nicht mehr inline. Dadurch kann es zur Laufzeit geändert werden, z. B. mit cl-letf
, was beim Testen hilfreich ist.Behoben
ts-fill
speichern. (Die darin aufgerufene Funktion split-string
verändert die Match-Daten.)ts-parse-org
speichern. (Die darin aufgerufene Funktion org-parse-time-string
modifiziert die Match-Daten.)Dokumentation
Erste getaggte Veröffentlichung. Veröffentlicht bei MELPA.
GPLv3