" Calendar functions
" Author: Patrick Texier
" Url:
" Last modified: 2010 May 22
" Version: 0.3
" Vim Version: Vim 7.2
" Change Log {{{1
" 2008 Jul 01
" - Negative years handling
" Init {{{1
if exists('g:loaded_datecalc')
"finish
endif
scriptencoding latin1
let g:loaded_datecalc = 1
if !has("float")
echo "Vim must be compiled with +float feature"
finish
endif
let s:save_cpo = &cpo
set cpo&vim
let s:use_lang = 'fr'
if !exists("s:use_lang")
if strpart(v:lang, 0, 2) == 'fr'
let s:use_lang = 'fr'
else
let s:use_lang = 'en'
endif
endif
" Script variables {{{1
let s:LastJulien = 1582.1014
let s:LostDay = 2299161
if s:use_lang == 'en'
let s:ListDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
let s:ListMonth = ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
let s:BeforeChrist = " B.C."
else
let s:ListDays = ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"]
let s:ListMonth = ["", "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"]
let s:BeforeChrist = " avant J.C"
endif
let s:ListFrDays = ["décadi", "primedi", "duodi", "tridi", "quartidi", "quintidi", "sextidi", "septidi", "octidi", "nonidi"]
let s:FrMonth = ["VEND", "BRUM", "FRIM", "NIVO", "PLUV", "VENT", "GERM", "FLOR","PRAI", "MESS", "THER", "FRUC", "COMP"]
let s:FrLongMonth = {"VEND": "vendémiaire", "BRUM": "brumaire", "FRIM": "frimaire", "NIVO": "nivôse", "PLUV": "pluviôse", "VENT": "ventôse", "GERM": "germinal", "FLOR": "floréal", "PRAI": "prairial", "MESS": "messidor", "THER": "thermidor", "FRUC": "fructidor", "COMP": "jour complémentaire"}
let s:FrYear = {"01": "I", "02": "II", "03": "III", "04": "IV", "05": "V", "06": "VI", "07": "VII", "08": "VIII", "09": "IX", "10": "X", "11": "XI", "12": "XII", "13": "XIII", "14": "XIV", "15": "XV" }
let s:FrYearLen = [365, 365, 366, 365, 365, 365, 366, 365, 365, 365, 366, 365, 365, 365, 100]
let s:FirstFr = 2375839.5
let s:LastFr = 2381051.5
" Functions {{{1
" AddDays(date DD/MM/YYYY, days) -> date {{{2
function! AddDays(date, days)
let l:result = Jd2date(Date2jd(a:date) + a:days)
return l:result
endfunction
" Date2fr (date DD/MM/YYYY) -> French republican date DD/MMMM/YY {{{2
function! Date2fr(date)
let l:jd = Date2jd(a:date)
if l:jd < s:FirstFr || l:jd > s:LastFr
return a:date
endif
let l:jd2 = s:FirstFr
let l:ar = 0
while l:jd2 + s:FrYearLen[l:ar] <= l:jd
let l:jd2 += s:FrYearLen[l:ar]
let l:ar += 1
endwhile
" l:jd and l:jd2 are floats but reste is integer
let l:reste = str2nr(printf("%3.0f", l:jd - l:jd2))
let l:mr = l:reste / 30
let l:jr = l:reste % 30 + 1
let l:ar += 1
let l:result = printf("%02d", l:jr) . "/" . s:FrMonth[l:mr] . "/" . printf("%02d", l:ar)
return l:result
endfunction
" Date2jd(date DD/MM/AAAA) -> julian day {{{2
function! Date2jd(date)
let l:jj = str2nr(strpart(a:date, 0, 2))
let l:mm = str2nr(strpart(a:date, 3, 2))
let l:aa = str2nr(strpart(a:date, 6, 5))
let l:m2 = l:mm
let l:a = l:aa
let l:jdd = 0.0
if (l:m2 < 3)
let l:a -= 1
let l:m2 += 12
endif
let l:jdd = floor(365.25 * l:a)
let l:jdd += floor(30.6001 * (l:m2 + 1)) + l:jj + 1720994.5
" gregorian calendar
if ((l:aa + l:mm/100.0 + l:jj/10000.0) > s:LastJulien)
let l:jdd = l:jdd + 2.0 - floor(l:a/100.0) + floor(l:a/400.0)
endif
return l:jdd
endfunction
" DayOfWeek(Date DD/MM/YYYY) -> day of week (string) {{{2
function! DayOfWeek(date)
let l:calc = Date2jd(a:date) + 1.5 - 7 * floor((Date2jd(a:date) + 1.5) / 7)
"return l:calc
let l:result = s:ListDays[float2nr(l:calc)]
return l:result
endfunction
" Days(date1 DD/MM/YYYY, date2 DD/MM/YYYY) -> numbers of days {{{2
function! Days(date1, date2)
let l:result = float2nr(Date2jd(a:date2) - Date2jd(a:date1))
return l:result
endfunction
" Easter(year AAAA) -> Easter date {{{2
function! Easter(year)
" Easter uses only integers
if a:year < 1582
let l:a = a:year % 4
let l:b = a:year % 7
let l:c = a:year % 19
let l:d = (19 * l:c + 15) % 30
let l:e = (2 * l:a + 4 * l:b - l:d + 34) % 7
let l:n = (l:d + l:e + 114) / 31
let l:p = ((l:d + l:e + 114) % 31) + 1
else
let l:a = a:year % 19
let l:b = a:year / 100
let l:c = a:year % 100
let l:d = l:b / 4
let l:e = l:b % 4
let l:f = (l:b + 8) / 25
let l:g = (l:b - l:f + 1) / 3
let l:h = (19 * l:a + l:b - l:d - l:g + 15) % 30
let l:i = l:c / 4
let l:k = l:c % 4
let l:r = (32 + 2 * l:e + 2 * l:i - l:h - l:k) % 7
let l:m = (l:a + 11 * l:h + 22 * l:r) / 451
let l:n = (l:h + l:r - 7 * l:m + 114) / 31
let l:p = ((l:h + l:r - 7 * l:m + 114) % 31) + 1
endif
let l:result = printf("%02d/%02d/%04d", l:p, l:n, a:year)
return l:result
endfunction
" Fr2date (date DD/MMMM/YY) -> Gregorian date DD/MM/YYYY {{{2
function! Fr2date(date)
let l:jd = s:FirstFr
let l:jj = str2nr(strpart(a:date, 0, 2))
let l:mm = strpart(a:date, 3, 4)
let l:aa = str2nr(strpart(a:date, 8, 2))
if l:jj < 1 || l:jj > 30
echo "Invalid day"
return ""
endif
if l:aa < 0 || l:aa > 15
echo "Invalid year"
return ""
endif
let l:ind = 0
while l:ind <= (l:aa - 2)
let l:jd = l:jd + s:FrYearLen[l:ind]
let l:ind += 1
endwhile
let l:ind = 0
while l:mm != s:FrMonth[l:ind] && l:ind < 12
let l:ind += 1
endwhile
if s:FrMonth[l:ind] != l:mm
echo "Invalid month"
return ""
endif
let l:jd += 30 * l:ind
let l:jd += l:jj - 1
let l:result = Jd2date(l:jd)
return l:result
endfunction
" Jd2date (julian day) julian day -> date DD/MM/AAAA {{{2
function! Jd2date(jd)
let l:a = 0.0
let l:z = floor(a:jd + 0.5)
let l:f = a:jd + 0.5 - l:z
" Gregorian calendar
if l:z >= s:LostDay
let l:ab = floor((l:z-1867216.25)/36524.25)
let l:a = l:z + 1.0 + l:ab - floor(l:ab / 4.0)
else
let l:a = l:z * 1.0
endif
let l:b = l:a + 1524.0
let l:c = floor((l:b - 122.1) / 365.25)
let l:d = floor(365.25 * l:c)
let l:e = floor((l:b - l:d) / 30.6001)
let l:jj = l:b - l:d - floor(30.6001 * l:e) + l:f
if (l:e <= 13.0)
let l:mm = l:e - 1.0
else
let l:mm = l:e - 13.0
endif
if (l:mm > 2.0)
let l:aa = l:c - 4716.0
else
let l:aa = l:c - 4715.0
endif
if l:aa >= 0
let l:result = printf("%02.0f/%02.0f/%04.0f", l:jj, l:mm, l:aa)
else
let l:result = printf("%02.0f/%02.0f/-%04.0f", l:jj, l:mm, abs(l:aa))
endif
return l:result
endfunction
" PrintDate (date DD/MM/YYYY or DD/MMMM/YY, day 0/1) -> Date {{{2
function! PrintDate(date, day)
let l:bc = ""
if a:date =~ "[A-Z]"
" French republican calendar
let l:dd = str2nr(strpart(a:date, 0, 2))
let l:mm = strpart(a:date, 3, 4)
let l:yy = strpart(a:date, 8, 2)
if a:day && l:mm != "COMP"
let l:day = s:ListFrDays[l:dd % 10] . " "
else
let l:day = ""
endif
let l:result = l:day . l:dd . " " . s:FrLongMonth[l:mm] . " an " . s:FrYear[l:yy]
else
" Gregorian calendar
let l:dd = str2nr(strpart(a:date, 0, 2))
let l:mm = str2nr(strpart(a:date, 3, 2))
let l:yy = strpart(a:date, 6, 5)
if a:day
let l:result = DayOfWeek(a:date) . " "
else
let l:result = ""
endif
let l:yy = str2nr(l:yy)
if l:yy <= 0
let l:yy = -l:yy + 1
let l:bc = s:BeforeChrist
endif
let l:result .= l:dd . " " . s:ListMonth[l:mm] . " " . l:yy . l:bc
endif
return l:result
endfunction
" PtTest(date) TODO {{{2
function! PtTest(date)
endfunction
" Reset {{{1
let &cpo = s:save_cpo
unlet s:save_cpo
" }}}1
" vim:fdm=marker