mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-13 11:42:21 +00:00
Fix unexpected output from 'printf %T' with certain formats (#65)
This commit changes the behavior of four date formats accepted by 'printf %()T' because the old behavior is not compatible with modern implementations of date(1): - %k and %l now return a blank-padded hour, the former based on a 24-hour clock and the latter a 12-hour clock (these are common extensions present on Linux and *BSD). - %f now returns a date with the format '%Y.%m.%d-%H:%M:%S' (BusyBox extension). - %q now returns the quarter of the current year (GNU extension). src/cmd/ksh93/data/builtins.c: - Copy the date format documentation from date in libcmd to the printf man page (for documenting 'printf %T'). src/cmd/ksh93/tests/builtins.sh: - Add four regression tests for the changed date formats. src/cmd/ksh93/sh.1: - Remove inaccurate information about the date formats accepted by printf %T'. The KornShell uses a custom version of strftime(3) that isn't guaranteed to accepts the same formats as the native strftime function. src/lib/libast/tm/tmxfmt.c: - Change the behavior of %f, %k, %l and %q to the common behavior. %k and %l are implemented as aliases to %_H and %_I to avoid duplicating code. src/lib/libcmd/date.c: - Update the documentation for the AST date command since it is also affected by the changes to 'printf %T'. Fixes #62
This commit is contained in:
parent
e70925ce10
commit
9526b3fa08
7 changed files with 103 additions and 22 deletions
11
NEWS
11
NEWS
|
@ -3,6 +3,17 @@ For full details, see the git log at: https://github.com/ksh93/ksh
|
|||
|
||||
Any uppercase BUG_* names are modernish shell bug IDs.
|
||||
|
||||
2020-07-07:
|
||||
|
||||
- Four of the date formats accepted by 'printf %()T' have had their
|
||||
functionality altered to the common behavior of date(1):
|
||||
- '%k' and '%l' print the current hour with blank padding, the former
|
||||
based on a 24-hour clock and the latter a twelve hour clock. These
|
||||
are common extensions present on Linux and *BSD.
|
||||
- '%l' prints the current hour (0-12) with blank padding (GNU and BSD).
|
||||
- '%f' prints a date with the format string '%Y.%m.%d-%H:%M:%S' (BusyBox).
|
||||
- '%q' prints the quarter of the year (GNU).
|
||||
|
||||
2020-07-06:
|
||||
|
||||
- 'notty' is now written to the ksh auditing file instead of '(null)' if
|
||||
|
|
|
@ -1221,8 +1221,74 @@ USAGE_LICENSE
|
|||
"convert it to an extended regular expression.]"
|
||||
"[+%T?Treat \astring\a as a date/time string and format it. The "
|
||||
"\bT\b can be preceded by \b(\b\adformat\a\b)\b, where "
|
||||
"\adformat\a is a date format as defined by the \bdate\b "
|
||||
"command.]"
|
||||
"\adformat\a is a date format. The accepted date formats are "
|
||||
"as follows:]{"
|
||||
"[+%?% character]"
|
||||
"[+a?abbreviated weekday name]"
|
||||
"[+A?full weekday name]"
|
||||
"[+b?abbreviated month name]"
|
||||
"[+B?full month name]"
|
||||
"[+c?\bctime\b(3) style date without the trailing newline]"
|
||||
"[+C?2-digit century]"
|
||||
"[+d?day of month number]"
|
||||
"[+D?date as \amm/dd/yy\a]"
|
||||
"[+e?blank padded day of month number]"
|
||||
"[+f?print a date with the format '\%Y.\%m.\%d-\%H:\%M:\%S']"
|
||||
"[+F?%ISO 8601:2000 standard date format; equivalent to Y-%m-%d]"
|
||||
"[+g?\bls\b(1) \b-l\b recent date with \ahh:mm\a]"
|
||||
"[+G?\bls\b(1) \b-l\b distant date with \ayyyy\a]"
|
||||
"[+h?abbreviated month name]"
|
||||
"[+H?24-hour clock hour, zero-padded]"
|
||||
"[+i?international \bdate\b(1) date with time zone type name]"
|
||||
"[+I?12-hour clock hour, zero-padded]"
|
||||
"[+j?1-offset Julian date]"
|
||||
"[+J?0-offset Julian date]"
|
||||
"[+k?24-hour clock hour, blank-padded]"
|
||||
"[+K?all numeric date; equivalent to \b%Y-%m-%d+%H:%M:%S\b; \b%_[EO]]K\b for space separator, %OK adds \b.%N\b, \b%EK\b adds \b%.N%z\b, \b%_EK\b adds \b.%N %z\b]"
|
||||
"[+l?12-hour clock hour, blank-padded]"
|
||||
"[+L?locale default date format]"
|
||||
"[+m?month number]"
|
||||
"[+M?minutes]"
|
||||
"[+n?newline character]"
|
||||
"[+N?nanoseconds 000000000-999999999]"
|
||||
"[+p?meridian (e.g., \bAM\b or \bPM\b)]"
|
||||
"[+q?quarter of the year]"
|
||||
"[+Q?\a<del>recent<del>distant<del>\a: \a<del>\a is a unique "
|
||||
"delimter character; \arecent\a format for recent "
|
||||
"dates, \adistant\a format otherwise]"
|
||||
"[+r?12-hour time as \ahh:mm:ss meridian\a]"
|
||||
"[+R?24-hour time as \ahh:mm\a]"
|
||||
"[+s?number of seconds since the epoch; \a.prec\a preceding "
|
||||
"\bs\b appends \aprec\a nanosecond digits, \b9\b if "
|
||||
"\aprec\a is omitted]"
|
||||
"[+S?seconds 00-60]"
|
||||
"[+t?tab character]"
|
||||
"[+T?24-hour time as \ahh:mm:ss\a]"
|
||||
"[+u?weekday number 1(Monday)-7]"
|
||||
"[+U?week number with Sunday as the first day]"
|
||||
"[+V?ISO week number (i18n is \afun\a)]"
|
||||
"[+w?weekday number 0(Sunday)-6]"
|
||||
"[+W?week number with Monday as the first day]"
|
||||
"[+x?locale date style that includes month, day and year]"
|
||||
"[+X?locale time style that includes hours and minutes]"
|
||||
"[+y?2-digit year (you'll be sorry)]"
|
||||
"[+Y?4-digit year]"
|
||||
"[+z?time zone \aSHHMM\a west of GMT offset where S is "
|
||||
"\b+\b or \b-\b, use pad _ for \aSHH:MM\a]"
|
||||
"[+Z?time zone name]"
|
||||
"[+=[=]][-+]]flag?set (default or +) or clear (-) \aflag\a "
|
||||
"for the remainder of \aformat\a, or for the remainder "
|
||||
"of the process if \b==\b is specified. \aflag\a may be:]{"
|
||||
"[+l?enable leap second adjustments]"
|
||||
"[+n?convert \b%S\b as \b%S.%N\b]"
|
||||
"[+u?UTC time zone]"
|
||||
"}"
|
||||
"[+#?equivalent to %s]"
|
||||
"[+??alternate?use \aalternate\a format if a default format "
|
||||
"override has not been specified, e.g., \bls\b(1) uses "
|
||||
"\"%?%l\"; export TM_OPTIONS=\"format='\aoverride\a'\" "
|
||||
"to override the default]"
|
||||
"}"
|
||||
"[+%Z?Output a byte whose value is \b0\b.]"
|
||||
"\fextra\f"
|
||||
"}"
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
* David Korn <dgk@research.att.com> *
|
||||
* *
|
||||
***********************************************************************/
|
||||
#define SH_RELEASE "93u+m 2020-07-06"
|
||||
#define SH_RELEASE "93u+m 2020-07-07"
|
||||
|
|
|
@ -6527,10 +6527,7 @@ A
|
|||
.BI %( date-format )T
|
||||
format can be used to treat an argument as a date/time string
|
||||
and to format the date/time according to the
|
||||
.I date-format\^
|
||||
as defined for the
|
||||
.BR date (1)
|
||||
command.
|
||||
.IR date-format .
|
||||
.TP
|
||||
.B %Z
|
||||
A
|
||||
|
|
|
@ -749,5 +749,12 @@ unset foo
|
|||
test_func
|
||||
)
|
||||
|
||||
# ======
|
||||
# Test the output of nonstandard date formats with 'printf %T'
|
||||
[[ $(printf '%(%l)T') == $(printf '%(%_I)T') ]] || err_exit 'date format %l is not the same as %_I'
|
||||
[[ $(printf '%(%k)T') == $(printf '%(%_H)T') ]] || err_exit 'date format %k is not the same as %_H'
|
||||
[[ $(printf '%(%f)T') == $(printf '%(%Y.%m.%d-%H:%M:%S)T') ]] || err_exit 'date format %f is not the same as %Y.%m.%d-%H:%M:%S'
|
||||
[[ $(printf '%(%q)T') == $(printf '%(%Qz)T') ]] && err_exit 'date format %q is the same as %Qz'
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
|
@ -271,8 +271,8 @@ tmxfmt(char* buf, size_t len, const char* format, Time_t t)
|
|||
case 'e': /* blank padded day of month */
|
||||
cp = number(cp, ep, (long)tm->tm_mday, -2, width, pad);
|
||||
continue;
|
||||
case 'f': /* (AST) OBSOLETE use %Qf */
|
||||
p = "%Qf";
|
||||
case 'f': /* Output the date in a format compatible with BusyBox %f */
|
||||
p = "%Y.%m.%d-%H:%M:%S";
|
||||
goto push;
|
||||
case 'F': /* ISO 8601:2000 standard date format */
|
||||
p = "%Y-%m-%d";
|
||||
|
@ -316,8 +316,8 @@ tmxfmt(char* buf, size_t len, const char* format, Time_t t)
|
|||
case 'J': /* Julian date (0 offset) */
|
||||
cp = number(cp, ep, (long)tm->tm_yday, 3, width, pad);
|
||||
continue;
|
||||
case 'k': /* (AST) OBSOLETE use %QD */
|
||||
p = "%QD";
|
||||
case 'k': /* hour (0 - 23) with blank padding */
|
||||
p = "%_H";
|
||||
goto push;
|
||||
case 'K': /* (AST) largest to smallest */
|
||||
switch (alt)
|
||||
|
@ -333,8 +333,8 @@ tmxfmt(char* buf, size_t len, const char* format, Time_t t)
|
|||
break;
|
||||
}
|
||||
goto push;
|
||||
case 'l': /* (AST) OBSOLETE use %QL */
|
||||
p = "%QL";
|
||||
case 'l': /* hour (0 - 12) with blank padding */
|
||||
p = "%_I";
|
||||
goto push;
|
||||
case 'L': /* (AST) OBSOLETE use %Ql */
|
||||
p = "%Ql";
|
||||
|
@ -364,9 +364,9 @@ tmxfmt(char* buf, size_t len, const char* format, Time_t t)
|
|||
while (cp < ep && (n = *p++))
|
||||
*cp++ = isupper(n) ? tolower(n) : n;
|
||||
continue;
|
||||
case 'q': /* (AST) OBSOLETE use %Qz */
|
||||
p = "%Qz";
|
||||
goto push;
|
||||
case 'q': /* quarter of the year (1-4) */
|
||||
cp = number(cp, ep, (long)(tm->tm_mon / 3) + 1, 0, width, pad);
|
||||
continue;
|
||||
case 'Q': /* (AST) %Q<alpha> or %Q<delim>recent<delim>distant<delim> */
|
||||
if (c = *format)
|
||||
{
|
||||
|
|
|
@ -95,26 +95,26 @@ USAGE_LICENSE
|
|||
" [+d?day of month number]"
|
||||
" [+D?date as \amm/dd/yy\a]"
|
||||
" [+e?blank padded day of month number]"
|
||||
" [+f?locale default override date format]"
|
||||
" [+f?print a date with the format '\%Y.\%m.\%d-\%H:\%M:\%S']"
|
||||
" [+F?%ISO 8601:2000 standard date format; equivalent to Y-%m-%d]"
|
||||
" [+g?\bls\b(1) \b-l\b recent date with \ahh:mm\a]"
|
||||
" [+G?\bls\b(1) \b-l\b distant date with \ayyyy\a]"
|
||||
" [+h?abbreviated month name]"
|
||||
" [+H?24-hour clock hour]"
|
||||
" [+H?24-hour clock hour, zero-padded]"
|
||||
" [+i?international \bdate\b(1) date with time zone type name]"
|
||||
" [+I?12-hour clock hour]"
|
||||
" [+I?12-hour clock hour, zero-padded]"
|
||||
" [+j?1-offset Julian date]"
|
||||
" [+J?0-offset Julian date]"
|
||||
" [+k?\bdate\b(1) style date]"
|
||||
" [+k?24-hour clock hour, blank-padded]"
|
||||
" [+K?all numeric date; equivalent to \b%Y-%m-%d+%H:%M:%S\b; \b%_[EO]]K\b for space separator, %OK adds \b.%N\b, \b%EK\b adds \b%.N%z\b, \b%_EK\b adds \b.%N %z\b]"
|
||||
" [+l?\bls\b(1) \b-l\b date; equivalent to \b%Q/%g/%G/\b]"
|
||||
" [+l?12-hour clock hour, blank-padded]"
|
||||
" [+L?locale default date format]"
|
||||
" [+m?month number]"
|
||||
" [+M?minutes]"
|
||||
" [+n?newline character]"
|
||||
" [+N?nanoseconds 000000000-999999999]"
|
||||
" [+p?meridian (e.g., \bAM\b or \bPM\b)]"
|
||||
" [+q?time zone type name (nation code)]"
|
||||
" [+q?quarter of the year]"
|
||||
" [+Q?\a<del>recent<del>distant<del>\a: \a<del>\a is a unique"
|
||||
" delimter character; \arecent\a format for recent"
|
||||
" dates, \adistant\a format otherwise]"
|
||||
|
|
Loading…
Reference in a new issue