ls(1): Alter time portion of "long format"
authorJohn Marino <draco@marino.st>
Fri, 20 Nov 2015 12:49:26 +0000 (13:49 +0100)
committerJohn Marino <draco@marino.st>
Fri, 20 Nov 2015 13:36:20 +0000 (14:36 +0100)
One side effect of moving to the CLDR standard for locale definitions
is that abreviated months are no longer guaranteed to align.  We altered
the definitions for CJK to ensure this, but we do not want to manually
adjust every locale.

The most obvious manifestation is seen with ls(1) using the long format
(-l option).  Not only is the month abbreviation no longer guaranteed to
be 3 characters wide, it's not even guaranteed to be a uniform width.  As
a result, the file listing may no longer line up, as seen with French:

  ironwolf# env LANG=fr_FR.UTF-8 ls -l | head
  drwxr-xr-x  2 root  wheel   512 26 mars  2015 ariadne
  drwxr-xr-x  2 root  wheel   512 26 mars  2015 artemis
  drwxr-xr-x  3 root  wheel   512  9 sept. 19:45 avida
  drwxr-xr-x  3 root  wheel   512  9 sept. 19:45 babel
  drwxr-xr-x  3 root  wheel   512 15 juin 20:38 bcftools
  drwxr-xr-x  2 root  wheel   512 20 sept. 11:27 biococoa
  drwxr-xr-x  2 root  wheel   512 26 mars  2015 biojava
  drwxr-xr-x  3 root  wheel   512 26 mars  2015 blat
  drwxr-xr-x  3 root  wheel   512  7 nov. 08:44 bwa

  ironwolf# env LANG=fr_FR.UTF-8 ls -lT | head
  drwxr-xr-x  2 root  wheel   512 26 mars 10:15:28 2015 ariadne
  drwxr-xr-x  2 root  wheel   512 26 mars 10:15:28 2015 artemis
  drwxr-xr-x  3 root  wheel   512  9 sept. 19:45:04 2015 avida
  drwxr-xr-x  3 root  wheel   512  9 sept. 19:45:04 2015 babel
  drwxr-xr-x  3 root  wheel   512 15 juin 20:38:55 2015 bcftools
  drwxr-xr-x  2 root  wheel   512 20 sept. 11:27:40 2015 biococoa
  drwxr-xr-x  2 root  wheel   512 26 mars 10:15:28 2015 biojava
  drwxr-xr-x  3 root  wheel   512 26 mars 10:15:28 2015 blat
  drwxr-xr-x  3 root  wheel   512  7 nov. 08:44:24 2015 bwa

To address both issues (misalignment and differing widths as a function
of locale), I've modified ls(1) to use valid forms of ISO 8601, an
international standard for the representation of time.

The default long format produces the last modified timestamp in the form
of YYYYMMDDTHH (Year|Month|Day|T|Hour with no spaces).  This is known as
the "basic" format which includes the optional "T" concatenator.  The
result is the time is represented by a single column using 1-3 characters
less than before.

  ironwolf# env LANG=fr_FR.UTF-8 ls -l | head
  drwxr-xr-x  2 root  wheel   512 20150326T10 ariadne
  drwxr-xr-x  2 root  wheel   512 20150326T10 artemis
  drwxr-xr-x  3 root  wheel   512 20150909T19 avida
  drwxr-xr-x  3 root  wheel   512 20150909T19 babel
  drwxr-xr-x  3 root  wheel   512 20150615T20 bcftools
  drwxr-xr-x  2 root  wheel   512 20150920T11 biococoa
  drwxr-xr-x  2 root  wheel   512 20150326T10 biojava
  drwxr-xr-x  3 root  wheel   512 20150326T10 blat
  drwxr-xr-x  3 root  wheel   512 20151107T08 bwa

