From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Adam Porter Newsgroups: gmane.emacs.bugs Subject: bug#71573: Related functions from ts.el Date: Mon, 17 Jun 2024 01:20:04 -0500 Message-ID: <0f564d69-2d04-49b9-935d-15ed8741c7ba@alphapapa.net> References: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="36657"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mozilla Thunderbird To: 71573@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Jun 17 08:21:13 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1sJ5jr-0009Jy-D7 for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 17 Jun 2024 08:21:13 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sJ5ji-00011d-L6; Mon, 17 Jun 2024 02:21:02 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sJ5jg-00011L-Kq for bug-gnu-emacs@gnu.org; Mon, 17 Jun 2024 02:21:00 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sJ5jg-0002IT-D1 for bug-gnu-emacs@gnu.org; Mon, 17 Jun 2024 02:21:00 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1sJ5ji-0007lU-4Q for bug-gnu-emacs@gnu.org; Mon, 17 Jun 2024 02:21:02 -0400 X-Loop: help-debbugs@gnu.org In-Reply-To: Resent-From: Adam Porter Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 17 Jun 2024 06:21:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 71573 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 71573-submit@debbugs.gnu.org id=B71573.171860521529789 (code B ref 71573); Mon, 17 Jun 2024 06:21:02 +0000 Original-Received: (at 71573) by debbugs.gnu.org; 17 Jun 2024 06:20:15 +0000 Original-Received: from localhost ([127.0.0.1]:59330 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sJ5iw-0007kO-U6 for submit@debbugs.gnu.org; Mon, 17 Jun 2024 02:20:15 -0400 Original-Received: from bonobo.banana.relay.mailchannels.net ([23.83.217.22]:58647) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sJ5is-0007kC-4Z for 71573@debbugs.gnu.org; Mon, 17 Jun 2024 02:20:13 -0400 X-Sender-Id: dreamhost|x-authsender|adam@alphapapa.net Original-Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id EC6314284D for <71573@debbugs.gnu.org>; Mon, 17 Jun 2024 06:20:05 +0000 (UTC) Original-Received: from pdx1-sub0-mail-a313.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 842CA427C0 for <71573@debbugs.gnu.org>; Mon, 17 Jun 2024 06:20:05 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1718605205; a=rsa-sha256; cv=none; b=x8ReSYWmlg8+V0IXhNqRGikRIzXdRKe9AIYd8TziYjbSJtgM1lCBIaydBilH5JyJrphUS0 49utZOVHOcDcdSOfiO7qR4DIZ86kZre1x0ffPSOP/GyUclutDhBEoxI/uBw1CPI9pntWYl NnJh1ETj1VXTz8Hbee7Eops+R5+b7r267STTAsChLLZxrtAkNSxQF770Dhs3m94elGuEnD mHT1rtLETD542g0Khc/tNQ/68QmXYSrkaTQa5QY7YbmdYO3gBqWsGyE+sIbcsKCvH9MOrK RQjomsEmINfXWm08/2Z5vCMWhfGjIZ4AdfPQuyAqjdVkmH0JhK/zWzQKpCgGPA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1718605205; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding:dkim-signature; bh=ZxiXVsF7QMEKEtzTG4MzsMiWpaT84kSc+T8AROwXUlk=; b=yPLLd0SfmFmcu2mFtrFaFNvHDwFBQOS7PRQAbTjmGG5xEIGqE4Hx4jEgi2iZO17Lg3r7yl VMC0UJ295F+zAM96xLFF6Z1h0K7YumuNR4un8uOedAXfUAsMhuYbOlTRTDpEaTNbH6dRuQ JaCtilIUzxSbUSy5EufzW86mL88Fui+6V1mpMS8sixvz2LiCekNuhbNe6W3B+1s72qUlin NII+w9IYvawAY5lqnV8WN0LZ4Fxc3TV7dNrzPhEhmkW9MY/PKL1UE/iruba0I54xnuHun9 EoQc6t6i6Gfd94PsCw66woX+TmIotewQl/n47YvQtR9ti9lY+aJYeVb5OERtYA== ARC-Authentication-Results: i=1; rspamd-79677bdb95-pq7kx; auth=pass smtp.auth=dreamhost smtp.mailfrom=adam@alphapapa.net X-Sender-Id: dreamhost|x-authsender|adam@alphapapa.net X-MC-Relay: Junk X-MailChannels-SenderId: dreamhost|x-authsender|adam@alphapapa.net X-MailChannels-Auth-Id: dreamhost X-Little-Invention: 674a568e2bcb89e5_1718605205749_541955930 X-MC-Loop-Signature: 1718605205749:385998355 X-MC-Ingress-Time: 1718605205749 Original-Received: from pdx1-sub0-mail-a313.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.121.33.136 (trex/6.9.2); Mon, 17 Jun 2024 06:20:05 +0000 Original-Received: from [10.144.73.185] (unknown [172.98.33.227]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: adam@alphapapa.net) by pdx1-sub0-mail-a313.dreamhost.com (Postfix) with ESMTPSA id 4W2fr51frcz6F for <71573@debbugs.gnu.org>; Sun, 16 Jun 2024 23:20:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alphapapa.net; s=dreamhost; t=1718605205; bh=ZxiXVsF7QMEKEtzTG4MzsMiWpaT84kSc+T8AROwXUlk=; h=Date:To:From:Subject:Content-Type:Content-Transfer-Encoding; b=Z2iFYTy/5EggbbMrxRctKmfuVQMLPBvtHj6YsAa3VZkcwiPr2isMnOgKzATHfbMmp XVhbCqImLBLSjqOUTrhbXXC06ZuJyvdHPEOrEhuCzno9uDepdR4Po/LqBG0CBnMrO1 rcjIijL10/BmM8FegxyxUpLc/LTxm1yImxarUQ5FNETlJUChVSAF9s0MLmlA82VBI1 QhVV6h5KvziXnbciSXndB5vaANF7CW9ZMAeiYVimKS19finne6hJjFaoRd8HNBqlXX wwllxgw1HeHvoNMWzTNhcFsxbdUxVpmPx0nx9UbpAFIHGA00SJXN9S+8J8TD2S5BnL jCDysX7KBvaqw== Content-Language: en-US X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:287359 Archived-At: Hi all, FWIW, my ts.el timestamp library has the related functions `ts-human-duration' and `ts-human-format-duration'. See and code below. They work a bit differently, but I've found them very useful in my other Elisp projects, and my profiling has shown that they perform very well relative to, e.g. the existing `format-seconds' function in terms of runtime and GC (see benchmarks in source comments). If any of the code in ts.el would be helpful, I'd be glad to contribute it to Emacs (some discussion about upstreaming parts of ts.el has also been going on in other, Org-related contexts). --Adam Elisp follows: (defun ts-human-duration (seconds) "Return plist describing duration SECONDS. List includes years, days, hours, minutes, and seconds. This is a simple calculation that does not account for leap years, leap seconds, etc." ;; TODO: Add weeks. (cl-macrolet ((dividef (place divisor) ;; Divide PLACE by DIVISOR, set PLACE to the remainder, and return the quotient. `(prog1 (/ ,place ,divisor) (setf ,place (% ,place ,divisor))))) (let* ((seconds (floor seconds)) (years (dividef seconds 31536000)) (days (dividef seconds 86400)) (hours (dividef seconds 3600)) (minutes (dividef seconds 60))) (list :years years :days days :hours hours :minutes minutes :seconds seconds)))) ;; See also the built-in function `format-seconds', which I seem to have ;; overlooked before writing this. However, a quick benchmark, run ;; 100,000 times, shows that, when controllable formatting is not needed, ;; `ts-human-format-duration' is much faster and generates less garbage: ;; | Form | x faster than next | Total runtime | # of GCs | Total GC runtime | ;; |--------------------------+--------------------+---------------+----------+------------------| ;; | ts-human-format-duration | 5.82 | 0.832945 | 3 | 0.574929 | ;; | format-seconds | slowest | 4.848253 | 17 | 3.288799 | (cl-defun ts-human-format-duration (seconds &optional abbreviate) "Return human-formatted string describing duration SECONDS. If SECONDS is less than 1, returns \"0 seconds\". If ABBREVIATE is non-nil, return a shorter version, without spaces. This is a simple calculation that does not account for leap years, leap seconds, etc." ;; FIXME: Doesn't work with negative values, even though `ts-human-duration' does. (if (< seconds 1) (if abbreviate "0s" "0 seconds") (cl-macrolet ((format> (place) ;; When PLACE is greater than 0, return formatted string using its symbol name. `(when (> ,place 0) (format "%d%s%s" ,place (if abbreviate "" " ") (if abbreviate ,(substring (symbol-name place) 0 1) ,(symbol-name place))))) (join-places (&rest places) ;; Return string joining the names and values of PLACES. `(->> (list ,@(cl-loop for place in places collect `(format> ,place))) -non-nil (s-join (if abbreviate "" ", "))))) (-let* (((&plist :years :days :hours :minutes :seconds) (ts-human-duration seconds))) (join-places years days hours minutes seconds)))))