GNU bug report logs - #78678
[PATCH v1] world-clock: Sort entries based on a user-provided function

Previous Next

Package: emacs;

Reported by: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>

Date: Tue, 3 Jun 2025 06:32:06 UTC

Severity: normal

Tags: patch

Done: Eli Zaretskii <eliz <at> gnu.org>

To reply to this bug, email your comments to 78678 AT debbugs.gnu.org.
There is no need to reopen the bug first.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#78678; Package emacs. (Tue, 03 Jun 2025 06:32:08 GMT) Full text and rfc822 format available.

Acknowledgement sent to "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Tue, 03 Jun 2025 06:32:09 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: [PATCH v1] world-clock: Sort entries based on a user-provided function
Date: Tue, 03 Jun 2025 02:30:59 -0400
[Message part 1 (text/plain, inline)]
Tags: patch


Hello all,

Please find below a feature proposal for sorting entries of
world-clock, and a first draft of a patch attached to this message.

# Motivation

The `world-clock' displays time zone entries in the order they appear
in `world-clock-list'. Usually this is enough, since orders like time
can often be done statically. However, there are scenarios where you
might want a dynamic ordering. For example:

1. You work with people in multiple time zones, and you want entries
to appear in order of proximity to working hours, e.g. in what time
zones are people likely to be responsive right now?

2. Daylight savings can go into effect at [different times]. For
example, eastern Europe and Egypt both shift from UTC+2 in the winter
to UTC+3 in the summer.

| Zone           | DST start            | DST end                  |
|----------------+----------------------+--------------------------|
| eastern Europe | last Sunday of March | last Sunday of October   |
| Egypt          | last Friday of April | last Thursday of October |

For a period in the spring, local time in Egypt (UTC+2) is earlier
than eastern Europe (UTC+3). Depending on the year, DST in Egypt may
end earlier or later than in eastern Europe.

In years like 2025 & 2026 where the last Thursday of October is after
the last Sunday of October, there’s no static ordering of the zones
that works all year (bracket contents are UTC offsets at a vertical
time slice):

#+begin_src text
time             |< ~April             ~November >|
Egypt  ---(+2)-----(+2)-|-(+3)--------(+3)---(+3)-|-(+2)-----
Europe ---(+2)---|-(+3)---(+3)--------(+3)-|-(+2)---(+2)-----
#+end_src

In other years like 2027, a consistent ordering is possible:

#+begin_src text
time             |< ~April             ~November >|
Egypt  ---(+2)-----(+2)-|-(+3)--------(+3)-|-(+2)---(+2)-----
Europe ---(+2)---|-(+3)---(+3)--------(+3)---(+3)-|-(+2)-----
#+end_src

[different times]
https://en.wikipedia.org/wiki/Daylight_saving_time_by_country

# Possible Implementation

A simple way to do this is with a `world-clock-sort-function' custom
variable that sorts the entries in `world-clock-display'.

