diff --git a/autoload/vital/__latest__/DateTime.vim b/autoload/vital/__latest__/DateTime.vim index a5958d6e3..2ddff702c 100644 --- a/autoload/vital/__latest__/DateTime.vim +++ b/autoload/vital/__latest__/DateTime.vim @@ -46,6 +46,7 @@ function! s:_vital_loaded(V) abort \ '_days': 0, \ '_seconds': 0, \ }) + let s:tz_default_offset = s:timezone().offset() endfunction function! s:_vital_depends() abort @@ -454,8 +455,18 @@ function! s:DateTime.format(format, ...) abort endfunction " @vimlint(EVL102, 0, l:locale) function! s:DateTime.strftime(format, ...) abort - let expr = printf('strftime(%s, %d)', string(a:format), self.unix_time()) - return s:_with_locale(expr, a:0 ? a:1 : '') + let tz = self.timezone() + let ts = self.unix_time() + tz.offset() - s:tz_default_offset + let locale = get(a:000, 0, '') + let format = a:format =~? '%z' + \ ? substitute(a:format, '%z', tz.offset_string(), 'g') + \ : a:format + if empty(locale) + return strftime(format, ts) + else + let expr = printf('strftime(%s, %d)', string(format), ts) + return s:_with_locale(expr, locale) + endif endfunction function! s:DateTime.to_string() abort return self.format('%c') diff --git a/doc/vital-date_time.txt b/doc/vital-date_time.txt index 3171cdf6b..bb2a4142a 100644 --- a/doc/vital-date_time.txt +++ b/doc/vital-date_time.txt @@ -192,9 +192,19 @@ DateTime.format({format} [, {locale}]) See |Vital.DateTime-format| about {format}. *Vital.DateTime-DateTime.strftime()* -DateTime.strftime({format} [, {locate}]) - Same as "strftime({format}, dt.unix_time())". - Note that timezone is always converted to current timezone. +DateTime.strftime({format} [, {locale}]) + An alternative version of |Vital.DateTime-DateTime.format()| which + use |strftime()| internally. While |Vital.DateTime-DateTime.format()| + parse {format}, it is really slow compared to using |strftime()|. + However |Vital.DateTime-DateTime.format()| is required while accepted + {format} and a return value of |strftime()| depends on the system. + That's why this function exists for user who need performance but the + accuracy. + It substitutes '%z' in {format} into the value returned from + |Vital.DateTime-TimeZone.offset_string()| while |strftime()| always + return the system default timezone offset string. + See https://gist.github.com/lambdalisue/e73bd722ca8840e82bd8 + for benchmarking. DateTime.to_string() *Vital.DateTime-DateTime.to_string()* Same as "format('%c')". diff --git a/test/DateTime.vimspec b/test/DateTime.vimspec index a3f08eafd..f86d14a41 100644 --- a/test/DateTime.vimspec +++ b/test/DateTime.vimspec @@ -671,8 +671,19 @@ Describe DateTime End Describe .strftime() - It is same as "strftime({format}, dt.unix_time())" - Assert Equals(dt.strftime('%c'), strftime('%c', dt.unix_time())) + Before + " Use non default timezone + let tz = DT.timezone().offset_string() ==# '+0300' ? '+0500' : '+0300' + let dt = DT.from_date(2012, 1, 2, 3, 4, 5, tz) + End + + It is same as "format('%z')" + Assert Equals(dt.strftime('%z'), dt.format('%z')) + End + + It is same as "format('%Y-%m-%d %H:%M:%S')" + let ft = '%Y-%m-%d %H:%M:%S' + Assert Equals(dt.strftime(ft), dt.format(ft)) End End