ts
es una biblioteca de fecha y hora para Emacs. Su objetivo es ser más conveniente que patrones como (string-to-number (format-time-string "%Y"))
al proporcionar accesos fáciles, como (ts-year (ts-now))
.
Para mejorar el rendimiento (significativamente), las partes de fecha formateadas se calculan de forma diferida en lugar de cuando se crea una instancia de un objeto de marca de tiempo, y las partes calculadas luego se almacenan en caché para acceder a ellas más tarde sin volver a calcularlas. Detrás de escena, esto evita llamadas innecesarias (string-to-number (format-time-string...
, que son sorprendentemente caras.
Obtener partes de la fecha actual:
; ; 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"
Incrementar la fecha actual:
; ; 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")
¿Qué día de la semana fue hace 2 días?
(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"
Obtenga la marca de tiempo para esta época la semana pasada:
(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")
Algunos descriptores de acceso tienen alias similares a los constructores format-time-string
:
(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
Analiza una cadena en un objeto de marca de tiempo y formatéala:
(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"
Formatee la diferencia entre dos marcas de tiempo:
(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"
Analice un elemento de marca de tiempo de organización directamente desde org-element-context
y encuentre la diferencia entre este y ahora:
( 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"
Analice una cadena de marca de tiempo de la organización (que tiene un repetidor) y formatee el año y el mes:
; ; 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"
¿Hace cuánto tiempo fue esta fecha en 1970?
( 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")
¿Hace cuánto comenzó la época?
(ts-human-format-duration
(ts-diff (ts-now) (make-ts :unix 0 )))
; ;=> "49 years, 227 days, 12 hours, 12 minutes, 30 seconds"
¿En cuál de los últimos 100 años la Navidad fue en sábado?
( 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)
Para poner un ejemplo más interesante, ¿una marca de tiempo cae dentro de la semana calendario anterior?
; ; 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
struct STRUCT
.ts-H (STRUCT)
ts
struct STRUCT
.ts-M (STRUCT)
ts
struct STRUCT
.ts-S (STRUCT)
ts
struct STRUCT
.ts-Y (STRUCT)
ts
struct STRUCT
.ts-b (STRUCT)
ts
struct STRUCT
.ts-d (STRUCT)
ts
struct STRUCT
.ts-day (STRUCT)
ts
struct STRUCT
.ts-day-abbr (STRUCT)
ts
struct STRUCT
.ts-day-name (STRUCT)
ts
struct STRUCT
.ts-day-of-month-num (STRUCT)
ts
struct STRUCT
.ts-day-of-week-abbr (STRUCT)
ts
struct STRUCT
.ts-day-of-week-name (STRUCT)
ts
struct STRUCT
.ts-day-of-week-num (STRUCT)
ts
struct STRUCT
.ts-day-of-year (STRUCT)
ts
struct STRUCT
.ts-dom (STRUCT)
ts
struct STRUCT
.ts-dow (STRUCT)
ts
struct STRUCT
.ts-doy (STRUCT)
ts
struct STRUCT
.ts-hour (STRUCT)
ts
struct STRUCT
.ts-internal (STRUCT)
ts
struct STRUCT
. Slot representa un valor de tiempo interno de Emacs (por ejemplo, según lo devuelto por current-time
).ts-m (STRUCT)
ts
struct STRUCT
.ts-min (STRUCT)
ts
struct STRUCT
.ts-minute (STRUCT)
ts
struct STRUCT
.ts-month (STRUCT)
ts
struct STRUCT
.ts-month-abbr (STRUCT)
ts
struct STRUCT
.ts-month-name (STRUCT)
ts
struct 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
struct STRUCT
.ts-tz-offset (STRUCT)
ts
struct STRUCT
.ts-unix (STRUCT)
ts
struct STRUCT
.ts-week (STRUCT)
ts
struct STRUCT
.ts-week-of-year (STRUCT)
ts
struct STRUCT
.ts-woy (STRUCT)
ts
struct STRUCT
.ts-year (STRUCT)
ts
struct STRUCT
. ts-apply (&rest SLOTS TS)
TS
con nuevos valores de ranura. Complete los espacios de marca de tiempo, sobrescriba los valores de espacio dados y devuelva una nueva marca de tiempo con el valor de marca de tiempo de Unix derivado de los nuevos valores de espacio. SLOTS
es una lista de pares clave-valor alternos como la que se pasa a make-ts
.ts-adjust (&rest ADJUSTMENTS)
ADJUSTMENTS
a TS
. ADJUSTMENTS
deben ser una serie de SLOTS
y VALUES
alternos para ajustarlos. Por ejemplo, este formulario devuelve una nueva marca de tiempo que corresponde a 47 horas en el futuro: (ts-adjust 'hour -1 'day +2 (ts-now))
Dado que el argumento de la marca de tiempo es el último, es adecuado para su uso en una macro de subprocesamiento.
ts-dec (SLOT VALUE TS)
TS
con su SLOT
disminuido en VALUE
. SLOT
debe especificarse como un símbolo simple, no como una palabra clave.ts-inc (SLOT VALUE TS)
TS
con su SLOT
incrementado en VALUE
. SLOT
debe especificarse como un símbolo simple, no como una palabra clave.ts-update (TS)
TS
después de actualizar su marca de tiempo Unix desde sus otras ranuras. No destructivo. Para usarse después de configurar ranuras con, por ejemplo, ts-fill
.Destructivo
ts-adjustf (TS &rest ADJUSTMENTS)
TS
después de haber aplicado ADJUSTMENTS
. Esta función es destructiva, ya que llama setf
en TS
. ADJUSTMENTS
deben ser una serie de SLOTS
y VALUES
alternos para ajustarlos. Por ejemplo, este formulario ajusta una marca de tiempo a 47 horas en el futuro:
(let ((ts (ts-now))) (ts-adjustf ts 'hour -1 'day +2))
ts-decf (PLACE &optional (VALUE 1))
PLACE
por VALUE
(predeterminado 1), actualice su marca de tiempo Unix y devuelva el nuevo valor de PLACE
.ts-incf (PLACE &optional (VALUE 1))
PLACE
por VALUE
(predeterminado 1), actualice su marca de tiempo Unix y devuelva el nuevo valor de PLACE
. ts-in (BEG END TS)
TS
está dentro del rango BEG
a END
, inclusive. Todos los argumentos deben ser estructuras ts
.ts< (AB)
A
es menor que la marca de tiempo B
ts<= (AB)
A
es <= marca de tiempo B
.ts= (AB)
A
es la misma que la marca de tiempo B
Compara sólo las ranuras unix
de las marcas de tiempo. Tenga en cuenta que la ranura Unix de una marca de tiempo es flotante y puede diferir en menos de un segundo, lo que hace que no sean iguales incluso si todas las partes formateadas de la marca de tiempo son iguales.ts> (AB)
A
es mayor que la marca de tiempo B
ts>= (AB)
A
es >= marca de tiempo B
. ts-human-duration (SECONDS)
SECONDS
en años, días, horas, minutos y segundos. Este es un cálculo simple que no tiene en cuenta los años bisiestos, los segundos intercalares, etc.ts-human-format-duration (SECONDS &optional ABBREVIATE)
SECONDS
. Si SECONDS
es menor que 1, devuelve "0 seconds"
. Si ABBREVIATE
no es nulo, devuelve una versión más corta, sin espacios. Este es un cálculo simple que no tiene en cuenta los años bisiestos, los segundos intercalares, etc. ts-format (&optional TS-OR-FORMAT-STRING TS)
format-time-string
. Si TS-OR-FORMAT-STRING
es una marca de tiempo o nula, use el valor de ts-default-format
. Si tanto TS-OR-FORMAT-STRING
como TS
son nulos, use la hora actual. ts-parse (STRING)
ts
, analizando STRING
con parse-time-string
.ts-parse-fill (FILL STRING)
ts
, analizando STRING
con parse-time-string
. Los valores de hora/minuto/segundo vacíos se rellenan según FILL
: si begin
, con 0; si end
, la hora se completa con 23 y el minuto/segundo con 59; si es nulo, se puede señalar un error cuando los valores de tiempo están vacíos. Tenga en cuenta que cuando FILL
end
, un valor de tiempo como “12:12” se completa hasta “12:12:00”, no “12:12:59”.ts-parse-org (ORG-TS-STRING)
ORG-TS-STRING
. Tenga en cuenta que se llama a la función org-parse-time-string
, que debe cargarse antes de llamar a esta función.ts-parse-org-fill (FILL ORG-TS-STRING)
ORG-TS-STRING
. Tenga en cuenta que se llama a la función org-parse-time-string
, que debe cargarse antes de llamar a esta función. Los valores de hora/minuto/segundo se completan según FILL
: si begin
, con 0; si end
, la hora se completa con 23 y el minuto/segundo con 59. Tenga en cuenta que org-parse-time-string
no admite marcas de tiempo que contengan segundos.ts-parse-org-element (ELEMENT)
ELEMENT
. El elemento debe ser como uno analizado por org-element
, cuyo primer elemento es timestamp
. Se supone que la marca de tiempo no es un rango. copy-ts (TS)
TS
de marca de tiempo.ts-difference (AB)
A
y B
ts-diff
ts-difference
.ts-fill (TS &optional ZONE)
TS
habiendo llenado todos los espacios desde su marca de tiempo Unix. Esto no es destructivo. ZONE
se pasa a format-time-string
, que ver.ts-now
ts
establecida en ahora.ts-p (STRUCT)
ts-reset (TS)
TS
con todas las ranuras vacías excepto unix
. No destructivo. Lo mismo que: (make-ts :unix (ts-unix ts))
ts-defstruct (&rest ARGS)
cl-defstruct
, pero con opciones de ranura adicionales.Opciones y valores de tragamonedas adicionales:
:accessor-init
: un sexp que inicializa la ranura en el descriptor de acceso si la ranura es nula. La struct
de símbolo estará vinculada a la estructura actual. El descriptor de acceso se define después de que la estructura esté completamente definida, por lo que puede hacer referencia a la definición de la estructura (por ejemplo, utilizando la macro cl-struct
pcase
).
:aliases
: A
lista de símbolos que tendrán un alias para el descriptor de acceso de la ranura, precedido por el nombre de la estructura (por ejemplo, una estructura ts
con year
de la ranura y el alias y
crearía un alias ts-y
).
ts-human-format-duration
vs. format-seconds
Emacs tiene una función incorporada, format-seconds
, que produce una salida similar a la de ts-human-format-duration
. Su salida también es controlable con una cadena de formato. Sin embargo, si la salida de ts-human-format-duration
es suficiente, funciona mucho mejor que format-seconds
. Este simple punto de referencia, ejecutado 100.000 veces, muestra que se ejecuta mucho más rápido y genera menos basura:
(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 ))))
Forma | x más rápido que el siguiente | Tiempo de ejecución total | # de GC | Tiempo de ejecución total del GC |
---|---|---|---|---|
ts-humano-formato-duración | 5.82 | 0.832945 | 3 | 0.574929 |
formato-segundos | el más lento | 4.848253 | 17 | 3.288799 |
(Consulte el Manual del desarrollador de paquetes de Emacs para conocer la macro bench-multi-lexical
).
Agregado
ts-fill
acepta un argumento ZONE
, como el que se pasa a format-time-string
, que ver. Fijado
ts-human-format-duration
devolvió una cadena vacía con una duración inferior a 1 segundo (ahora devuelve "0 seconds"
). Agregado
ts-parse-fill
y ts-parse-org-fill
.ts-in
.Cambió
ts-now
ya no está incluida. Esto permite cambiarlo en tiempo de ejecución, por ejemplo, con cl-letf
, lo cual es útil en las pruebas.Fijado
ts-fill
. (La función split-string
, que se llama en ella, modifica los datos de coincidencia).ts-parse-org
. (La función org-parse-time-string
, que se llama en ella, modifica los datos de coincidencia).Documentación
Primer lanzamiento etiquetado. Publicado en MELPA.
GPLv3