1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 02:20:03 +08:00
SpaceVim/bundle/gina.vim/autoload/vital/_gina/DateTime.vim

826 lines
24 KiB
VimL

" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not modify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_gina#DateTime#import() abort', printf("return map({'now': '', '_vital_depends': '', 'from_julian_day': '', 'from_format': '', 'am_pm_names': '', 'delta': '', 'from_unix_time': '', 'month_names': '', 'is_leap_year': '', 'compare': '', 'weekday_names': '', 'from_date': '', 'timezone': '', '_vital_loaded': ''}, \"vital#_gina#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
" date and time library.
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V) abort
let s:V = a:V
let s:Prelude = s:V.import('Prelude')
let s:Process = s:V.import('Process')
let s:Bitwise = s:V.import('Bitwise')
let s:NUM_SECONDS = 60
let s:NUM_MINUTES = 60
let s:NUM_HOURS = 24
let s:NUM_DAYS_OF_WEEK = 7
let s:NUM_MONTHS = 12
let s:SECONDS_OF_HOUR = s:NUM_SECONDS * s:NUM_MINUTES
let s:SECONDS_OF_DAY = s:SECONDS_OF_HOUR * s:NUM_HOURS
let s:ERA_TIME = s:_g2jd(1, 1, 1)
let s:EPOC_TIME = s:_g2jd(1970, 1, 1)
let s:MONTHS = map(range(1, 12),
\ 's:from_date(1970, v:val, 1, 0, 0, 0, 0).unix_time()')
let s:WEEKS = map(range(4, 10),
\ 's:from_date(1970, 1, v:val, 0, 0, 0, 0).unix_time()')
let s:AM_PM_TIMES = map([0, 12],
\ 's:from_date(1970, 1, 1, v:val, 0, 0, 0).unix_time()')
" default values
call extend(s:DateTime, {
\ '_year': 0,
\ '_month': 1,
\ '_day': 1,
\ '_hour': 0,
\ '_minute': 0,
\ '_second': 0,
\ '_timezone': s:timezone(),
\ })
call extend(s:TimeDelta, {
\ '_days': 0,
\ '_seconds': 0,
\ })
let s:tz_default_offset = s:timezone().offset()
endfunction
function! s:_vital_depends() abort
return ['Prelude', 'Process', 'Bitwise']
endfunction
" Creates a DateTime object with current time from system.
function! s:now(...) abort
let now = s:from_unix_time(localtime())
if a:0
let now = now.to(s:timezone(a:1))
endif
return now
endfunction
" Creates a DateTime object from given unix time.
function! s:from_unix_time(unix_time, ...) abort
let tz = call('s:timezone', a:000)
return call('s:from_date',
\ map(split(strftime('%Y %m %d %H %M %S', a:unix_time)),
\ 'str2nr(v:val, 10)')).to(tz)
endfunction
" Creates a DateTime object from given date and time.
" @param year = 1970
" @param month = 1
" @param day = 1
" @param hour = 0
" @param minute = 0
" @param second = 0
" @param timezone = ''
function! s:from_date(...) abort
let o = copy(s:DateTime)
let [o._year, o._month, o._day, o._hour, o._minute, o._second, tz] =
\ a:000 + [1970, 1, 1, 0, 0, 0, ''][a:0 :]
let o._timezone = s:timezone(tz)
return o._normalize()
endfunction
" Creates a DateTime object from format.
function! s:from_format(string, format, ...) abort
let o = copy(s:DateTime)
let locale = a:0 ? a:1 : ''
let remain = a:string
let skip_pattern = ''
for f in s:_split_format(a:format)
if s:Prelude.is_string(f)
let pat = '^' . skip_pattern . '\V' . escape(f, '\')
let matched_len = len(matchstr(remain, pat))
if matched_len == 0
throw join([
\ 'vital: DateTime: Parse error:',
\ 'input: ' . a:string,
\ 'format: ' . a:format,
\ ], "\n")
endif
let remain = remain[matched_len :]
else " if s:Prelude.is_list(f)
let info = f[0]
if info[0] ==# '#skip'
let skip_pattern = info[1]
else
let remain = s:_read_format(o, f, remain, skip_pattern, locale)
let skip_pattern = ''
endif
endif
unlet f
endfor
return o._normalize()
endfunction
" @vimlint(EVL102, 1, l:locale)
function! s:_read_format(datetime, descriptor, remain, skip_pattern, locale) abort
" "o", "key", "value" and "locale" are used by parse_conv
let o = a:datetime
let locale = a:locale " for parse_conv
let [info, flag, width] = a:descriptor
let key = '_' . info[0]
if !has_key(o, key)
let key = '_'
endif
let Captor = info[1]
if s:Prelude.is_funcref(Captor)
let pattern = call(Captor, [a:locale], {})
if s:Prelude.is_list(pattern)
let candidates = pattern
unlet pattern
let pattern = '\%(' . join(candidates, '\|') . '\)'
endif
elseif s:Prelude.is_list(Captor)
if width ==# ''
let width = Captor[1]
endif
let pattern = '\d\{1,' . width . '}'
if flag ==# '_'
let pattern = '\s*' . pattern
endif
else " if s:Prelude.is_string(Captor)
let pattern = Captor
endif
let value = matchstr(a:remain, '^' . a:skip_pattern . pattern)
let matched_len = len(value)
if exists('candidates')
let value = index(candidates, value)
elseif s:Prelude.is_list(Captor)
let value = str2nr(value, 10)
endif
if 4 <= len(info)
let l:['value'] = eval(info[3])
endif
if key !=# '_'
let o[key] = value
endif
return a:remain[matched_len :]
endfunction
" @vimlint(EVL102, 0, l:locale)
" Creates a DateTime object from Julian day.
function! s:from_julian_day(jd, ...) abort
let tz = call('s:timezone', a:000)
let second = 0
if s:Prelude.is_float(a:jd)
let jd = float2nr(floor(a:jd))
let second = float2nr(s:SECONDS_OF_DAY * (a:jd - jd))
else
let jd = a:jd
endif
let [year, month, day] = s:_jd2g(jd)
return s:from_date(year, month, day, 12, 0, second, '+0000').to(tz)
endfunction
" Creates a new TimeZone object.
function! s:timezone(...) abort
let info = a:0 ? a:1 : ''
if s:_is_class(info, 'TimeZone')
return info
endif
if info is# ''
unlet info
let info = s:_default_tz()
endif
let tz = copy(s:TimeZone)
if s:Prelude.is_number(info)
let tz._offset = info * s:NUM_MINUTES * s:NUM_SECONDS
elseif s:Prelude.is_string(info)
let list = matchlist(info, '\v^([+-])?(\d{1,2}):?(\d{1,2})?$')
if !empty(list)
let tz._offset = str2nr(list[1] . s:NUM_SECONDS) *
\ (str2nr(list[2]) * s:NUM_MINUTES + str2nr(list[3]))
else
" TODO: TimeZone names
throw 'vital: DateTime: Unknown timezone: ' . string(info)
endif
else
throw 'vital: DateTime: Invalid timezone: ' . string(info)
endif
return tz
endfunction
" Creates a new TimeDelta object.
function! s:delta(...) abort
let info = a:0 ? a:1 : ''
if s:_is_class(info, 'TimeDelta')
return info
endif
let d = copy(s:TimeDelta)
if a:0 == 2 && s:Prelude.is_number(a:1) && s:Prelude.is_number(a:2)
let d._days = a:1
let d._seconds = a:2
else
let a = copy(a:000)
while 2 <= len(a) && s:Prelude.is_number(a[0]) && s:Prelude.is_string(a[1])
let [value, unit] = remove(a, 0, 1)
if unit =~? '^sec\%(onds\?\)\?$'
let d._seconds += value
elseif unit =~? '^min\%(utes\?\)\?$'
let d._seconds += value * s:NUM_SECONDS
elseif unit =~? '^hours\?$'
let d._seconds += value * s:SECONDS_OF_HOUR
elseif unit =~? '^days\?$'
let d._days += value
elseif unit =~? '^weeks\?$'
let d._days += value * s:NUM_DAYS_OF_WEEK
else
throw 'vital: DateTime: Invalid unit for delta(): ' . string(unit)
endif
endwhile
if !empty(a)
throw 'vital: DateTime: Invalid arguments for delta(): ' . string(a)
endif
endif
return d._normalize()
endfunction
function! s:compare(d1, d2) abort
return a:d1.compare(a:d2)
endfunction
" Returns month names according to the current or specified locale.
" @param fullname = false
" @param locale = ''
function! s:month_names(...) abort
return s:_names(s:MONTHS, a:0 && a:1 ? '%B' : '%b', get(a:000, 1, ''))
endfunction
" Returns weekday names according to the current or specified locale.
" @param fullname = false
" @param locale = ''
function! s:weekday_names(...) abort
return s:_names(s:WEEKS, a:0 && a:1 ? '%A' : '%a', get(a:000, 1, ''))
endfunction
" Returns am/pm names according to the current or specified locale.
" @param lowercase = false
" @param locale = ''
function! s:am_pm_names(...) abort
let [lowercase, locale] = a:000 + [0, ''][a:0 :]
let names = s:_am_pm_names(lowercase, locale)
if lowercase
" Some environments do not support %P.
" In this case, use tolower() of %p instead of.
let failed = names[0] ==# '' || names[0] ==# 'P'
if failed
let names = s:_am_pm_names(0, locale)
call map(names, 'tolower(v:val)')
endif
endif
return names
endfunction
function! s:_am_pm_names(lowercase, locale) abort
return s:_names(s:AM_PM_TIMES, a:lowercase ? '%P' : '%p', a:locale)
endfunction
" Returns 1 if the year is a leap year.
function! s:is_leap_year(year) abort
return a:year % 4 == 0 && a:year % 100 != 0 || a:year % 400 == 0
endfunction
" ----------------------------------------------------------------------------
let s:Class = {}
function! s:Class._clone() abort
return filter(copy(self), 'v:key !~# "^__"')
endfunction
function! s:_new_class(class) abort
return extend({'class': a:class}, s:Class)
endfunction
function! s:_is_class(obj, class) abort
return s:Prelude.is_dict(a:obj) && get(a:obj, 'class', '') ==# a:class
endfunction
" ----------------------------------------------------------------------------
let s:DateTime = s:_new_class('DateTime')
function! s:DateTime.year() abort
return self._year
endfunction
function! s:DateTime.month() abort
return self._month
endfunction
function! s:DateTime.day() abort
return self._day
endfunction
function! s:DateTime.hour() abort
return self._hour
endfunction
function! s:DateTime.minute() abort
return self._minute
endfunction
function! s:DateTime.second() abort
return self._second
endfunction
function! s:DateTime.timezone(...) abort
if a:0
let dt = self._clone()
let dt._timezone = call('s:timezone', a:000)
return dt
endif
return self._timezone
endfunction
function! s:DateTime.day_of_week() abort
if !has_key(self, '__day_of_week')
let self.__day_of_week = self.timezone(0).days_from_era() % 7
endif
return self.__day_of_week
endfunction
function! s:DateTime.day_of_year() abort
if !has_key(self, '__day_of_year')
let self.__day_of_year = self.timezone(0).julian_day() -
\ s:_g2jd(self._year, 1, 1) + 1
endif
return self.__day_of_year
endfunction
function! s:DateTime.days_from_era() abort
if !has_key(self, '__day_from_era')
let self.__day_from_era = self.julian_day() - s:ERA_TIME + 1
endif
return self.__day_from_era
endfunction
function! s:DateTime.julian_day(...) abort
let utc = self.to(0)
let jd = s:_g2jd(utc._year, utc._month, utc._day)
if a:0 && a:1
if has('float')
let jd += (utc.seconds_of_day() + 0.0) / s:SECONDS_OF_DAY - 0.5
elseif utc._hour < 12
let jd -= 1
endif
endif
return jd
endfunction
function! s:DateTime.seconds_of_day() abort
return (self._hour * s:NUM_MINUTES + self._minute)
\ * s:NUM_SECONDS + self._second
endfunction
function! s:DateTime.quarter() abort
return (self._month - 1) / 3 + 1
endfunction
function! s:DateTime.unix_time() abort
if !has_key(self, '__unix_time')
if self._year < 1969 ||
\ (!has('num64') && (2038 < self._year))
let self.__unix_time = -1
else
let utc = self.to(0)
let self.__unix_time = (utc.julian_day() - s:EPOC_TIME) *
\ s:SECONDS_OF_DAY + utc.seconds_of_day()
if self.__unix_time < 0
let self.__unix_time = -1
endif
endif
endif
return self.__unix_time
endfunction
function! s:DateTime.is_leap_year() abort
return s:is_leap_year(self._year)
endfunction
function! s:DateTime.is(dt) abort
return self.compare(a:dt) == 0
endfunction
function! s:DateTime.compare(dt) abort
return self.delta(a:dt).sign()
endfunction
function! s:DateTime.delta(dt) abort
let left = self.to(0)
let right = a:dt.to(0)
return s:delta(left.days_from_era() - right.days_from_era(),
\ (left.seconds_of_day() + left.timezone().offset()) -
\ (right.seconds_of_day() + right.timezone().offset()))
endfunction
function! s:DateTime.to(...) abort
let dt = self._clone()
if a:0 == 1 && !s:_is_class(a:1, 'TimeDelta')
let tz = s:timezone(a:1)
let dt._second += tz.offset() - dt.timezone().offset()
let dt._timezone = tz
return dt._normalize()
endif
let delta = call('s:delta', a:000)
let dt._day += delta._days
let dt._second += delta._seconds
return dt._normalize()
endfunction
" @vimlint(EVL102, 1, l:locale)
function! s:DateTime.format(format, ...) abort
let locale = a:0 ? a:1 : ''
let result = ''
for f in s:_split_format(a:format)
if s:Prelude.is_string(f)
let result .= f
elseif s:Prelude.is_list(f)
let [info, flag, width] = f
let padding = ''
if s:Prelude.is_list(info[1])
let [padding, w] = info[1]
if width ==# ''
let width = w
endif
endif
if has_key(self, info[0])
let value = self[info[0]]()
if 2 < len(info)
let l:['value'] = eval(info[2])
endif
elseif 2 < len(info)
let value = info[2]
else
let value = ''
endif
if flag ==# '^'
let value = toupper(value)
elseif flag ==# '-'
let padding = ''
elseif flag ==# '_'
let padding = ' '
elseif flag ==# '0'
let padding = '0'
endif
let result .= printf('%' . padding . width . 's', value)
unlet value
endif
unlet f
endfor
return result
endfunction
" @vimlint(EVL102, 0, l:locale)
function! s:DateTime.strftime(format, ...) abort
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')
endfunction
function! s:DateTime._normalize() abort
let next = 0
for unit in ['second', 'minute', 'hour']
let key = '_' . unit
let self[key] += next
let [next, self[key]] =
\ s:_divmod(self[key], s:['NUM_' . toupper(unit . 's')])
endfor
let self._day += next
let [self._year, self._month, self._day] =
\ s:_jd2g(s:_g2jd(self._year, self._month, self._day))
return self
endfunction
let s:DateTime['+'] = s:DateTime.to
let s:DateTime['-'] = s:DateTime.delta
let s:DateTime['=='] = s:DateTime.is
" ----------------------------------------------------------------------------
let s:TimeZone = s:_new_class('TimeZone')
function! s:TimeZone.offset() abort
return self._offset
endfunction
function! s:TimeZone.minutes() abort
return self._offset / s:NUM_SECONDS
endfunction
function! s:TimeZone.hours() abort
return self._offset / s:SECONDS_OF_HOUR
endfunction
function! s:TimeZone.sign() abort
return self._offset < 0 ? -1 : 0 < self._offset ? 1 : 0
endfunction
function! s:TimeZone.offset_string() abort
return substitute(self.w3c(), ':', '', '')
endfunction
function! s:TimeZone.w3c() abort
let sign = self._offset < 0 ? '-' : '+'
let minutes = abs(self._offset) / s:NUM_SECONDS
return printf('%s%02d:%02d', sign,
\ minutes / s:NUM_MINUTES, minutes % s:NUM_MINUTES)
endfunction
" ----------------------------------------------------------------------------
let s:TimeDelta = s:_new_class('TimeDelta')
function! s:TimeDelta.seconds() abort
return self._seconds % s:NUM_SECONDS
endfunction
function! s:TimeDelta.minutes() abort
return self._seconds / s:NUM_SECONDS % s:NUM_MINUTES
endfunction
function! s:TimeDelta.hours() abort
return self._seconds / s:SECONDS_OF_HOUR
endfunction
function! s:TimeDelta.days() abort
return self._days
endfunction
function! s:TimeDelta.weeks() abort
return self._days / s:NUM_DAYS_OF_WEEK
endfunction
function! s:TimeDelta.months() abort
return self._days / 30
endfunction
function! s:TimeDelta.years() abort
return self._days / 365
endfunction
function! s:TimeDelta.total_seconds() abort
return self._days * s:SECONDS_OF_DAY + self._seconds
endfunction
function! s:TimeDelta.is(td) abort
return self.subtract(a:td).sign() == 0
endfunction
function! s:TimeDelta.sign() abort
if self._days < 0 || self._seconds < 0
return -1
elseif 0 < self._days || 0 < self._seconds
return 1
endif
return 0
endfunction
function! s:TimeDelta.negate() abort
let td = self._clone()
let td._days = -self._days
let td._seconds = -self._seconds
return td._normalize()
endfunction
function! s:TimeDelta.duration() abort
return self.sign() < 0 ? self.negate() : self
endfunction
function! s:TimeDelta.add(...) abort
let n = self._clone()
let other = call('s:delta', a:000)
let n._days += other._days
let n._seconds += other._seconds
return n._normalize()
endfunction
function! s:TimeDelta.subtract(...) abort
let other = call('s:delta', a:000)
return self.add(other.negate())
endfunction
function! s:TimeDelta.about() abort
if self.sign() == 0
return 'now'
endif
let dir = self.sign() < 0 ? 'ago' : 'later'
let d = self.duration()
if d._days == 0
if d._seconds < s:NUM_SECONDS
let val = d.seconds()
let unit = val == 1 ? 'second' : 'seconds'
elseif d._seconds < s:SECONDS_OF_HOUR
let val = d.minutes()
let unit = val == 1 ? 'minute' : 'minutes'
else
let val = d.hours()
let unit = val == 1 ? 'hour' : 'hours'
endif
else
if d._days < s:NUM_DAYS_OF_WEEK
let val = d.days()
let unit = val == 1 ? 'day' : 'days'
elseif d._days < 30
let val = d.weeks()
let unit = val == 1 ? 'week' : 'weeks'
elseif d._days < 365
let val = d.months()
let unit = val == 1 ? 'month' : 'months'
else
let val = d.years()
let unit = val == 1 ? 'year' : 'years'
endif
endif
return printf('%d %s %s', val, unit, dir)
endfunction
function! s:TimeDelta.to_string() abort
let str = self.sign() < 0 ? '-' : ''
let d = self.duration()
if d._days != 0
let str .= d._days . (d._days == 1 ? 'day' : 'days') . ', '
endif
let str .= printf('%02d:%02d:%02d', d.hours(), d.minutes(), d.seconds())
return str
endfunction
function! s:TimeDelta._normalize() abort
let over_days = self._seconds / s:SECONDS_OF_DAY
let self._days += over_days
let self._seconds = self._seconds % s:SECONDS_OF_DAY
if self._days < 0 && 0 < self._seconds
let self._days += 1
let self._seconds -= s:SECONDS_OF_DAY
elseif 0 < self._days && self._seconds < 0
let self._days -= 1
let self._seconds += s:SECONDS_OF_DAY
endif
return self
endfunction
" ----------------------------------------------------------------------------
" Converts Gregorian Calendar to Julian day
function! s:_g2jd(year, month, day) abort
let [next, month] = s:_divmod(a:month - 1, s:NUM_MONTHS)
let year = a:year + next + 4800 - (month <= 1)
let month += month <= 1 ? 10 : -2
return a:day + (153 * month + 2) / 5 + s:_div(1461 * year, 4) - 32045
\ - s:_div(year, 100) + s:_div(year, 400)
endfunction
" Converts Julian day to Gregorian Calendar
function! s:_jd2g(jd) abort
let t = a:jd + 68569
let n = s:_div(4 * t, 146097)
let t -= s:_div(146097 * n + 3, 4) - 1
let i = (4000 * t) / 1461001
let t += -(1461 * i) / 4 + 30
let j = (80 * t) / 2447
let x = j / 11
let day = t - (2447 * j) / 80
let month = j + 2 - (12 * x)
let year = 100 * (n - 49) + i + x
return [year, month, day]
endfunction
function! s:_names(dates, format, locale) abort
return s:_with_locale('map(copy(a:1), "strftime(a:2, v:val)")',
\ a:locale, copy(a:dates), a:format)
endfunction
function! s:_with_locale(expr, locale, ...) abort
let current_locale = ''
if a:locale !=# ''
let current_locale = v:lc_time
execute 'language time' a:locale
endif
try
return eval(a:expr)
finally
if a:locale !=# ''
execute 'language time' current_locale
endif
endtry
endfunction
function! s:_div(n, d) abort
return s:_divmod(a:n, a:d)[0]
endfunction
function! s:_mod(n, d) abort
return s:_divmod(a:n, a:d)[1]
endfunction
function! s:_divmod(n, d) abort
let [q, mod] = [a:n / a:d, a:n % a:d]
return mod != 0 && (a:d < 0) != (mod < 0) ? [q - 1, mod + a:d] : [q, mod]
endfunction
" ----------------------------------------------------------------------------
function! s:_month_abbr(locale) abort
return s:month_names(0, a:locale)
endfunction
function! s:_month_full(locale) abort
return s:month_names(1, a:locale)
endfunction
function! s:_weekday_abbr(locale) abort
return s:weekday_names(0, a:locale)
endfunction
function! s:_weekday_full(locale) abort
return s:weekday_names(1, a:locale)
endfunction
function! s:_am_pm_lower(locale) abort
return s:am_pm_names(1, a:locale)
endfunction
function! s:_am_pm_upper(locale) abort
return s:am_pm_names(0, a:locale)
endfunction
" key = descriptor
" value = string (format alias)
" value = [field, captor, format_conv, parse_conv]
" at format:
" field = function name of source.
" captor = [flat, width] for number format.
" format_conv = expr for convert. some variables are available.
" parse_conv = unused.
" at parse:
" field = param name (with "_")
" if it doesn't exist, the descriptor can't use.
" field = #skip
" in this case, captor is a skipping pattern
" captor = pattern to match.
" captor = [flat, width] for number format.
" captor = a function to return a pattern or candidates.
" format_conv = unused.
" parse_conv = expr for convert. some variables are available.
let s:format_info = {
\ '%': ['', '%', '%'],
\ 'a': ['day_of_week', function('s:_weekday_abbr'),
\ 's:_weekday_abbr(locale)[value]'],
\ 'A': ['day_of_week', function('s:_weekday_full'),
\ 's:_weekday_full(locale)[value]'],
\ 'b': ['month', function('s:_month_abbr'),
\ 's:_month_abbr(locale)[value - 1]', 'value + 1'],
\ 'B': ['month', function('s:_month_full'),
\ 's:_month_full(locale)[value - 1]', 'value + 1'],
\ 'c': '%F %T %z',
\ 'C': ['year', ['0', 2], '(value + 99) / 100', 'o[key] % 100 + value * 100'],
\ 'd': ['day', ['0', 2]],
\ 'D': '%m/%d/%y',
\ 'e': '%_m/%_d/%_y',
\ 'F': '%Y-%m-%d',
\ 'h': '%b',
\ 'H': ['hour', ['0', 2]],
\ 'I': ['hour', ['0', 2], 's:_mod(value - 1, 12) + 1', 'value % 12'],
\ 'j': ['day_of_year', ['0', 3]],
\ 'k': '%_H',
\ 'l': '%_I',
\ 'm': ['month', ['0', 2]],
\ 'M': ['minute', ['0', 2]],
\ 'n': ['', '\_s*', "\n"],
\ 'p': ['hour', function('s:_am_pm_upper'),
\ 's:_am_pm_upper(locale)[value / 12]', 'o[key] + value * 12'],
\ 'P': ['hour', function('s:_am_pm_lower'),
\ 's:_am_pm_lower(locale)[value / 12]', 'o[key] + value * 12'],
\ 'r': '%I:%M:%S %p',
\ 'R': '%H:%M',
\ 's': ['unix_time', ['', '']],
\ 'S': ['second', ['0', 2]],
\ 't': ['', '\_.*', "\t"],
\ 'u': ['day_of_week', ['0', 1], 'value == 0 ? 7 : value'],
\ 'U': 'TODO',
\ 'T': '%H:%M:%S',
\ 'w': ['day_of_week', ['0', 1]],
\ 'y': ['year', ['0', 2], 'value % 100',
\ '(o[key] != 0 ? o[key] : (value < 69 ? 2000 : 1900)) + value'],
\ 'Y': ['year', ['0', 4]],
\ 'z': ['timezone', '\v[+-]?%(\d{1,2})?:?%(\d{1,2})?', 'value.offset_string()',
\ 's:timezone(empty(value) ? 0 : value)'],
\ '*': ['#skip', '.\{-}', ''],
\ }
let s:DESCRIPTORS_PATTERN = '[' . join(keys(s:format_info), '') . ']'
" 'foo%Ybar%02m' => ['foo', ['Y', '', -1], 'bar', ['m', '0', 2], '']
function! s:_split_format(format) abort
let res = []
let pat = '\C%\([-_0^#]\?\)\(\d*\)\(' . s:DESCRIPTORS_PATTERN . '\)'
let format = a:format
while format !=# ''
let i = match(format, pat)
if i < 0
let res += [format]
break
endif
if i != 0
let res += [format[: i - 1]]
let format = format[i :]
endif
let [matched, flag, width, d] = matchlist(format, pat)[: 3]
let format = format[len(matched) :]
let info = s:format_info[d]
if s:Prelude.is_string(info)
let format = info . format
else
let res += [[info, flag, width]]
endif
unlet info
endwhile
return res
endfunction
if has('win32') " This means any versions of windows https://github.com/vim-jp/vital.vim/wiki/Coding-Rule#how-to-check-if-the-runtime-os-is-windows
function! s:_default_tz() abort
let hm = map(split(strftime('%H %M', 0), ' '), 'str2nr(v:val)')
if str2nr(strftime('%Y', 0)) != 1970
let tz_sec = s:SECONDS_OF_DAY - hm[0] * s:SECONDS_OF_HOUR - hm[1] * s:NUM_SECONDS
return printf('-%02d%02d', tz_sec / s:SECONDS_OF_HOUR, (tz_sec / s:NUM_SECONDS) % s:NUM_MINUTES)
endif
return printf('+%02d%02d', hm[0], hm[1])
endfunction
else
function! s:_default_tz() abort
return strftime('%z')
endfunction
endif
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0: