0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.1.2326: cannot parse a date/time string

Problem:    Cannot parse a date/time string.
Solution:   Add strptime(). (Stephen Wall, closes #)
This commit is contained in:
Bram Moolenaar
2019-11-21 15:36:18 +01:00
parent 9ae862ebba
commit 10455d43fe
9 changed files with 121 additions and 20 deletions

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.1. Last change: 2019 Nov 17
*eval.txt* For Vim version 8.1. Last change: 2019 Nov 21
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -488,7 +488,7 @@ as a key.
To avoid having to put quotes around every key the #{} form can be used. This
does require the key to consist only of ASCII letters, digits, '-' and '_'.
Example: >
let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3}
:let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3}
Note that 333 here is the string "333". Empty keys are not possible with #{}.
A value can be any expression. Using a Dictionary for a value creates a
@@ -2667,7 +2667,7 @@ remote_read({serverid} [, {timeout}])
remote_send({server}, {string} [, {idvar}])
String send key sequence
remote_startserver({name}) none become server {name}
remove({list}, {idx} [, {end}]) any/List
remove({list}, {idx} [, {end}]) any/List
remove items {idx}-{end} from {list}
remove({blob}, {idx} [, {end}]) Number/Blob
remove bytes {idx}-{end} from {blob}
@@ -2770,7 +2770,7 @@ strchars({expr} [, {skipcc}]) Number character length of the String {expr}
strcharpart({str}, {start} [, {len}])
String {len} characters of {str} at {start}
strdisplaywidth({expr} [, {col}]) Number display length of the String {expr}
strftime({format} [, {time}]) String time in specified format
strftime({format} [, {time}]) String format time with a specified format
strgetchar({str}, {index}) Number get char {index} from {str}
stridx({haystack}, {needle} [, {start}])
Number index of {needle} in {haystack}
@@ -2778,6 +2778,8 @@ string({expr}) String String representation of {expr} value
strlen({expr}) Number length of the String {expr}
strpart({str}, {start} [, {len}])
String {len} characters of {str} at {start}
strptime({format}, {timestring})
Number Convert {timestring} to unix timestamp
strridx({haystack}, {needle} [, {start}])
Number last index of {needle} in {haystack}
strtrans({expr}) String translate string to make it printable
@@ -5634,7 +5636,7 @@ getwininfo([{winid}]) *getwininfo()*
terminal 1 if a terminal window
{only with the +terminal feature}
tabnr tab page number
topline first displayed buffer line
topline first displayed buffer line
variables a reference to the dictionary with
window-local variables
width window width
@@ -5652,7 +5654,7 @@ getwininfo([{winid}]) *getwininfo()*
getwinpos([{timeout}]) *getwinpos()*
The result is a list with two numbers, the result of
getwinposx() and getwinposy() combined:
|getwinposx()| and |getwinposy()| combined:
[x-pos, y-pos]
{timeout} can be used to specify how long to wait in msec for
a response from the terminal. When omitted 100 msec is used.
@@ -6614,7 +6616,7 @@ listener_remove({id}) *listener_remove()*
localtime() *localtime()*
Return the current time, measured as seconds since 1st Jan
1970. See also |strftime()| and |getftime()|.
1970. See also |strftime()|, |strptime()| and |getftime()|.
log({expr}) *log()*
@@ -7103,9 +7105,9 @@ mkdir({name} [, {path} [, {prot}]])
There is no error if the directory already exists and the "p"
flag is passed (since patch 8.0.1708). However, without the
"p" option the call will fail.
"p" option the call will fail.
The function result is a Number, which is 1 if the call was
The function result is a Number, which is 1 if the call was
successful or 0 if the directory creation failed or partly
failed.
@@ -9267,7 +9269,7 @@ strftime({format} [, {time}]) *strftime()*
{format} depends on your system, thus this is not portable!
See the manual page of the C function strftime() for the
format. The maximum length of the result is 80 characters.
See also |localtime()| and |getftime()|.
See also |localtime()|, |getftime()| and |strptime()|.
The language can be changed with the |:language| command.
Examples: >
:echo strftime("%c") Sun Apr 27 11:49:23 1997
@@ -9368,6 +9370,34 @@ strpart({src}, {start} [, {len}]) *strpart()*
Can also be used as a |method|: >
GetText()->strpart(5)
strptime({format}, {timestring}) *strptime()*
The result is a Number, which is a unix timestamp representing
the date and time in {timestring}, which is expected to match
the format specified in {format}.
The accepted {format} depends on your system, thus this is not
portable! See the manual page of the C function strptime()
for the format. Especially avoid "%c". The value of $TZ also
matters.
If the {timestring} cannot be parsed with {format} zero is
returned. If you do not know the format of {timestring} you
can try different {format} values until you get a non-zero
result.
See also |strftime()|.
Examples: >
:echo strptime("%Y %b %d %X", "1997 Apr 27 11:49:23")
< 862156163 >
:echo strftime("%c", strptime("%y%m%d %T", "970427 11:53:55"))
< Sun Apr 27 11:53:55 1997 >
:echo strftime("%c", strptime("%Y%m%d%H%M%S", "19970427115355") + 3600)
< Sun Apr 27 12:53:55 1997
Not available on all systems. To check use: >
:if exists("*strptime")
strridx({haystack}, {needle} [, {start}]) *strridx()*
The result is a Number, which gives the byte index in
{haystack} of the last occurrence of the String {needle}.

View File

