ts
adalah perpustakaan tanggal dan waktu untuk Emacs. Ini bertujuan untuk menjadi lebih nyaman daripada pola seperti (string-to-number (format-time-string "%Y"))
dengan menyediakan pengakses yang mudah, seperti (ts-year (ts-now))
.
Untuk meningkatkan kinerja (secara signifikan), bagian tanggal yang diformat dihitung dengan lambat dibandingkan ketika objek stempel waktu dipakai, dan bagian yang dihitung kemudian di-cache untuk akses selanjutnya tanpa menghitung ulang. Di balik layar, ini menghindari panggilan (string-to-number (format-time-string...
yang tidak perlu, yang ternyata sangat mahal.
Dapatkan bagian dari tanggal saat ini:
; ; 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"
Tambahkan tanggal saat ini:
; ; 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")
Hari apa dalam seminggu 2 hari yang lalu?
(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"
Dapatkan stempel waktu untuk kali ini minggu lalu:
(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")
Beberapa pengakses memiliki alias yang mirip dengan konstruktor 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
Parsing string menjadi objek stempel waktu dan format ulang:
(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"
Format perbedaan antara dua stempel waktu:
(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"
Parsing elemen stempel waktu Organisasi langsung dari org-element-context
dan temukan perbedaan antara elemen tersebut dan sekarang:
( 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"
Parsing string stempel waktu Organisasi (yang memiliki repeater) dan format tahun dan bulan:
; ; 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"
Berapa lama tanggal ini pada tahun 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")
Berapa lama zaman ini dimulai?
(ts-human-format-duration
(ts-diff (ts-now) (make-ts :unix 0 )))
; ;=> "49 years, 227 days, 12 hours, 12 minutes, 30 seconds"
Dalam 100 tahun terakhir, Natal manakah yang jatuh pada hari Sabtu?
( 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)
Untuk contoh yang lebih menarik, apakah stempel waktu termasuk dalam minggu kalender sebelumnya?
; ; 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 mewakili nilai waktu internal Emacs (misalnya yang dikembalikan oleh 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
dengan nilai slot baru. Isi slot stempel waktu, timpa nilai slot yang diberikan, dan kembalikan stempel waktu baru dengan nilai stempel waktu Unix yang berasal dari nilai slot baru. SLOTS
adalah daftar pasangan nilai kunci bergantian seperti yang diteruskan ke make-ts
.ts-adjust (&rest ADJUSTMENTS)
ADJUSTMENTS
ke TS
. ADJUSTMENTS
harus berupa rangkaian SLOTS
dan VALUES
yang bergantian untuk menyesuaikannya. Misalnya, formulir ini mengembalikan stempel waktu baru yaitu 47 jam ke depan: (ts-adjust 'hour -1 'day +2 (ts-now))
Karena argumen stempel waktu adalah yang terakhir, argumen ini cocok untuk digunakan dalam makro threading.
ts-dec (SLOT VALUE TS)
TS
dengan SLOT
-nya dikurangi VALUE
. SLOT
harus ditentukan sebagai simbol biasa, bukan kata kunci.ts-inc (SLOT VALUE TS)
TS
dengan SLOT
-nya ditambah VALUE
. SLOT
harus ditentukan sebagai simbol biasa, bukan kata kunci.ts-update (TS)
TS
setelah memperbarui stempel waktu Unix dari slot lainnya. Tidak merusak. Untuk digunakan setelah mengatur slot, misalnya ts-fill
.Merusak
ts-adjustf (TS &rest ADJUSTMENTS)
TS
yang telah menerapkan ADJUSTMENTS
. Fungsi ini bersifat destruktif, karena memanggil setf
pada TS
. ADJUSTMENTS
harus berupa rangkaian SLOTS
dan VALUES
yang bergantian untuk menyesuaikannya. Misalnya, formulir ini menyesuaikan stempel waktu menjadi 47 jam ke depan:
(let ((ts (ts-now))) (ts-adjustf ts 'hour -1 'day +2))
ts-decf (PLACE &optional (VALUE 1))
PLACE
sebanyak VALUE
(default 1), perbarui stempel waktu Unix, dan kembalikan nilai baru PLACE
.ts-incf (PLACE &optional (VALUE 1))
PLACE
sebanyak VALUE
(default 1), perbarui stempel waktu Unix, dan kembalikan nilai baru PLACE
. ts-in (BEG END TS)
TS
berada dalam jangkauan BEG
hingga END
, inklusif. Semua argumen harus berupa ts
struct.ts< (AB)
A
lebih kecil dari stempel waktu B
.ts<= (AB)
A
adalah <= stempel waktu B
.ts= (AB)
A
sama dengan stempel waktu B
. Hanya membandingkan slot unix
stempel waktu. Perhatikan bahwa slot Unix stempel waktu berbentuk float dan mungkin berbeda kurang dari satu detik, menyebabkan slot tersebut tidak sama meskipun semua bagian stempel waktu yang diformat sama.ts> (AB)
A
lebih besar dari stempel waktu B
.ts>= (AB)
A
adalah >= stempel waktu B
. ts-human-duration (SECONDS)
SECONDS
dalam tahun, hari, jam, menit, dan detik. Ini adalah perhitungan sederhana yang tidak memperhitungkan tahun kabisat, detik kabisat, dan sebagainya.ts-human-format-duration (SECONDS &optional ABBREVIATE)
SECONDS
. Jika SECONDS
kurang dari 1, kembalikan "0 seconds"
. Jika ABBREVIATE
bukan nihil, kembalikan versi yang lebih pendek, tanpa spasi. Ini adalah perhitungan sederhana yang tidak memperhitungkan tahun kabisat, detik kabisat, dan sebagainya. ts-format (&optional TS-OR-FORMAT-STRING TS)
format-time-string
. Jika TS-OR-FORMAT-STRING
adalah stempel waktu atau nihil, gunakan nilai ts-default-format
. Jika TS-OR-FORMAT-STRING
dan TS
keduanya nihil, gunakan waktu saat ini. ts-parse (STRING)
ts
baru, parsing STRING
dengan parse-time-string
.ts-parse-fill (FILL STRING)
ts
baru, parsing STRING
dengan parse-time-string
. Nilai jam/menit/detik yang kosong diisi sesuai dengan FILL
: if begin
, dengan 0; jika end
, jam diisi 23 dan menit/detik diisi 59; jika nihil, kesalahan mungkin ditandai ketika nilai waktu kosong. Perhatikan bahwa ketika FILL
adalah end
, nilai waktu seperti “12:12” diisi menjadi “12:12:00”, bukan “12:12:59”.ts-parse-org (ORG-TS-STRING)
ORG-TS-STRING
. Perhatikan bahwa fungsi org-parse-time-string
dipanggil, yang harus dimuat sebelum memanggil fungsi ini.ts-parse-org-fill (FILL ORG-TS-STRING)
ORG-TS-STRING
. Perhatikan bahwa fungsi org-parse-time-string
dipanggil, yang harus dimuat sebelum memanggil fungsi ini. Nilai jam/menit/detik diisi sesuai dengan FILL
: if begin
, dengan 0; jika end
, jam diisi dengan 23 dan menit/detik dengan 59. Perhatikan bahwa org-parse-time-string
tidak mendukung stempel waktu yang berisi detik.ts-parse-org-element (ELEMENT)
ELEMENT
. Elemen harus seperti yang diurai oleh org-element
, elemen pertama adalah timestamp
. Asumsikan stempel waktu bukanlah rentang. copy-ts (TS)
TS
.ts-difference (AB)
A
dan B
.ts-diff
ts-difference
.ts-fill (TS &optional ZONE)
TS
setelah mengisi semua slot dari stempel waktu Unix-nya. Ini tidak merusak. ZONE
diteruskan ke format-time-string
, yang dilihat.ts-now
ts
struct yang disetel ke sekarang.ts-p (STRUCT)
ts-reset (TS)
TS
dengan semua slot dibersihkan kecuali unix
. Tidak merusak. Sama seperti: (make-ts :unix (ts-unix ts))
ts-defstruct (&rest ARGS)
cl-defstruct
, tetapi dengan opsi slot tambahan.Opsi dan nilai slot tambahan:
:accessor-init
: sexp yang menginisialisasi slot di accessor jika slotnya nihil. Simbol struct
akan terikat pada struct saat ini. Pengakses didefinisikan setelah struct didefinisikan sepenuhnya, sehingga dapat merujuk pada definisi struct (misalnya dengan menggunakan makro cl-struct
pcase
).
:aliases
: A
simbol yang akan diberi alias ke pengakses slot, diawali dengan nama struct (misalnya struct ts
dengan slot year
dan alias y
akan membuat alias ts-y
).
ts-human-format-duration
vs. format-seconds
Emacs memiliki fungsi bawaan, format-seconds
, yang menghasilkan keluaran serupa dengan ts-human-format-duration
. Outputnya juga dapat dikontrol dengan format string. Namun, jika keluaran ts-human-format-duration
mencukupi, kinerjanya jauh lebih baik daripada format-seconds
. Tolok ukur sederhana ini, yang dijalankan 100.000 kali, menunjukkan bahwa ia berjalan jauh lebih cepat dan menghasilkan lebih sedikit sampah:
(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 ))))
Membentuk | x lebih cepat dari berikutnya | Total waktu proses | # GC | Total waktu proses GC |
---|---|---|---|---|
ts-durasi-format-manusia | 5.82 | 0,832945 | 3 | 0,574929 |
format-detik | paling lambat | 4.848253 | 17 | 3.288799 |
(Lihat Buku Panduan Pengembang Paket Emacs untuk makro bench-multi-lexical
.)
Ditambahkan
ts-fill
menerima argumen ZONE
, seperti yang diteruskan ke format-time-string
, yang dilihat. Tetap
ts-human-format-duration
mengembalikan string kosong dengan durasi kurang dari 1 detik (sekarang mengembalikan "0 seconds"
). Ditambahkan
ts-parse-fill
dan ts-parse-org-fill
.ts-in
.Berubah
ts-now
tidak lagi sebaris. Hal ini memungkinkan untuk diubah pada saat runtime dengan, misalnya cl-letf
, yang berguna dalam pengujian.Tetap
ts-fill
. (Fungsi split-string
, yang dipanggil di dalamnya, mengubah data kecocokan.)ts-parse-org
. (Fungsi org-parse-time-string
, yang dipanggil di dalamnya, mengubah data kecocokan.)Dokumentasi
Rilis yang diberi tag pertama. Diterbitkan ke MELPA.
GPLv3