vim-patch:8.1.2326: cannot parse a date/time string
Problem: Cannot parse a date/time string. Solution: Add strptime(). (Stephen Wall, closes #)10455d43fe
N/A patches for version.c: vim-patch:8.1.2344: Cygwin: warning for using strptime() Problem: Cygwin: warning for using strptime(). Solution: Move defining _XOPEN_SOURCE and __USE_XOPEN to vim.h. (Ken Takata, closes vim/vim#5265) Use 700 for _XOPEN_SOURCE for mkdtemp().6a228c6463
This commit is contained in:
parent
75a9db5b7d
commit
3261ba98a2
|
@ -52,6 +52,7 @@ check_function_exists(setsid HAVE_SETSID)
|
||||||
check_function_exists(sigaction HAVE_SIGACTION)
|
check_function_exists(sigaction HAVE_SIGACTION)
|
||||||
check_function_exists(strcasecmp HAVE_STRCASECMP)
|
check_function_exists(strcasecmp HAVE_STRCASECMP)
|
||||||
check_function_exists(strncasecmp HAVE_STRNCASECMP)
|
check_function_exists(strncasecmp HAVE_STRNCASECMP)
|
||||||
|
check_function_exists(strptime HAVE_STRPTIME)
|
||||||
|
|
||||||
# Symbols
|
# Symbols
|
||||||
check_symbol_exists(FD_CLOEXEC "fcntl.h" HAVE_FD_CLOEXEC)
|
check_symbol_exists(FD_CLOEXEC "fcntl.h" HAVE_FD_CLOEXEC)
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#cmakedefine HAVE_STRCASECMP
|
#cmakedefine HAVE_STRCASECMP
|
||||||
#cmakedefine HAVE_STRINGS_H
|
#cmakedefine HAVE_STRINGS_H
|
||||||
#cmakedefine HAVE_STRNCASECMP
|
#cmakedefine HAVE_STRNCASECMP
|
||||||
|
#cmakedefine HAVE_STRPTIME
|
||||||
#cmakedefine HAVE_SYS_SDT_H
|
#cmakedefine HAVE_SYS_SDT_H
|
||||||
#cmakedefine HAVE_SYS_UTSNAME_H
|
#cmakedefine HAVE_SYS_UTSNAME_H
|
||||||
#cmakedefine HAVE_SYS_WAIT_H
|
#cmakedefine HAVE_SYS_WAIT_H
|
||||||
|
|
|
@ -444,7 +444,7 @@ as a key.
|
||||||
To avoid having to put quotes around every key the #{} form can be used. This
|
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 '_'.
|
does require the key to consist only of ASCII letters, digits, '-' and '_'.
|
||||||
Example: >
|
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 #{}.
|
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
|
A value can be any expression. Using a Dictionary for a value creates a
|
||||||
|
@ -2430,7 +2430,7 @@ strcharpart({str}, {start} [, {len}])
|
||||||
String {len} characters of {str} at
|
String {len} characters of {str} at
|
||||||
character {start}
|
character {start}
|
||||||
strdisplaywidth({expr} [, {col}]) Number display length of the String {expr}
|
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}
|
strgetchar({str}, {index}) Number get char {index} from {str}
|
||||||
stridx({haystack}, {needle} [, {start}])
|
stridx({haystack}, {needle} [, {start}])
|
||||||
Number index of {needle} in {haystack}
|
Number index of {needle} in {haystack}
|
||||||
|
@ -2439,6 +2439,8 @@ strlen({expr}) Number length of the String {expr}
|
||||||
strpart({str}, {start} [, {len} [, {chars}]])
|
strpart({str}, {start} [, {len} [, {chars}]])
|
||||||
String {len} bytes/chars of {str} at
|
String {len} bytes/chars of {str} at
|
||||||
byte {start}
|
byte {start}
|
||||||
|
strptime({format}, {timestring})
|
||||||
|
Number Convert {timestring} to unix timestamp
|
||||||
strridx({haystack}, {needle} [, {start}])
|
strridx({haystack}, {needle} [, {start}])
|
||||||
Number last index of {needle} in {haystack}
|
Number last index of {needle} in {haystack}
|
||||||
strtrans({expr}) String translate string to make it printable
|
strtrans({expr}) String translate string to make it printable
|
||||||
|
@ -4983,7 +4985,7 @@ getwininfo([{winid}]) *getwininfo()*
|
||||||
|
|
||||||
getwinpos([{timeout}]) *getwinpos()*
|
getwinpos([{timeout}]) *getwinpos()*
|
||||||
The result is a list with two numbers, the result of
|
The result is a list with two numbers, the result of
|
||||||
getwinposx() and getwinposy() combined:
|
|getwinposx()| and |getwinposy()| combined:
|
||||||
[x-pos, y-pos]
|
[x-pos, y-pos]
|
||||||
{timeout} can be used to specify how long to wait in msec for
|
{timeout} can be used to specify how long to wait in msec for
|
||||||
a response from the terminal. When omitted 100 msec is used.
|
a response from the terminal. When omitted 100 msec is used.
|
||||||
|
@ -5853,7 +5855,7 @@ list2str({list} [, {utf8}]) *list2str()*
|
||||||
<
|
<
|
||||||
localtime() *localtime()*
|
localtime() *localtime()*
|
||||||
Return the current time, measured as seconds since 1st Jan
|
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()*
|
log({expr}) *log()*
|
||||||
|
@ -8488,7 +8490,7 @@ strftime({format} [, {time}]) *strftime()*
|
||||||
{format} depends on your system, thus this is not portable!
|
{format} depends on your system, thus this is not portable!
|
||||||
See the manual page of the C function strftime() for the
|
See the manual page of the C function strftime() for the
|
||||||
format. The maximum length of the result is 80 characters.
|
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.
|
The language can be changed with the |:language| command.
|
||||||
Examples: >
|
Examples: >
|
||||||
:echo strftime("%c") Sun Apr 27 11:49:23 1997
|
:echo strftime("%c") Sun Apr 27 11:49:23 1997
|
||||||
|
@ -8578,6 +8580,31 @@ strpart({src}, {start} [, {len} [, {chars}]]) *strpart()*
|
||||||
example, to get the character under the cursor: >
|
example, to get the character under the cursor: >
|
||||||
strpart(getline("."), col(".") - 1, 1, v:true)
|
strpart(getline("."), col(".") - 1, 1, v:true)
|
||||||
<
|
<
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
strridx({haystack}, {needle} [, {start}]) *strridx()*
|
strridx({haystack}, {needle} [, {start}]) *strridx()*
|
||||||
The result is a Number, which gives the byte index in
|
The result is a Number, which gives the byte index in
|
||||||
{haystack} of the last occurrence of the String {needle}.
|
{haystack} of the last occurrence of the String {needle}.
|
||||||
|
|
|
@ -788,6 +788,7 @@ Date and Time: *date-functions* *time-functions*
|
||||||
getftime() get last modification time of a file
|
getftime() get last modification time of a file
|
||||||
localtime() get current time in seconds
|
localtime() get current time in seconds
|
||||||
strftime() convert time to a string
|
strftime() convert time to a string
|
||||||
|
strptime() convert a date/time string to time
|
||||||
reltime() get the current or elapsed time accurately
|
reltime() get the current or elapsed time accurately
|
||||||
reltimestr() convert reltime() result to a string
|
reltimestr() convert reltime() result to a string
|
||||||
reltimefloat() convert reltime() result to a Float
|
reltimefloat() convert reltime() result to a Float
|
||||||
|
|
|
@ -341,6 +341,7 @@ return {
|
||||||
string={args=1},
|
string={args=1},
|
||||||
strlen={args=1},
|
strlen={args=1},
|
||||||
strpart={args={2, 4}},
|
strpart={args={2, 4}},
|
||||||
|
strptime={args=2},
|
||||||
strridx={args={2, 3}},
|
strridx={args={2, 3}},
|
||||||
strtrans={args=1},
|
strtrans={args=1},
|
||||||
strwidth={args=1},
|
strwidth={args=1},
|
||||||
|
|
|
@ -10189,6 +10189,36 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len);
|
rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "strptime({format}, {timestring})" function
|
||||||
|
static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
char fmt_buf[NUMBUFLEN];
|
||||||
|
char str_buf[NUMBUFLEN];
|
||||||
|
|
||||||
|
struct tm tmval = { 0 };
|
||||||
|
char *fmt = (char *)tv_get_string_buf(&argvars[0], fmt_buf);
|
||||||
|
char *str = (char *)tv_get_string_buf(&argvars[1], str_buf);
|
||||||
|
|
||||||
|
vimconv_T conv = {
|
||||||
|
.vc_type = CONV_NONE,
|
||||||
|
};
|
||||||
|
char_u *enc = enc_locale();
|
||||||
|
convert_setup(&conv, p_enc, enc);
|
||||||
|
if (conv.vc_type != CONV_NONE) {
|
||||||
|
fmt = (char *)string_convert(&conv, (char_u *)fmt, NULL);
|
||||||
|
}
|
||||||
|
if (fmt == NULL
|
||||||
|
|| os_strptime(str, fmt, &tmval) == NULL
|
||||||
|
|| (rettv->vval.v_number = mktime(&tmval)) == -1) {
|
||||||
|
rettv->vval.v_number = 0;
|
||||||
|
}
|
||||||
|
if (conv.vc_type != CONV_NONE) {
|
||||||
|
xfree(fmt);
|
||||||
|
}
|
||||||
|
convert_setup(&conv, NULL, NULL);
|
||||||
|
xfree(enc);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "strridx()" function
|
* "strridx()" function
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -196,6 +196,22 @@ char *os_ctime(char *result, size_t result_len)
|
||||||
return os_ctime_r(&rawtime, result, result_len);
|
return os_ctime_r(&rawtime, result, result_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Portable version of POSIX strptime()
|
||||||
|
///
|
||||||
|
/// @param str[in] string to convert
|
||||||
|
/// @param format[in] format to parse "str"
|
||||||
|
/// @param tm[out] time representation of "str"
|
||||||
|
/// @return Pointer to first unprocessed character or NULL
|
||||||
|
char *os_strptime(const char *str, const char *format, struct tm *tm)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
#ifdef HAVE_STRPTIME
|
||||||
|
return strptime(str, format, tm);
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// Obtains the current Unix timestamp.
|
/// Obtains the current Unix timestamp.
|
||||||
///
|
///
|
||||||
/// @return Seconds since epoch.
|
/// @return Seconds since epoch.
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
" Tests for various functions.
|
" Tests for various functions.
|
||||||
|
|
||||||
source shared.vim
|
source shared.vim
|
||||||
|
source check.vim
|
||||||
|
|
||||||
" Must be done first, since the alternate buffer must be unset.
|
" Must be done first, since the alternate buffer must be unset.
|
||||||
func Test_00_bufexists()
|
func Test_00_bufexists()
|
||||||
|
@ -171,9 +173,8 @@ func Test_str2nr()
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_strftime()
|
func Test_strftime()
|
||||||
if !exists('*strftime')
|
CheckFunction strftime
|
||||||
return
|
|
||||||
endif
|
|
||||||
" Format of strftime() depends on system. We assume
|
" Format of strftime() depends on system. We assume
|
||||||
" that basic formats tested here are available and
|
" that basic formats tested here are available and
|
||||||
" identical on all systems which support strftime().
|
" identical on all systems which support strftime().
|
||||||
|
@ -214,6 +215,28 @@ func Test_strftime()
|
||||||
endif
|
endif
|
||||||
endfunc
|
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()
|
func Test_resolve_unix()
|
||||||
if !has('unix')
|
if !has('unix')
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue