To: vim_dev@googlegroups.com Subject: Patch 8.1.2326 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2326 Problem: Cannot parse a date/time string. Solution: Add strptime(). (Stephen Wall, closes #) Files: 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 *** ../vim-8.1.2325/runtime/doc/eval.txt 2019-11-16 18:21:57.986848040 +0100 --- runtime/doc/eval.txt 2019-11-21 15:04:08.613993187 +0100 *************** *** 2770,2776 **** 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 strgetchar({str}, {index}) Number get char {index} from {str} stridx({haystack}, {needle} [, {start}]) Number index of {needle} in {haystack} --- 2770,2776 ---- 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 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,2783 **** --- 2778,2785 ---- 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 *************** *** 2885,2891 **** win_id2win({expr}) Number get window nr from window ID win_screenpos({nr}) List get screen position of window {nr} win_splitmove({nr}, {target} [, {options}]) ! none move window {nr} to split of {target} winbufnr({nr}) Number buffer number of window {nr} wincol() Number window column of the cursor winheight({nr}) Number height of window {nr} --- 2887,2893 ---- win_id2win({expr}) Number get window nr from window ID win_screenpos({nr}) List get screen position of window {nr} win_splitmove({nr}, {target} [, {options}]) ! Number move window {nr} to split of {target} winbufnr({nr}) Number buffer number of window {nr} wincol() Number window column of the cursor winheight({nr}) Number height of window {nr} *************** *** 6608,6614 **** localtime() *localtime()* Return the current time, measured as seconds since 1st Jan ! 1970. See also |strftime()| and |getftime()|. log({expr}) *log()* --- 6616,6622 ---- localtime() *localtime()* Return the current time, measured as seconds since 1st Jan ! 1970. See also |strftime()|, |strptime()| and |getftime()|. log({expr}) *log()* *************** *** 7054,7059 **** --- 7062,7068 ---- Can also be used as a |method|: > GetText()->matchstrpos('word') + < *max()* max({expr}) Return the maximum value of all items in {expr}. {expr} can be a list or a dictionary. For a dictionary, *************** *** 9242,9248 **** {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()|. The language can be changed with the |:language| command. Examples: > :echo strftime("%c") Sun Apr 27 11:49:23 1997 --- 9269,9275 ---- {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()|, |getftime()| and |strptime()|. The language can be changed with the |:language| command. Examples: > :echo strftime("%c") Sun Apr 27 11:49:23 1997 *************** *** 9287,9292 **** --- 9314,9320 ---- Can also be used as a |method|: > GetHaystack()->stridx(needle) + < *string()* string({expr}) Return {expr} converted to a String. If {expr} is a Number, Float, String, Blob or a composition of them, then the result *************** *** 9342,9347 **** --- 9370,9403 ---- 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}. *** ../vim-8.1.2325/runtime/doc/usr_41.txt 2019-07-13 21:18:51.468469559 +0200 --- runtime/doc/usr_41.txt 2019-11-21 13:50:04.513247470 +0100 *************** *** 796,801 **** --- 796,802 ---- 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 *** ../vim-8.1.2325/src/auto/configure 2019-11-17 19:07:38.341132068 +0100 --- src/auto/configure 2019-11-21 14:07:02.679652312 +0100 *************** *** 12572,12579 **** 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 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" --- 12572,12579 ---- 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 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" *** ../vim-8.1.2325/src/config.h.in 2019-06-18 22:53:19.014129858 +0200 --- src/config.h.in 2019-11-21 13:45:23.988516112 +0100 *************** *** 206,211 **** --- 206,212 ---- #undef HAVE_STRNCASECMP #undef HAVE_STRNICMP #undef HAVE_STRPBRK + #undef HAVE_STRPTIME #undef HAVE_STRTOL #undef HAVE_CANBERRA #undef HAVE_ST_BLKSIZE *** ../vim-8.1.2325/src/configure.ac 2019-11-17 19:07:38.337132077 +0100 --- src/configure.ac 2019-11-21 13:45:23.988516112 +0100 *************** *** 3744,3751 **** 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) AC_FUNC_SELECT_ARGTYPES AC_FUNC_FSEEKO --- 3744,3751 ---- 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 strptime strtol tgetent towlower towupper iswupper \ ! tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt) AC_FUNC_SELECT_ARGTYPES AC_FUNC_FSEEKO *** ../vim-8.1.2325/src/evalfunc.c 2019-11-16 18:21:57.990848019 +0100 --- src/evalfunc.c 2019-11-21 14:52:42.967501521 +0100 *************** *** 20,27 **** # include #endif ! #ifdef MACOS_X ! # include // for time_t #endif #ifdef FEAT_FLOAT --- 20,27 ---- # include #endif ! #if defined(MACOS_X) ! # include // for time_t #endif #ifdef FEAT_FLOAT *************** *** 237,242 **** --- 237,245 ---- 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,743 **** --- 741,749 ---- {"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,7417 **** --- 7418,7457 ---- 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 */ *** ../vim-8.1.2325/src/os_unix.h 2019-09-04 20:59:10.491409987 +0200 --- src/os_unix.h 2019-11-21 14:25:14.741654669 +0100 *************** *** 127,135 **** # endif #endif #if !defined(HAVE_SYS_TIME_H) || defined(TIME_WITH_SYS_TIME) ! # include /* on some systems time.h should not be ! included together with sys/time.h */ #endif #ifdef HAVE_SYS_TIME_H # include --- 127,142 ---- # 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) ! // Needed for strptime() ! # ifndef _XOPEN_SOURCE ! # define _XOPEN_SOURCE ! # endif ! # ifndef __USE_XOPEN ! # define __USE_XOPEN ! # endif ! # include #endif #ifdef HAVE_SYS_TIME_H # include *** ../vim-8.1.2325/src/testdir/test_functions.vim 2019-11-16 18:21:57.990848019 +0100 --- src/testdir/test_functions.vim 2019-11-21 14:55:38.525894449 +0100 *************** *** 181,189 **** endfunc func Test_strftime() ! if !exists('*strftime') ! return ! endif " Format of strftime() depends on system. We assume " that basic formats tested here are available and " identical on all systems which support strftime(). --- 181,188 ---- endfunc func Test_strftime() ! 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,228 **** --- 221,248 ---- 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() *** ../vim-8.1.2325/src/version.c 2019-11-21 13:27:02.104312710 +0100 --- src/version.c 2019-11-21 13:50:34.172938327 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 2326, /**/ -- hundred-and-one symptoms of being an internet addict: 97. Your mother tells you to remember something, and you look for a File/Save command. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///