@@ -796,6 +796,7 @@ Date and Time: *date-functions* *time-functions*
getftime() get last modification time of a file
localtime() get current time in seconds
strftime() convert time to a string
strptime() convert a date/time string to time
reltime() get the current or elapsed time accurately
reltimestr() convert reltime() result to a string
reltimefloat() convert reltime() result to a Float

4
src/auto/configure vendored
View File

@@ -12572,8 +12572,8 @@ for ac_func in fchdir fchown fchmod fsync getcwd getpseudotty \
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
strnicmp strpbrk strtol tgetent towlower towupper iswupper tzset \
usleep utime utimes mblen ftruncate unsetenv posix_openpt
strnicmp strpbrk strptime strtol tgetent towlower towupper iswupper \
tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

View File

@@ -206,6 +206,7 @@
#undef HAVE_STRNCASECMP
#undef HAVE_STRNICMP
#undef HAVE_STRPBRK
#undef HAVE_STRPTIME
#undef HAVE_STRTOL
#undef HAVE_CANBERRA
#undef HAVE_ST_BLKSIZE

View File

@@ -3744,8 +3744,8 @@ AC_CHECK_FUNCS(fchdir fchown fchmod fsync getcwd getpseudotty \
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
strnicmp strpbrk strtol tgetent towlower towupper iswupper tzset \
usleep utime utimes mblen ftruncate unsetenv posix_openpt)
strnicmp strpbrk strptime strtol tgetent towlower towupper iswupper \
tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt)
AC_FUNC_SELECT_ARGTYPES
AC_FUNC_FSEEKO

View File

@@ -20,7 +20,7 @@
# include <float.h>
#endif
#ifdef MACOS_X
#if defined(MACOS_X)
# include <time.h> // for time_t
#endif
@@ -237,6 +237,9 @@ static void f_stridx(typval_T *argvars, typval_T *rettv);
static void f_strlen(typval_T *argvars, typval_T *rettv);
static void f_strcharpart(typval_T *argvars, typval_T *rettv);
static void f_strpart(typval_T *argvars, typval_T *rettv);
#ifdef HAVE_STRPTIME
static void f_strptime(typval_T *argvars, typval_T *rettv);
#endif
static void f_strridx(typval_T *argvars, typval_T *rettv);
static void f_strtrans(typval_T *argvars, typval_T *rettv);
static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv);
@@ -738,6 +741,9 @@ static funcentry_T global_functions[] =
{"string", 1, 1, FEARG_1, f_string},
{"strlen", 1, 1, FEARG_1, f_strlen},
{"strpart", 2, 3, FEARG_1, f_strpart},
#ifdef HAVE_STRPTIME
{"strptime", 2, 2, FEARG_1, f_strptime},
#endif
{"strridx", 2, 3, FEARG_1, f_strridx},
{"strtrans", 1, 1, FEARG_1, f_strtrans},
{"strwidth", 1, 1, FEARG_1, f_strwidth},
@@ -7412,6 +7418,40 @@ f_strpart(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string = vim_strnsave(p + n, len);
}
#ifdef HAVE_STRPTIME
/*
* "strptime({format}, {timestring})" function
*/
static void
f_strptime(typval_T *argvars, typval_T *rettv)
{
struct tm tmval;
char_u *fmt;
char_u *str;
vimconv_T conv;
char_u *enc;
vim_memset(&tmval, NUL, sizeof(tmval));
fmt = tv_get_string(&argvars[0]);
str = tv_get_string(&argvars[1]);
conv.vc_type = CONV_NONE;
enc = enc_locale();
convert_setup(&conv, p_enc, enc);
if (conv.vc_type != CONV_NONE)
fmt = string_convert(&conv, fmt, NULL);
if (fmt == NULL
|| strptime((char *)str, (char *)fmt, &tmval) == NULL
|| (rettv->vval.v_number = mktime(&tmval)) == -1)
rettv->vval.v_number = 0;
if (conv.vc_type != CONV_NONE)
vim_free(fmt);
convert_setup(&conv, NULL, NULL);
vim_free(enc);
}
#endif
/*
* "strridx()" function
*/

View File

@@ -127,9 +127,16 @@
# endif
#endif
// on some systems time.h should not be included together with sys/time.h
#if !defined(HAVE_SYS_TIME_H) || defined(TIME_WITH_SYS_TIME)
# include <time.h> /* on some systems time.h should not be
included together with sys/time.h */
// Needed for strptime()
# ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE
# endif
# ifndef __USE_XOPEN
# define __USE_XOPEN
# endif
# include <time.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>

View File

@@ -181,9 +181,8 @@ func Test_str2nr()
endfunc
func Test_strftime()
if !exists('*strftime')
return
endif
CheckFunction strftime
" Format of strftime() depends on system. We assume
" that basic formats tested here are available and
" identical on all systems which support strftime().
@@ -222,7 +221,28 @@ func Test_strftime()
else
unlet $TZ
endif
endfunc
func Test_strptime()
CheckFunction strptime
if exists('$TZ')
let tz = $TZ
endif
let $TZ = 'UTC'
call assert_equal(1484653763, strptime('%Y-%m-%d %X', '2017-01-17 11:49:23'))
call assert_fails('call strptime()', 'E119:')
call assert_fails('call strptime("xxx")', 'E119:')
call assert_equal(0, strptime("%Y", ''))
call assert_equal(0, strptime("%Y", "xxx"))
if exists('tz')
let $TZ = tz
else
unlet $TZ
endif
endfunc
func Test_resolve_unix()

View File

@@ -741,6 +741,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2326,
/**/
2325,
/**/