The -T option uses the extended format of ISO 8601 without the T symbol,
but with the minutes and seconds representation.  The result is two
characters wider than the approach FreeBSD is taking to address the same
issue (FreeBSD is padding the month section and expanding the field by
two characters to accommodate 5-character wide month names).  The output
on DragonFly looks like this:

  ironwolf# env LANG=fr_FR.UTF-8 ls -lT | head
  drwxr-xr-x  2 root  wheel   512 2015-03-26 10:15:28 ariadne
  drwxr-xr-x  2 root  wheel   512 2015-03-26 10:15:28 artemis
  drwxr-xr-x  3 root  wheel   512 2015-09-09 19:45:04 avida
  drwxr-xr-x  3 root  wheel   512 2015-09-09 19:45:04 babel
  drwxr-xr-x  3 root  wheel   512 2015-06-15 20:38:55 bcftools
  drwxr-xr-x  2 root  wheel   512 2015-09-20 11:27:40 biococoa
  drwxr-xr-x  2 root  wheel   512 2015-03-26 10:15:28 biojava
  drwxr-xr-x  3 root  wheel   512 2015-03-26 10:15:28 blat
  drwxr-xr-x  3 root  wheel   512 2015-11-07 08:44:24 bwa

The long format no longer changes if the last modified time is within six
months (future or past), thus file times are more quickly comparable with
a quick visual scan versus switching between year and hours:seconds.

Reported by: bapt@FreeBSD.org

bin/ls/ls.1
bin/ls/print.c

index f2c2483..0625099 100644 (file)
@@ -31,7 +31,7 @@
 .\"     @(#)ls.1       8.7 (Berkeley) 7/29/94
 .\" $FreeBSD: src/bin/ls/ls.1,v 1.86 2005/02/13 22:25:09 ru Exp $
 .\"
-.Dd March 4, 2014
+.Dd November 20, 2015
 .Dt LS 1
 .Os
 .Sh NAME
@@ -150,7 +150,8 @@ When used with the
 (lowercase letter
 .Dq ell )
 option, display complete time information for the file, including
-month, day, hour, minute, second, and year.
+month, day, hour, minute, second, and year using the ISO 8601 extended
+format.
 .It Fl W
 Display whiteouts when scanning directories.
 .It Fl a
@@ -325,19 +326,14 @@ option is given, the following information
 is displayed for each file:
 file mode,
 number of links, owner name, group name,
-number of bytes in the file, abbreviated
-month, day-of-month file was last modified,
-hour file last modified, minute file last
-modified, and the pathname.
+number of bytes in the file,
+last modified time in ISO 8601 basic format reduced to
+hour accuracy, and the pathname.
 In addition, for each directory whose contents are displayed, the total
 number of 512-byte blocks used by the files in the directory is displayed
 on a line by itself immediately before the information for the files in the
 directory.
 .Pp
-If the modification time of the file is more than 6 months
-in the past or future, then the year of the last modification
-is displayed in place of the hour and minute fields.
-.Pp
 If the owner or group names are not a known user or group name,
 or the
 .Fl n
index 7887b1e..7519e37 100644 (file)
@@ -31,7 +31,6 @@
  *
  * @(#)print.c 8.4 (Berkeley) 4/17/94
  * $FreeBSD: src/bin/ls/print.c,v 1.73 2004/06/08 09:27:42 das Exp $
- * $DragonFly: src/bin/ls/print.c,v 1.20 2008/06/24 21:55:48 y0netan1 Exp $
  */
 
 #include <sys/param.h>
@@ -350,23 +349,16 @@ printtime(time_t ftime)
        char longstring[80];
        static time_t now;
        const char *format;
-       static int d_first = -1;
 
-       if (d_first < 0)
-               d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
        if (now == 0)
                now = time(NULL);
 
-#define        SIXMONTHS       ((365 / 2) * 86400)
        if (f_sectime)
-               /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */
-               format = d_first ? "%e %b %T %Y " : "%b %e %T %Y ";
-       else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS)
-               /* mmm dd hh:mm || dd mmm hh:mm */
-               format = d_first ? "%e %b %R " : "%b %e %R ";
+               /* ISO 8601 (extended without T): YYYY-DD-MM hh:mm:ss */
+               format = "%F %T ";
        else
-               /* mmm dd  yyyy || dd mmm  yyyy */
-               format = d_first ? "%e %b  %Y " : "%b %e  %Y ";
+               /* ISO 8601 (basic with T): YYYYDDMMThh */
+               format = "%Y%m%dT%H ";
        strftime(longstring, sizeof(longstring), format, localtime(&ftime));
        fputs(longstring, stdout);
 }