summaryrefslogtreecommitdiff
path: root/tex/context/base/core-con.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/core-con.lua')
-rw-r--r--tex/context/base/core-con.lua605
1 files changed, 605 insertions, 0 deletions
diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua
new file mode 100644
index 000000000..dca1c7d10
--- /dev/null
+++ b/tex/context/base/core-con.lua
@@ -0,0 +1,605 @@
+if not modules then modules = { } end modules ['core-con'] = {
+ version = 1.001,
+ comment = "companion to core-con.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>This module implements a bunch of conversions. Some are more
+efficient than their <l n='tex'/> counterpart, some are even
+slower but look nicer this way.</p>
+
+<p>Some code may move to a module in the language namespace.</p>
+--ldx]]--
+
+local utf = unicode.utf8
+
+local floor, date, time, concat = math.floor, os.date, os.time, table.concat
+local lower, format, rep = string.lower, string.format, string.rep
+local texsprint, utfchar = tex.sprint, utf.char
+local tonumber, tostring = tonumber, tostring
+
+local ctxcatcodes = tex.ctxcatcodes
+
+converters = converters or { }
+languages = languages or { }
+
+--~ ['arabic-digits'] = {
+--~ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664,
+--~ 0x0665, 0x0666, 0x0667, 0x0668, 0x0669
+--~ },
+--~ ['persian-digits'] = {
+--~ 0x06F0, 0x06F1, 0x06F2, 0x06F3, 0x06F4,
+--~ 0x06F5, 0x06F6, 0x06F7, 0x06F8, 0x06F9
+--~ },
+
+languages.counters = {
+ ['**'] = {
+ 0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
+ 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
+ 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
+ 0x0075, 0x0076, 0x0077, 0x0078, 0x0079,
+ 0x007A
+ },
+ ['slovenian'] = {
+ 0x0061, 0x0062, 0x0063, 0x010D, 0x0064,
+ 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006A, 0x006B, 0x006C, 0x006D, 0x006E,
+ 0x006F, 0x0070, 0x0072, 0x0073, 0x0161,
+ 0x0074, 0x0075, 0x0076, 0x007A, 0x017E
+ },
+ ['greek'] = { -- this should be the lowercase table
+ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
+ 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
+ 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
+ 0x03A6, 0x03A7, 0x03A8, 0x03A9
+ },
+ ['arabic'] = {
+ 0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
+ 0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
+ 0x0643, 0x0644, 0x0645, 0x0646, 0x0633,
+ 0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
+ 0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
+ 0x0636, 0x0638, 0x063A,
+ },
+ ['persian'] = {
+ 0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
+ 0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
+ 0x06A9, 0x0644, 0x0645, 0x0646, 0x0633,
+ 0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
+ 0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
+ 0x0636, 0x0638, 0x063A,
+ },
+ ['thai'] = {
+ 0xE050, 0xE051, 0xE052, 0xE053, 0xE054,
+ 0xE055, 0xE056, 0xE057, 0xE058, 0xE059
+ },
+ ['devangari'] = {
+ 0x0966, 0x0967, 0x0968, 0x0969, 0x096A,
+ 0x096B, 0x096C, 0x096D, 0x096E, 0x096F
+ },
+ ['gurmurkhi'] = {
+ 0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A,
+ 0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F
+ },
+ ['gujarati'] = {
+ 0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA,
+ 0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF
+ },
+ ['tibetan'] = {
+ 0x0F20, 0x0F21, 0x0F22, 0x0F23, 0x0F24,
+ 0x0F25, 0x0F26, 0x0F27, 0x0F28, 0x0F29
+ },
+ ['korean'] = {
+ 0x3131, 0x3134, 0x3137, 0x3139, 0x3141,
+ 0x3142, 0x3145, 0x3147, 0x3148, 0x314A,
+ 0x314B, 0x314C, 0x314D, 0x314E
+ },
+ ['korean-parent'] = { -- parenthesed
+ 0x3200, 0x3201, 0x3202, 0x3203, 0x3204,
+ 0x3205, 0x3206, 0x3207, 0x3208, 0x3209,
+ 0x320A, 0x320B, 0x320C, 0x320D
+ },
+ ['korean-circle'] = { -- circled
+ 0x3260, 0x3261, 0x3262, 0x3263, 0x3264,
+ 0x3265, 0x3266, 0x3267, 0x3268, 0x3269,
+ 0x326A, 0x326B, 0x326C, 0x326D
+ },
+}
+
+local counters = languages.counters
+
+counters['ar'] = counters['arabic']
+counters['gr'] = counters['greek']
+counters['g'] = counters['greek']
+counters['sl'] = counters['slovenian']
+counters['kr'] = counters['korean']
+counters['kr-p'] = counters['korean-parent']
+counters['kr-c'] = counters['korean-circle']
+
+local fallback = utf.byte('0')
+
+local function chr(n,m)
+ if n > 0 and n < 27 then
+ texsprint(utfchar(n+m))
+ end
+end
+local function chrs(n,m)
+ if n > 26 then
+ chrs(floor((n-1)/26),m)
+ n = (n-1)%26 + 1
+ end
+ texsprint(utfchar(n+m))
+end
+local function maxchrs(n,m,cmd)
+ if n > m then
+ maxchrs(floor((n-1)/m),m,cmd)
+ n = (n-1)%m + 1
+ end
+ texsprint(ctxcatcodes, format("%s{%s}",cmd,n))
+end
+
+converters.chr = chr
+converters.chrs = chrs
+converters.maxchrs = maxchrs
+
+--~ more efficient but needs testing
+--~
+--~ local escapes = utffilters.private.escapes
+--~
+--~ local function do_alphabetic(n,mapping,chr)
+--~ local max = #mapping
+--~ if n > max then
+--~ do_alphabetic(floor((n-1)/max),max,chr)
+--~ n = (n-1)%max+1
+--~ end
+--~ n = chr(n,mapping)
+--~ texsprint(ctxcatcodes,escapes[n] or utfchar(n))
+--~ end
+
+--~ local lccodes, uccodes = characters.lccode, characters.uccode
+
+--~ local function do_alphabetic(n,mapping,chr)
+--~ local max = #mapping
+--~ if n > max then
+--~ do_alphabetic(floor((n-1)/max),mapping,chr)
+--~ n = (n-1)%max+1
+--~ end
+--~ characters.flush(chr(n,mapping))
+--~ end
+--~
+--~ local function lowercased(n,mapping) return characters.lccode(mapping[n] or fallback) end
+--~ local function uppercased(n,mapping) return characters.uccode(mapping[n] or fallback) end
+--~
+--~ function converters.alphabetic(n,code)
+--~ do_alphabetic(n,counters[code] or counters['**'],lowercased) -- lccode catches wrong tables
+--~ end
+--~
+--~ function converters.Alphabetic(n,code)
+--~ do_alphabetic(n,counters[code] or counters['**'],uppercased)
+--~ end
+
+--
+
+local function do_alphabetic(n,mapping,mapper)
+ local chr = mapper(mapping[n] or fallback)
+ local max = #mapping
+ if n > max then
+ do_alphabetic(floor((n-1)/max),mapping,mapper)
+ n = (n-1)%max+1
+ end
+ characters.flush(chr)
+end
+
+function converters.alphabetic(n,code)
+ do_alphabetic(n,counters[code] or counters['**'],characters.lccode)
+end
+
+function converters.Alphabetic(n,code)
+ do_alphabetic(n,counters[code] or counters['**'],characters.uccode)
+end
+
+--
+
+function converters.character (n) chr (n,96) end
+function converters.Character (n) chr (n,64) end
+function converters.characters(n) chrs(n,96) end
+function converters.Characters(n) chrs(n,64) end
+
+function converters.weekday(day,month,year)
+ texsprint(date("%w",time{year=year,month=month,day=day})+1)
+end
+
+function converters.isleapyear(year)
+ return (year % 400 == 0) or ((year % 100 ~= 0) and (year % 4 == 0))
+end
+
+function converters.leapyear(year)
+ if converters.isleapyear(year) then texsprint(1) else texsprint(0) end
+end
+
+local days = {
+ [false] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ [true] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+}
+
+function converters.nofdays(year,month)
+ texsprint(days[converters.isleapyear(year)][month])
+end
+
+function converters.year () texsprint(date("%Y")) end
+function converters.month () texsprint(date("%m")) end
+function converters.hour () texsprint(date("%H")) end
+function converters.minute () texsprint(date("%M")) end
+function converters.second () texsprint(date("%S")) end
+function converters.textime() texsprint(tonumber(date("%H"))*60+tonumber(date("%M"))) end
+
+local roman = {
+ { [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' },
+ { [0] = '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC' },
+ { [0] = '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM' },
+}
+
+local function toroman(n)
+ if n >= 4000 then
+ return toroman(floor(n/1000)) .. " " .. toroman(n%1000)
+ else
+ return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] ..
+ roman[2][floor((n%100)/10)] .. roman[1][floor((n% 10)/1)]
+ end
+end
+
+function converters.romannumerals(n) return texsprint(lower(toroman(n))) end
+function converters.Romannumerals(n) return texsprint( toroman(n) ) end
+
+converters.toroman = toroman
+
+--~ local small = {
+--~ 0x0627, 0x066E, 0x062D, 0x062F, 0x0647, 0x0648, 0x0631
+--~ }
+
+--~ local large = {
+--~ { 0x0627, 0x0628, 0x062C, 0x062F, 0x0647, 0x0648, 0x0632, 0x062D, 0x0637, },
+--~ { 0x064A, 0x0643, 0x0644, 0x0645, 0x0646, 0x0633, 0x0639, 0x0641, 0x0635, },
+--~ { 0x0642, 0x0631, 0x0634, 0x062A, 0x062B, 0x062E, 0x0630, 0x0636, 0x0638, },
+--~ { 0x063A },
+--~ }
+
+local small = {
+ "ا", "ٮ", "ح", "د", "ه", "و", "ر",
+}
+
+local medium = {
+ "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" ,
+ "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" ,
+ "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" ,
+ "غ" ,
+}
+
+local large = {
+ { "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" },
+ { "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" },
+ { "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" },
+ { "غ" },
+}
+
+function converters.toabjad(n,what)
+ if n <= 0 or n >= 2000 then
+ return tostring(n)
+ elseif what == 2 and n <= 7 then
+ return small[n]
+ elseif what == 3 and n <= 28 then
+ return medium[n]
+ else
+ local a, b, c, d
+ a, n = floor(n/1000), n % 1000 -- mod(n,1000)
+ b, n = floor(n/ 100), n % 100 -- mod(n, 100)
+ c, n = floor(n/ 10), n % 10 -- mod(n, 10)
+ d, n = floor(n/ 1), n % 1 -- mod(n, 1)
+ return (large[4][a] or "") .. (large[3][b] or "") .. (large[2][c] or "") .. (large[1][d] or "")
+ end
+end
+
+function converters.abjadnumerals (n) return texsprint(converters.toabjad(n,false)) end
+function converters.abjadnodotnumerals(n) return texsprint(converters.toabjad(n,true)) end
+
+local vector = {
+ normal = {
+ [0] = "〇",
+ [1] = "一",
+ [2] = "二",
+ [3] = "三",
+ [4] = "四",
+ [5] = "五",
+ [6] = "六",
+ [7] = "七",
+ [8] = "八",
+ [9] = "九",
+ [10] = "十",
+ [100] = "百",
+ [1000] = "千",
+ [10000] = "万",
+ [100000000] = "亿",
+ },
+ cap = {
+ [0] = "零",
+ [1] = "壹",
+ [2] = "贰",
+ [3] = "叁",
+ [4] = "肆",
+ [5] = "伍",
+ [6] = "陆",
+ [7] = "柒",
+ [8] = "捌",
+ [9] = "玖",
+ [10] = "拾",
+ [100] = "佰",
+ [1000] = "仟",
+ [10000] = "萬",
+ [100000000] = "亿",
+ },
+ all = {
+ [0] = "〇",
+ [1] = "一",
+ [2] = "二",
+ [3] = "三",
+ [4] = "四",
+ [5] = "五",
+ [6] = "六",
+ [7] = "七",
+ [8] = "八",
+ [9] = "九",
+ [10] = "十",
+ [20] = "廿",
+ [30] = "卅",
+ [100] = "百",
+ [1000] = "千",
+ [10000] = "万",
+ [100000000] = "亿",
+ }
+}
+
+--~ function tochinese(n,name) -- normal, caps, all
+--~ local result = { }
+--~ local vector = vector[name] or vector.normal
+--~ while true do
+--~ if n == 0 then
+--~ break
+--~ elseif n >= 100000000 then
+--~ local m = floor(n/100000000)
+--~ if m > 1 then result[#result+1] = tochinese(m) end
+--~ result[#result+1] = vector[100000000]
+--~ n = n % 100000000
+--~ elseif n >= 10000000 then
+--~ result[#result+1] = tochinese(floor(n/10000))
+--~ result[#result+1] = vector[10000]
+--~ n = n % 10000
+--~ elseif n >= 1000000 then
+--~ result[#result+1] = tochinese(floor(n/10000))
+--~ result[#result+1] = vector[10000]
+--~ n = n % 10000
+--~ elseif n >= 100000 then
+--~ result[#result+1] = tochinese(floor(n/10000))
+--~ result[#result+1] = vector[10000]
+--~ n = n % 10000
+--~ elseif n >= 10000 then
+--~ local m = floor(n/10000)
+--~ if m > 1 then result[#result+1] = vector[m] end
+--~ result[#result+1] = vector[10000]
+--~ n = n % 10000
+--~ elseif n >= 1000 then
+--~ local m = floor(n/1000)
+--~ if m > 1 then result[#result+1] = vector[m] end
+--~ result[#result+1] = vector[1000]
+--~ n = n % 1000
+--~ elseif n >= 100 then
+--~ local m = floor(n/100)
+--~ if m > 1 then result[#result+1] = vector[m] end
+--~ result[#result+1] = vector[100]
+--~ n = n % 100
+--~ elseif n >= 10 then
+--~ local m = floor(n/10)
+--~ if vector[m*10] then
+--~ result[#result+1] = vector[m*10]
+--~ else
+--~ result[#result+1] = vector[m]
+--~ result[#result+1] = vector[10]
+--~ end
+--~ n = n % 10
+--~ else
+--~ result[#result+1] = vector[n]
+--~ break
+--~ end
+--~ end
+--~ return concat(result)
+--~ end
+
+function tochinese(n,name) -- normal, caps, all
+ -- improved version by Li Yanrui
+ local result = { }
+ local vector = vector[name] or vector.normal
+ while true do
+ if n == 0 then
+ break
+ elseif n >= 100000000 then
+ local m = floor(n/100000000)
+ result[#result+1] = tochinese(m,name)
+ result[#result+1] = vector[100000000]
+ local z = n - m * 100000000
+ if z > 0 and z < 10000000 then result[#result+1] = vector[0] end
+ n = n % 100000000
+ elseif n >= 10000000 then
+ local m = floor(n/10000)
+ result[#result+1] = tochinese(m,name)
+ result[#result+1] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ n = n % 10000
+ elseif n >= 1000000 then
+ local m = floor(n/10000)
+ result[#result+1] = tochinese(m,name)
+ result[#result+1] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ n = n % 10000
+ elseif n >= 100000 then
+ local m = floor(n/10000)
+ result[#result+1] = tochinese(m,name)
+ result[#result+1] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ n = n % 10000
+ elseif n >= 10000 then
+ local m = floor(n/10000)
+ result[#result+1] = vector[m]
+ result[#result+1] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ n = n % 10000
+ elseif n >= 1000 then
+ local m = floor(n/1000)
+ result[#result+1] = vector[m]
+ result[#result+1] = vector[1000]
+ local z = n - m * 1000
+ if z > 0 and z < 100 then result[#result+1] = vector[0] end
+ n = n % 1000
+ elseif n >= 100 then
+ local m = floor(n/100)
+ result[#result+1] = vector[m]
+ result[#result+1] = vector[100]
+ local z = n - m * 100
+ if z > 0 and z < 10 then result[#result+1] = vector[0] end
+ n = n % 100
+ elseif n >= 10 then
+ local m = floor(n/10)
+ if m > 1 and vector[m*10] then
+ result[#result+1] = vector[m*10]
+ else
+ result[#result+1] = vector[m]
+ result[#result+1] = vector[10]
+ end
+ n = n % 10
+ else
+ result[#result+1] = vector[n]
+ break
+ end
+ end
+ if (result[1] == vector[1] and result[2] == vector[10]) then
+ result[1] = ""
+ end
+ return concat(result)
+end
+
+--~ local t = { 1,10,15,25,35,45,11,100,111,1111,10000,11111,100000,111111,1111111,11111111,111111111,100000000,1111111111,11111111111,111111111111,1111111111111 }
+--~ for k=1,#t do
+--~ local v = t[k]
+--~ print(v,tochinese(v),tochinese(v,"all"),tochinese(v,"cap"))
+--~ end
+
+function converters.chinesenumerals (n) return texsprint(tochinese(n,"normal")) end
+function converters.chinesecapnumerals(n) return texsprint(tochinese(n,"cap" )) end
+function converters.chineseallnumerals(n) return texsprint(tochinese(n,"all" )) end
+
+--~ Well, since the one asking for this didn't test it the following code is not
+--~ enabled.
+--~
+--~ -- This Lua version is based on a Javascript by Behdad Esfahbod which in turn
+--~ -- is based on GPL'd code by Roozbeh Pournader of the The FarsiWeb Project
+--~ -- Group: http://www.farsiweb.info/jalali/jalali.js.
+--~ --
+--~ -- We start tables at one, I kept it zero based in order to stay close to
+--~ -- the original.
+--~ --
+--~ -- Conversion by Hans Hagen
+--~
+--~ local g_days_in_month = { [0]=31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+--~ local j_days_in_month = { [0]=31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 }
+--~
+--~ local function div(a,b)
+--~ return math.floor(a/b)
+--~ end
+--~
+--~ local function remainder(a,b)
+--~ return a - div(a,b)*b
+--~ end
+--~
+--~ function gregorian_to_jalali(gy,gm,gd)
+--~ local jy, jm, jd, g_day_no, j_day_no, j_np, i
+--~ gy, gm, gd = gy - 1600, gm - 1, gd - 1
+--~ g_day_no = 365*gy + div((gy+3),4) - div((gy+99),100) + div((gy+399),400)
+--~ i = 0
+--~ while i < gm do
+--~ g_day_no = g_day_no + g_days_in_month[i]
+--~ i = i + 1
+--~ end
+--~ if (gm>1 and ((gy%4==0 and gy%100~=0) or (gy%400==0))) then
+--~ g_day_no = g_day_no + 1
+--~ end
+--~ g_day_no = g_day_no + gd
+--~ j_day_no = g_day_no - 79
+--~ j_np = div(j_day_no,12053)
+--~ j_day_no = remainder(j_day_no,12053)
+--~ jy = 979 + 33*j_np + 4*div(j_day_no,1461)
+--~ j_day_no = remainder(j_day_no,1461)
+--~ if j_day_no >= 366 then
+--~ jy = jy + div((j_day_no-1),365)
+--~ j_day_no = remainder((j_day_no-1),365)
+--~ end
+--~ i = 0
+--~ while i < 11 and j_day_no >= j_days_in_month[i] do
+--~ j_day_no = j_day_no - j_days_in_month[i]
+--~ i = i + 1
+--~ end
+--~ jm = i + 1
+--~ jd = j_day_no + 1
+--~ return jy, jm, jd
+--~ end
+--~
+--~ function jalali_to_gregorian(jy,jm,jd)
+--~ local gy, gm, gd, g_day_no, j_day_no, leap, i
+--~ jy, jm, jd = jy - 979, jm - 1, jd - 1
+--~ j_day_no = 365*jy + div(jy,33)*8 + div((remainder(jy,33)+3),4)
+--~ i = 0
+--~ while i < jm do
+--~ j_day_no = j_day_no + j_days_in_month[i]
+--~ i = i + 1
+--~ end
+--~ j_day_no = j_day_no + jd
+--~ g_day_no = j_day_no + 79
+--~ gy = 1600 + 400*div(g_day_no,146097)
+--~ g_day_no = remainder (g_day_no, 146097)
+--~ leap = 1
+--~ if g_day_no >= 36525 then
+--~ g_day_no = g_day_no - 1
+--~ gy = gy + 100*div(g_day_no,36524)
+--~ g_day_no = remainder (g_day_no, 36524)
+--~ if g_day_no >= 365 then
+--~ g_day_no = g_day_no + 1
+--~ else
+--~ leap = 0
+--~ end
+--~ end
+--~ gy = gy + 4*div(g_day_no,1461)
+--~ g_day_no = remainder (g_day_no, 1461)
+--~ if g_day_no >= 366 then
+--~ leap = 0
+--~ g_day_no = g_day_no - 1
+--~ gy = gy + div(g_day_no, 365)
+--~ g_day_no = remainder(g_day_no, 365)
+--~ end
+--~ i = 0
+--~ while g_day_no >= g_days_in_month[i] + ((i == 1 and leap) or 0) do
+--~ g_day_no = g_day_no - g_days_in_month[i] + ((i == 1 and leap) or 0)
+--~ i = i + 1
+--~ end
+--~ gm = i + 1
+--~ gd = g_day_no + 1
+--~ return gy, gm, gd
+--~ end
+--~
+--~ print(gregorian_to_jalali(2009,02,24))
+--~ print(jalali_to_gregorian(1387,12,06))