#+begin_src emacs-lisp
(setopt world-clock-sort-function 'my/world-clock-sort-function)
#+end_src

You could then accomplish each of the orderings mentioned earlier:

1. Time zones appear in order of how far they are from the middle of
the workday:

#+begin_src emacs-lisp
(defun my/world-clock-sort-function (tzlist)
  "Sort on proximity of local time to work hours."
  (let* ((now (current-time))
         (start 9)
         (end  17)
         (mid (/ (+ start end) 2.0)))
    (sort tzlist
          :key (lambda (entry)
                 (pcase-let* ((zone (car entry))
                              (`(,s ,m ,h _) (decode-time now zone))
                              (hour (+ h (/ m 60.0) (/ s 3600.0)))
                              (diff (min (abs (- hour (- mid 24)))
                                         (abs (- hour mid))
                                         (abs (- hour (+ mid 24))))))
                   diff)))))
#+end_src

2. Sort on an ISO-8601 timestamp so zones are always in ascending
order:

#+begin_src emacs-lisp
(defun my/world-clock-sort-function (tzlist)
  "Sort on local ISO-8601 timestamps."
  (let ((now (current-time)))
    (sort tzlist
          :key (lambda (entry)
                 (let ((zone (car entry)))
                   (format-time-string "%FT%T" now zone))))))
#+end_src

Note that in the current patch there’s a small race condition between
recording the current time in `world-clock-display' and sorting the
list.

Any thoughts on this idea and the interface?

Thanks,

-- 
Jacob S. Gordon
jacob.as.gordon <at> gmail.com

=========================

Please avoid sending me HTML emails and MS Office documents.
https://useplaintext.email/#etiquette
https://www.gnu.org/philosophy/no-word-attachments.html


In GNU Emacs 30.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.49,
cairo version 1.18.4)
System Description: Arch Linux

Configured using:
 'configure --with-pgtk --sysconfdir=/etc --prefix=/usr
 --libexecdir=/usr/lib --localstatedir=/var --disable-build-details
 --with-cairo --with-harfbuzz --with-libsystemd --with-modules
 --with-native-compilation=aot --with-tree-sitter 'CFLAGS=-march=x86-64
 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=3
 -Wformat -Werror=format-security -fstack-clash-protection
 -fcf-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -g
 -ffile-prefix-map=/build/emacs/src=/usr/src/debug/emacs -flto=auto'
 'LDFLAGS=-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro
 -Wl,-z,now -Wl,-z,pack-relative-relocs -flto=auto'
 'CXXFLAGS=-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions
 -Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security
 -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer
 -mno-omit-leaf-frame-pointer -Wp,-D_GLIBCXX_ASSERTIONS -g
 -ffile-prefix-map=/build/emacs/src=/usr/src/debug/emacs -flto=auto''

[v1-0001-world-clock-sort-entries-based-user-provided-function.patch (text/patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78678; Package emacs. (Tue, 03 Jun 2025 12:01:02 GMT) Full text and rfc822 format available.

Message #8 received at 78678 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
Cc: 78678 <at> debbugs.gnu.org
Subject: Re: bug#78678: [PATCH v1] world-clock: Sort entries based on a
 user-provided function
Date: Tue, 03 Jun 2025 15:00:34 +0300
> From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
> Date: Tue, 03 Jun 2025 02:30:59 -0400
> 
> Please find below a feature proposal for sorting entries of
> world-clock, and a first draft of a patch attached to this message.
> 
> # Motivation
> 
> The `world-clock' displays time zone entries in the order they appear
> in `world-clock-list'. Usually this is enough, since orders like time
> can often be done statically. However, there are scenarios where you
> might want a dynamic ordering. For example:
> 
> 1. You work with people in multiple time zones, and you want entries
> to appear in order of proximity to working hours, e.g. in what time
> zones are people likely to be responsive right now?
> 
> 2. Daylight savings can go into effect at [different times]. For
> example, eastern Europe and Egypt both shift from UTC+2 in the winter
> to UTC+3 in the summer.

I have no objections to adding such a feature.

> A simple way to do this is with a `world-clock-sort-function' custom
> variable that sorts the entries in `world-clock-display'.
> 
> #+begin_src emacs-lisp
> (setopt world-clock-sort-function 'my/world-clock-sort-function)
> #+end_src
> 
> You could then accomplish each of the orderings mentioned earlier:

This requires users to be Lisp programmers.  If there are
reasonably-useful cases where a certain order would be desirable,
allowing users to customize a variable using symbol values makes the
feature much more friendly to users who are not programmers.  Would it
make sense to add a couple of such values?

> >From 0d293d92d81d1086a63942734fa067c4f0ca0bfe Mon Sep 17 00:00:00 2001
> From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
> Date: Mon, 2 Jun 2025 21:06:37 -0400
> 
> The 'world-clock' displays time zone entries in the order they appear in
> 'world-clock-list' (or a default if unset).  We introduce a custom
> variable 'world-clock-sort-function' to generate an order on each update
> of 'world-clock-display'.  The default value of 'identity' preserves the
> existing behavior.
> 
> * lisp/time.el (world-clock-sort-function, world-clock-display):
> 
> Add custom variable 'world-clock-sort-function', and sort time zone
> entries in 'world-clock-display' according to it.

Please reformat the log message according to our conventions
(described in CONTRIBUTE).

> +** Time
> +
> +*** New user option 'world-clock-sort-function'

The heading lines in NEWS should end with a period.

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78678; Package emacs. (Mon, 09 Jun 2025 03:55:02 GMT) Full text and rfc822 format available.

Message #11 received at 78678 <at> debbugs.gnu.org (full text, mbox):

From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 78678 <at> debbugs.gnu.org
Subject: Re: bug#78678: [PATCH v2] world-clock: Add user option to control
 order of entries
Date: Sun, 8 Jun 2025 23:54:06 -0400
[Message part 1 (text/plain, inline)]
Hello,

On 2025-06-03 08:00, Eli Zaretskii wrote:
> This requires users to be Lisp programmers.  If there are
> reasonably-useful cases where a certain order would be desirable,
> allowing users to customize a variable using symbol values makes the
> feature much more friendly to users who are not programmers.  Would
> it make sense to add a couple of such values?

I agree, and I think it does make sense. After trying a version with
symbols for common use-cases, I think the most flexible option is to
allow the user to provide a format for `format-time-string' to act as
the sorting key. This is similar in complexity to the variable
`world-clock-time-format', and some predefined values can be put in
the `:type' block of the `defcustom':

#+begin_src emacs-lisp
:type '(choice (const :tag "No sorting" nil)
               (const :tag "Chronological order" "%FT%T")
               (const :tag "Reverse chronological order" ("%FT%T" . t))
               (const :tag "Time of day order" "%T")
               (const :tag "Reverse time of day order" ("%T" . t))
               (string :tag "Format string")
               (cons :tag "Format string and reverse flag"
                     (string :tag "Format string")
                     (boolean :tag "Reverse"))
               (function :tag "Sorting function")))
#+end_src

Then, sorting can be switched based on the type in a helper function:

#+begin_quote
(defun world-clock--sort-entries (tzlist time)
  "Sort TZLIST according to `world-clock-sort-order' at a given TIME."
  (pcase world-clock-sort-order
    ((pred null) tzlist)
    ((or (and (pred stringp) format)
        `(,(and (pred stringp) format) .
          ,(and (pred booleanp) reverse)))
     (sort tzlist
           :key (lambda (entry)
                   (format-time-string format time (car entry)))
           :reverse reverse))
    ((pred functionp) (funcall world-clock-sort-order tzlist time))
    (_ (error "Invalid `world-clock-sort-order': `%s'"
              world-clock-sort-order))))
#+end_quote

In terms of coding standards:

+ I could do this without `pcase', if desired.
+ I can write unit tests if we’re okay with the idea.

> Please reformat the log message according to our conventions
> (described in CONTRIBUTE).

Done in the updated patch (I think?).

Thank you!

-- 
Jacob S. Gordon
jacob.as.gordon <at> gmail.com

======================

Please avoid sending me HTML emails and MS Office documents.
https://useplaintext.email/#etiquette
https://www.gnu.org/philosophy/no-word-attachments.html
[v2-0001-world-clock-Add-user-option-to-control-entry-order.patch (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78678; Package emacs. (Thu, 12 Jun 2025 07:18:02 GMT) Full text and rfc822 format available.

Message #14 received at 78678 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
Cc: 78678 <at> debbugs.gnu.org
Subject: Re: bug#78678: [PATCH v2] world-clock: Add user option to control
 order of entries
Date: Thu, 12 Jun 2025 10:16:29 +0300
> Date: Sun, 8 Jun 2025 23:54:06 -0400
> From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
> Cc: 78678 <at> debbugs.gnu.org
> 
> On 2025-06-03 08:00, Eli Zaretskii wrote:
> > This requires users to be Lisp programmers.  If there are
> > reasonably-useful cases where a certain order would be desirable,
> > allowing users to customize a variable using symbol values makes the
> > feature much more friendly to users who are not programmers.  Would
> > it make sense to add a couple of such values?
> 
> I agree, and I think it does make sense. After trying a version with
> symbols for common use-cases, I think the most flexible option is to
> allow the user to provide a format for `format-time-string' to act as
> the sorting key. This is similar in complexity to the variable
> `world-clock-time-format', and some predefined values can be put in
> the `:type' block of the `defcustom':
> 
> #+begin_src emacs-lisp
> :type '(choice (const :tag "No sorting" nil)
>                (const :tag "Chronological order" "%FT%T")
>                (const :tag "Reverse chronological order" ("%FT%T" . t))
>                (const :tag "Time of day order" "%T")
>                (const :tag "Reverse time of day order" ("%T" . t))
>                (string :tag "Format string")
>                (cons :tag "Format string and reverse flag"
>                      (string :tag "Format string")
>                      (boolean :tag "Reverse"))
>                (function :tag "Sorting function")))
> #+end_src
> 
> Then, sorting can be switched based on the type in a helper function:
> 
> #+begin_quote
> (defun world-clock--sort-entries (tzlist time)
>   "Sort TZLIST according to `world-clock-sort-order' at a given TIME."
>   (pcase world-clock-sort-order
>     ((pred null) tzlist)
>     ((or (and (pred stringp) format)
>         `(,(and (pred stringp) format) .
>           ,(and (pred booleanp) reverse)))
>      (sort tzlist
>            :key (lambda (entry)
>                    (format-time-string format time (car entry)))
>            :reverse reverse))
>     ((pred functionp) (funcall world-clock-sort-order tzlist time))
>     (_ (error "Invalid `world-clock-sort-order': `%s'"
>               world-clock-sort-order))))
> #+end_quote
> 
> In terms of coding standards:
> 
> + I could do this without `pcase', if desired.
> + I can write unit tests if we’re okay with the idea.
> 
> > Please reformat the log message according to our conventions
> > (described in CONTRIBUTE).
> 
> Done in the updated patch (I think?).

Thanks, this version LGTM.

However, before we can accept this contribution, we need you to sign a
copyright-assignment agreement, given the size of this contribution.
If you are willing to do that, I will send you the form to fill and
the instructions to go with it, to start your assignment paperwork
rolling.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78678; Package emacs. (Thu, 12 Jun 2025 16:11:02 GMT) Full text and rfc822 format available.

Message #17 received at 78678 <at> debbugs.gnu.org (full text, mbox):

From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 78678 <at> debbugs.gnu.org
Subject: Re: bug#78678: [PATCH v2] world-clock: Add user option to control
 order of entries
Date: Thu, 12 Jun 2025 12:10:07 -0400
Hello,

On 2025-06-12 03:16, Eli Zaretskii wrote:
> However, before we can accept this contribution, we need you to sign a
> copyright-assignment agreement, given the size of this contribution.

The FSF signed my agreement on [2025-06-06 Fri], so I think I’m clear
to contribute now.

Thanks,

--
Jacob S. Gordon
jacob.as.gordon <at> gmail.com

======================

Please avoid sending me HTML emails and MS Office documents.
https://useplaintext.email/#etiquette
https://www.gnu.org/philosophy/no-word-attachments.html




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78678; Package emacs. (Thu, 12 Jun 2025 16:37:03 GMT) Full text and rfc822 format available.

Message #20 received at 78678 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
Cc: 78678 <at> debbugs.gnu.org
Subject: Re: bug#78678: [PATCH v2] world-clock: Add user option to control
 order of entries
Date: Thu, 12 Jun 2025 19:36:25 +0300
> Date: Thu, 12 Jun 2025 12:10:07 -0400
> From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
> Cc: 78678 <at> debbugs.gnu.org
> 
> Hello,
> 
> On 2025-06-12 03:16, Eli Zaretskii wrote:
> > However, before we can accept this contribution, we need you to sign a
> > copyright-assignment agreement, given the size of this contribution.
> 
> The FSF signed my agreement on [2025-06-06 Fri], so I think I’m clear
> to contribute now.

Thanks for letting us know.  Your assignment is not yet on file, so I
guess we need to wait for a couple of days until it is.




Reply sent to Eli Zaretskii <eliz <at> gnu.org>:
You have taken responsibility. (Sat, 14 Jun 2025 14:23:07 GMT) Full text and rfc822 format available.

Notification sent to "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>:
bug acknowledged by developer. (Sat, 14 Jun 2025 14:23:09 GMT) Full text and rfc822 format available.

Message #25 received at 78678-done <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
Cc: 78678-done <at> debbugs.gnu.org
Subject: Re: bug#78678: [PATCH v2] world-clock: Add user option to control
 order of entries
Date: Sat, 14 Jun 2025 17:22:29 +0300
> Date: Sun, 8 Jun 2025 23:54:06 -0400
> From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
> Cc: 78678 <at> debbugs.gnu.org
> 
> On 2025-06-03 08:00, Eli Zaretskii wrote:
> > This requires users to be Lisp programmers.  If there are
> > reasonably-useful cases where a certain order would be desirable,
> > allowing users to customize a variable using symbol values makes the
> > feature much more friendly to users who are not programmers.  Would
> > it make sense to add a couple of such values?
> 
> I agree, and I think it does make sense. After trying a version with
> symbols for common use-cases, I think the most flexible option is to
> allow the user to provide a format for `format-time-string' to act as
> the sorting key. This is similar in complexity to the variable
> `world-clock-time-format', and some predefined values can be put in
> the `:type' block of the `defcustom':
> 
> #+begin_src emacs-lisp
> :type '(choice (const :tag "No sorting" nil)
>                (const :tag "Chronological order" "%FT%T")
>                (const :tag "Reverse chronological order" ("%FT%T" . t))
>                (const :tag "Time of day order" "%T")
>                (const :tag "Reverse time of day order" ("%T" . t))
>                (string :tag "Format string")
>                (cons :tag "Format string and reverse flag"
>                      (string :tag "Format string")
>                      (boolean :tag "Reverse"))
>                (function :tag "Sorting function")))
> #+end_src
> 
> Then, sorting can be switched based on the type in a helper function:
> 
> #+begin_quote
> (defun world-clock--sort-entries (tzlist time)
>   "Sort TZLIST according to `world-clock-sort-order' at a given TIME."
>   (pcase world-clock-sort-order
>     ((pred null) tzlist)
>     ((or (and (pred stringp) format)
>         `(,(and (pred stringp) format) .
>           ,(and (pred booleanp) reverse)))
>      (sort tzlist
>            :key (lambda (entry)
>                    (format-time-string format time (car entry)))
>            :reverse reverse))
>     ((pred functionp) (funcall world-clock-sort-order tzlist time))
>     (_ (error "Invalid `world-clock-sort-order': `%s'"
>               world-clock-sort-order))))
> #+end_quote
> 
> In terms of coding standards:
> 
> + I could do this without `pcase', if desired.
> + I can write unit tests if we’re okay with the idea.
> 
> > Please reformat the log message according to our conventions
> > (described in CONTRIBUTE).
> 
> Done in the updated patch (I think?).

Thanks, installed on master, and closing the bug.

(the code as submitted triggered a byte-compiler warning, so I fixed
that by a followup patch.)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78678; Package emacs. (Sat, 14 Jun 2025 14:33:04 GMT) Full text and rfc822 format available.

Message #28 received at 78678-done <at> debbugs.gnu.org (full text, mbox):

From: "Jacob S. Gordon" <jacob.as.gordon <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 78678-done <at> debbugs.gnu.org
Subject: Re: bug#78678: [PATCH v2] world-clock: Add user option to control
 order of entries
Date: Sat, 14 Jun 2025 10:32:10 -0400
On 2025-06-14 10:22, Eli Zaretskii wrote:
> Thanks, installed on master, and closing the bug.

Perfect!

> (the code as submitted triggered a byte-compiler warning, so I fixed
> that by a followup patch.)

Shoot, thanks for the fix. I’ve added that to my list of
pre-submission checks.

Best,

-- 
Jacob S. Gordon
jacob.as.gordon <at> gmail.com

======================

Please avoid sending me HTML emails and MS Office documents.
https://useplaintext.email/#etiquette
https://www.gnu.org/philosophy/no-word-attachments.html




This bug report was last modified 1 day ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.