]> granicus.if.org Git - vim/commitdiff
patch 8.1.2326: cannot parse a date/time string v8.1.2326
authorBram Moolenaar <Bram@vim.org>
Thu, 21 Nov 2019 14:36:18 +0000 (15:36 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 21 Nov 2019 14:36:18 +0000 (15:36 +0100)
Problem:    Cannot parse a date/time string.
Solution:   Add strptime(). (Stephen Wall, closes #)

runtime/doc/eval.txt
runtime/doc/usr_41.txt
src/auto/configure
src/config.h.in
src/configure.ac
src/evalfunc.c
src/os_unix.h
src/testdir/test_functions.vim
src/version.c

index 2a040130f1158a8246de281145b77d1531f62524..7c8c8d30f48301af3b0ab69d631cf7ee13a6d501 100644 (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}.
index be116ad9251610ff5bbf131423932fa150da3ac5..79e3a087cc7429994331b08a466b0c305c098c60 100644 (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
index d591ab5f1c72f30ebbe6a19692cfb647ec6fa9e5..713bf9ea80b867e12677de0b84b0f57a9fd7e644 100755 (executable)
@@ -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"
index f9ae0bbf3d51f9ee2ced85134dead03d3036e35d..e17f036c7c1d624fb0383bec220342373d141d96 100644 (file)
 #undef HAVE_STRNCASECMP
 #undef HAVE_STRNICMP
 #undef HAVE_STRPBRK
+#undef HAVE_STRPTIME
 #undef HAVE_STRTOL
 #undef HAVE_CANBERRA
 #undef HAVE_ST_BLKSIZE
index 4065817f34f60ebba36fa4994835eb6b0bc5ffea..6a10638e01e1a9ca7a5a8099225131d9c61552c3 100644 (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
 
index 945c5f227f213e1336f753ba55048deaae54a79b..63c4057ba780db5df187f65aaa03084e638bdb0d 100644 (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
  */
index 618c0e97084baa4f753fdbe629aa8469c110984e..a7a0c841f1454745329d9d446245da4df931df15 100644 (file)
 # 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>
index e7b81daf4bb80cb84263d27c1052865453149478..7284787834473508d9e51373256646a4bc38d3ad 100644 (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()
index c448e57fd65d00d7a60f30c5201044d317480ba0..23a1fc8cc7e18c4da1a10c2124aa54c737f9c667 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2326,
 /**/
     2325,
 /**/