[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: date command is great but could use improvements

From: Bob Proulx
Subject: Re: date command is great but could use improvements
Date: Tue, 24 May 2022 14:30:03 -0600

David Chmelik wrote:
>         I noticed two types for weeks in year: 1 to 53, 0 to 53, numbering
> 54 weeks, but there can't be 54, right?
>         Only two options exist to number weekdays, when should be
> more/user-configurable.

The %Y and %U or %W options work in combination.  Use %U for weeks
starting with Sunday or %W for weeks starting with Monday.

The ISO %G and %V options work in combination.  Use them together.

Mixing these different sets up creates confusion.  Use %Y and %U/%W
together or use %G and %V together.  Here is an example of a date with
some odd corner cases.

    $ cal 01 2026
        January 2026
    Su Mo Tu We Th Fr Sa
                 1  2  3
     4  5  6  7  8  9 10
    11 12 13 14 15 16 17
    18 19 20 21 22 23 24
    25 26 27 28 29 30 31

    $ cal 01 2027
        January 2027
    Su Mo Tu We Th Fr Sa
                    1  2
     3  4  5  6  7  8  9
    10 11 12 13 14 15 16
    17 18 19 20 21 22 23
    24 25 26 27 28 29 30

    $ date -d "2026-12-31 12:00" +%G%V

    $ date -d "2027-01-01 12:00" +%G%V

    $ date -d "2026-12-31 12:00" +%Y%U

    $ date -d "2027-01-01 12:00" +%Y%U

Use of ISO week numbers tends to create confusion.  The ISO week
numbering scheme is somewhat different from calendar week numbering.
ISO week numbers start on Monday of the week with the year's first
Thursday in it.  See Wikipidia’s ISO 8601 page or Wikipidia’s ISO week date
page for a good summary.

ISO Week Dates can be created using the following format.

    $ date -d "2022-01-01 12:00:00 +0000" "+%G-W%V-%u"

    $ date -d "2022-01-03 12:00:00 +0000" "+%G-W%V-%u"

>         Glad to see one can display weekday 1 to 7 (how everyone thinks
> about it) except said 1 is Monday (as in Europe.)  I was shocked to see one
> can only display Sunday starting week at 0. Everyone thinks of days 1 to 7,
> even programmers/sysadmins having to talk so users understand.  Majority are
> PC users now with Linux kernel being most popular (normally GNU also
> available on Replicant/Android/etc.) but people where Sunday is first
> weekday (The United States of America, USA, and I've never heard a
> programmer/sysadmin/scientist/professor who uses UNIX/GNU//Linux say 'zeroth
> weekday') will want PC (so date command) to number days from 1, as date
> numbers days month days 1 to up to 31, weeks 1 to 53, quarters/seasons 1 to
> 4, months & civil time 1 to 12.

This all originates with Unix in the 1970's.  Please see the ctime(3)
man page.  In it one will find something like this (abbreviated)

    man ctime

       The ctime(), gmtime(), and localtime() functions all take an argument
       of data type time_t, which represents calendar time.  When interpreted
       as an absolute time value, it represents the number of seconds elapsed
       since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).

       The asctime() and mktime() functions both take an argument representing
       broken-down time, which is a representation separated into year, month,
       day, and so on.

       Broken-down time is stored in the structure tm, which is defined in
       <time.h> as follows:

           struct tm {
               int tm_sec;    /* Seconds (0-60) */
               int tm_min;    /* Minutes (0-59) */
               int tm_hour;   /* Hours (0-23) */
               int tm_mday;   /* Day of the month (1-31) */
               int tm_mon;    /* Month (0-11) */
               int tm_year;   /* Year - 1900 */
               int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
               int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
               int tm_isdst;  /* Daylight saving time */

       The members of the tm structure are:

       tm_sec    The number of seconds after the minute, normally in the range
                 0 to 59, but can be up to 60 to allow for leap seconds.

       tm_min    The number of minutes after the hour, in the range 0 to 59.

       tm_hour   The number of hours past midnight, in the range 0 to 23.

       tm_mday   The day of the month, in the range 1 to 31.

       tm_mon    The number of months since January, in the range 0 to 11.

       tm_year   The number of years since 1900.

       tm_wday   The number of days since Sunday, in the range 0 to 6.

       tm_yday   The number of days since January 1, in the range 0 to 365.

       tm_isdst  A flag that indicates whether daylight saving time is in
                 effect at the time described.  The value is positive if
                 daylight saving time is in effect, zero if it is not, and
                 negative if the information is not available.

This is the origination of the range values.  The command line utility
is at the source a wrapper around these library routines and these
data structures.

       The call ctime(t) is equivalent to asctime(localtime(t)).  It converts
       the calendar time t into a null-terminated string of the form

           "Wed Jun 30 21:49:08 1993\n"

Note the similarity to the default date output.  It's almost but not
quite this format.  Note that one really should never use the default
date format because it is ambiguous.  Instead use "date -R" or other
unambiguous format.

>         I'm European-American, programming since 1993, and may recall Monday
> was first weekday growing up in The United Kingdom (UK,) but moved to USA at
> age seven and they said Sunday is /first/ weekday, so that's what I use
> until revisiting Europe/Britain.  If date or clock displays day 0, I'd know
> it's Sunday, but every day after think it's day as a user (then may miss
> things I must go to.) For other almost or 97+% (non-programmer) people if
> they want detailed system tray clock, problem's even worse.
>         I won't say break UNIX tradition, but how about adding more types or
> making configurable? (even some British Isles programmers might want Monday
> 0.)

The goal of the Unix Philosophy is not to program every possibility
but to make programming every possibility possible.  There is already
a rich set of features that has proven powerful over the last five
decades.  If one needs special cases that are not part of the
fundamental set then it is possible and fairly easy to create such a
custom function.  The command line shell is well suited to this type
of customization.

For my own uses I most often prefer this date format.

    date "+%F %T %z"

>         Various other calendars are in usage worldwide that start week on
> other days, and I'm sure users start with day 1 (but some programmers might
> want day 0.)
>         The older European calendar (still in some usage) counts days of the
> year: 1 to 365 or 366.

The date documentation shows:

         day of year (‘001’...‘366’)

    $ date -d '2022-12-31 12:00' +%j

If one desires a zero based day of year then it is a simple matter to
subtract one from this.

    $ date -d '2022-01-01 12:00' +%j

    $ printf "%03d\n" $(( $(date -d '2022-01-01 12:00' +%j) - 1 ))

>         Another British Isles time unit is fortnight: 14 days, which may not
> be used much, but I like it (of course has week 1 & 2.)

Note that GNU date does support the concept of "fortnight" being 14
days.  See the documentation for details.

>         Manpage grammar/typographical errors exist; alphabetic time zone
> abbreviation says EDT: likely you mean Eastern Time (ET, North America)
> zone, which contains at least two 'local times,' Eastern Standard Time (EST)
> & Eastern Daylight saving Time (EDT,) which aren't zones, rather than
> settings people & organizations/governments might choose or not in a zone,
> and adherence varies.  I don't use Pacific Time's PDT because daylight
> saving time is unnatural/difficult (thousands to millions or more feel same)
> and I'm not working yet (besides volunteer Free/Libre Software (FLS)
> programming, helping at parents' rural place, rarely artwork.)

By Act of Congress the US timezones have been established.  The names
used are not always unambiguous.  Their use is not recommended.
The Coreutils date documentation includes this section.

       Time zone items other than ‘UTC’ and ‘Z’ are obsolescent and are not
    recommended, because they are ambiguous; for example, ‘EST’ has a
    different meaning in Australia than in the United States, and ‘A’ has
    different meaning as a military time zone than as an obsolescent RFC 822
    time zone.  Instead, it’s better to use unambiguous numeric time zone
    corrections like ‘-0500’, as described in the previous section.

> Users of date and derived GUI clocks might want time zone & local
> time.  Another manpage grammar mistake is saying 'alternate' when
> 'alternative' is meant: 'alternate' means to switch back & forth:

This occurs in date's --help output.

    After any flags comes an optional field width, as a decimal number;
    then an optional modifier, which is either
    E to use the locale's alternate representations if available, or
    O to use the locale's alternate numeric symbols if available.

I see that Webster does specify this alternate usage.  :-)

>         Ntpd isn't coreutils, but I wish I could set system clock to PST and

It is not recommended to set the system clock to local time.  Better
to always set the system clock to UTC.

> get updates from UTC-8 servers, but display reminder others use PDT, and
> might be nice if date allowed such clarification (as many scientists dislike
> unnatural time, especially some/many programmers who tend to stay up late,
> and astronomers.)  Setting system clock to UTC won't do (unless visiting
> UTC.)

You didn't say what OS you are running but GNU systems support setting
the system clock to UTC and setting the userland to an appropriate
local time.  That's the recommended configuration.  I'll hazard a
guess that configuration accounts for most of all systems on the
Internet.  Only a very few systems must deal with a system clock not
set to UTC.

In addition to /etc/localtime for userland timezone configuration note
there is also the TZ variable which can be set as an environment local
override for individual processes.

Both of those are GNU glibc domain topics though and not Coreutils
which is simply a user of the system libc library.

Happy Hacking!

reply via email to

[Prev in Thread] Current Thread [Next in Thread]