core-con.lua /size: 63 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
core-con
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to core-con.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
-- todo: split into lang-con.lua and core-con.lua
10 11
--[[ldx-- 12<p>This module implements a bunch of conversions. Some are more 13efficient than their <l n='tex'/> counterpart, some are even 14slower but look nicer this way.</p> 15 16<p>Some code may move to a module in the language namespace.</p> 17--ldx]]
--
18 19
local
floor
=
math
.
floor
20
local
osdate
,
ostime
=
os
.
date
,
os
.
time
21
local
concat
,
insert
,
reverse
=
table
.
concat
,
table
.
insert
,
table
.
reverse
22
local
lower
,
upper
,
rep
,
match
,
gsub
=
string
.
lower
,
string
.
upper
,
string
.
rep
,
string
.
match
,
string
.
gsub
23
local
utfchar
,
utfbyte
=
utf
.
char
,
utf
.
byte
24
local
tonumber
,
tostring
,
type
,
rawset
=
tonumber
,
tostring
,
type
,
rawset
25
local
P
,
S
,
R
,
Cc
,
Cf
,
Cg
,
Ct
,
Cs
,
C
,
V
,
Carg
=
lpeg
.
P
,
lpeg
.
S
,
lpeg
.
R
,
lpeg
.
Cc
,
lpeg
.
Cf
,
lpeg
.
Cg
,
lpeg
.
Ct
,
lpeg
.
Cs
,
lpeg
.
C
,
lpeg
.
V
,
lpeg
.
Carg
26
local
lpegmatch
,
lpegpatterns
=
lpeg
.
match
,
lpeg
.
patterns
27
local
div
,
mod
=
math
.
div
,
math
.
mod
28 29
local
context
=
context
30
local
commands
=
commands
31
local
implement
=
interfaces
.
implement
32 33
local
settings_to_array
=
utilities
.
parsers
.
settings_to_array
34
local
allocate
=
utilities
.
storage
.
allocate
35
local
setmetatableindex
=
table
.
setmetatableindex
36
local
formatters
=
string
.
formatters
37
local
variables
=
interfaces
.
variables
38
local
constants
=
interfaces
.
constants
39
local
addformatter
=
utilities
.
strings
.
formatters
.
add
40 41
local
texset
=
tex
.
set
42 43
converters
=
converters
or
{
}
44
local
converters
=
converters
45 46
languages
=
languages
or
{
}
47
local
languages
=
languages
48 49
local
helpers
=
converters
.
helpers
or
{
}
50
converters
.
helpers
=
helpers
51 52
local
ctx_labeltext
=
context
.
labeltext
53
local
ctx_LABELTEXT
=
context
.
LABELTEXT
54
local
ctx_space
=
context
.
space
55
local
ctx_convertnumber
=
context
.
convertnumber
56
local
ctx_highordinalstr
=
context
.
highordinalstr
57 58
converters
.
number
=
tonumber
59
converters
.
numbers
=
tonumber
60 61
implement
{
name
=
"
number
"
,
actions
=
context
}
62
implement
{
name
=
"
numbers
"
,
actions
=
context
}
63 64
-- to be reconsidered ... languages namespace here, might become local plus a register command
65 66
local
counters
=
allocate
{
67
[
'
default
'
]
=
{
-- no metatable as we do a test on keys
68
0x0061
,
0x0062
,
0x0063
,
0x0064
,
0x0065
,
69
0x0066
,
0x0067
,
0x0068
,
0x0069
,
0x006A
,
70
0x006B
,
0x006C
,
0x006D
,
0x006E
,
0x006F
,
71
0x0070
,
0x0071
,
0x0072
,
0x0073
,
0x0074
,
72
0x0075
,
0x0076
,
0x0077
,
0x0078
,
0x0079
,
73
0x007A
74
}
,
75
[
'
slovenian
'
]
=
{
76
0x0061
,
0x0062
,
0x0063
,
0x010D
,
0x0064
,
77
0x0065
,
0x0066
,
0x0067
,
0x0068
,
0x0069
,
78
0x006A
,
0x006B
,
0x006C
,
0x006D
,
0x006E
,
79
0x006F
,
0x0070
,
0x0072
,
0x0073
,
0x0161
,
80
0x0074
,
0x0075
,
0x0076
,
0x007A
,
0x017E
81
}
,
82
[
'
spanish
'
]
=
{
83
0x0061
,
0x0062
,
0x0063
,
0x0064
,
0x0065
,
84
0x0066
,
0x0067
,
0x0068
,
0x0069
,
0x006A
,
85
0x006B
,
0x006C
,
0x006D
,
0x006E
,
0x00F1
,
86
0x006F
,
0x0070
,
0x0071
,
0x0072
,
0x0073
,
87
0x0074
,
0x0075
,
0x0076
,
0x0077
,
0x0078
,
88
0x0079
,
0x007A
89
}
,
90
[
'
russian
'
]
=
{
91
0x0430
,
0x0431
,
0x0432
,
0x0433
,
0x0434
,
92
0x0435
,
0x0436
,
0x0437
,
0x0438
,
0x043a
,
93
0x043b
,
0x043c
,
0x043d
,
0x043e
,
0x043f
,
94
0x0440
,
0x0441
,
0x0442
,
0x0443
,
0x0444
,
95
0x0445
,
0x0446
,
0x0447
,
0x0448
,
0x0449
,
96
0x044d
,
0x044e
,
0x044f
97
}
,
98
[
'
greek
'
]
=
{
-- this should be the lowercase table
99
-- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
100
-- 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
101
-- 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
102
-- 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
103
-- 0x03A6, 0x03A7, 0x03A8, 0x03A9
104
0x03B1
,
0x03B2
,
0x03B3
,
0x03B4
,
0x03B5
,
105
0x03B6
,
0x03B7
,
0x03B8
,
0x03B9
,
0x03BA
,
106
0x03BB
,
0x03BC
,
0x03BD
,
0x03BE
,
0x03BF
,
107
0x03C0
,
0x03C1
,
0x03C3
,
0x03C4
,
0x03C5
,
108
0x03C6
,
0x03C7
,
0x03C8
,
0x03C9
,
109
}
,
110
[
'
arabic
'
]
=
{
111
0x0627
,
0x0628
,
0x062C
,
0x062F
,
0x0647
,
112
0x0648
,
0x0632
,
0x062D
,
0x0637
,
0x0649
,
113
0x0643
,
0x0644
,
0x0645
,
0x0646
,
0x0633
,
114
0x0639
,
0x0641
,
0x0635
,
0x0642
,
0x0631
,
115
0x0634
,
0x062A
,
0x062B
,
0x062E
,
0x0630
,
116
0x0636
,
0x0638
,
0x063A
,
117
}
,
118
[
'
persian
'
]
=
{
119
0x0627
,
0x0628
,
0x062C
,
0x062F
,
0x0647
,
120
0x0648
,
0x0632
,
0x062D
,
0x0637
,
0x0649
,
121
0x06A9
,
0x0644
,
0x0645
,
0x0646
,
0x0633
,
122
0x0639
,
0x0641
,
0x0635
,
0x0642
,
0x0631
,
123
0x0634
,
0x062A
,
0x062B
,
0x062E
,
0x0630
,
124
0x0636
,
0x0638
,
0x063A
,
125
}
,
126
[
'
thai
'
]
=
{
127
0xE050
,
0xE051
,
0xE052
,
0xE053
,
0xE054
,
128
0xE055
,
0xE056
,
0xE057
,
0xE058
,
0xE059
129
}
,
130
[
'
devangari
'
]
=
{
131
0x0966
,
0x0967
,
0x0968
,
0x0969
,
0x096A
,
132
0x096B
,
0x096C
,
0x096D
,
0x096E
,
0x096F
133
}
,
134
[
'
gurmurkhi
'
]
=
{
135
0x0A66
,
0x0A67
,
0x0A68
,
0x0A69
,
0x0A6A
,
136
0x0A6B
,
0x0A6C
,
0x0A6D
,
0x0A6E
,
0x0A6F
137
}
,
138
[
'
gujarati
'
]
=
{
139
0x0AE6
,
0x0AE7
,
0x0AE8
,
0x0AE9
,
0x0AEA
,
140
0x0AEB
,
0x0AEC
,
0x0AED
,
0x0AEE
,
0x0AEF
141
}
,
142
[
'
tibetan
'
]
=
{
143
0x0F20
,
0x0F21
,
0x0F22
,
0x0F23
,
0x0F24
,
144
0x0F25
,
0x0F26
,
0x0F27
,
0x0F28
,
0x0F29
145
}
,
146
[
'
korean
'
]
=
{
147
0x3131
,
0x3134
,
0x3137
,
0x3139
,
0x3141
,
148
0x3142
,
0x3145
,
0x3147
,
0x3148
,
0x314A
,
149
0x314B
,
0x314C
,
0x314D
,
0x314E
150
}
,
151
[
'
korean-parenthesis
'
]
=
{
--
152
0x3200
,
0x3201
,
0x3202
,
0x3203
,
0x3204
,
153
0x3205
,
0x3206
,
0x3207
,
0x3208
,
0x3209
,
154
0x320A
,
0x320B
,
0x320C
,
0x320D
155
}
,
156
[
'
korean-circle
'
]
=
{
-- circled
157
0x3260
,
0x3261
,
0x3262
,
0x3263
,
0x3264
,
158
0x3265
,
0x3266
,
0x3267
,
0x3268
,
0x3269
,
159
0x326A
,
0x326B
,
0x326C
,
0x326D
160
}
,
161
}
162 163
languages
.
counters
=
counters
164 165
counters
[
'
ar
'
]
=
counters
[
'
arabic
'
]
166
counters
[
'
gr
'
]
=
counters
[
'
greek
'
]
167
counters
[
'
g
'
]
=
counters
[
'
greek
'
]
168
counters
[
'
sl
'
]
=
counters
[
'
slovenian
'
]
169
counters
[
'
es
'
]
=
counters
[
'
spanish
'
]
170
counters
[
'
ru
'
]
=
counters
[
'
russian
'
]
171
counters
[
'
kr
'
]
=
counters
[
'
korean
'
]
172
counters
[
'
kr-p
'
]
=
counters
[
'
korean-parenthesis
'
]
173
counters
[
'
kr-c
'
]
=
counters
[
'
korean-circle
'
]
174 175
counters
[
'
thainumerals
'
]
=
counters
[
'
thai
'
]
176
counters
[
'
devanagarinumerals
'
]
=
counters
[
'
devanagari
'
]
177
counters
[
'
gurmurkhinumerals
'
]
=
counters
[
'
gurmurkhi
'
]
178
counters
[
'
gujaratinumerals
'
]
=
counters
[
'
gujarati
'
]
179
counters
[
'
tibetannumerals
'
]
=
counters
[
'
tibetan
'
]
180
counters
[
'
greeknumerals
'
]
=
counters
[
'
greek
'
]
181
counters
[
'
arabicnumerals
'
]
=
counters
[
'
arabic
'
]
182
counters
[
'
persiannumerals
'
]
=
counters
[
'
persian
'
]
183
counters
[
'
arabicexnumerals
'
]
=
counters
[
'
persian
'
]
184
counters
[
'
koreannumerals
'
]
=
counters
[
'
korean
'
]
185
counters
[
'
koreanparenthesisnumerals
'
]
=
counters
[
'
korean-parenthesis
'
]
186
counters
[
'
koreancirclenumerals
'
]
=
counters
[
'
korean-circle
'
]
187 188
counters
[
'
sloveniannumerals
'
]
=
counters
[
'
slovenian
'
]
189
counters
[
'
spanishnumerals
'
]
=
counters
[
'
spanish
'
]
190
counters
[
'
russiannumerals
'
]
=
counters
[
'
russian
'
]
191 192
local
decimals
=
allocate
{
193
[
'
arabic
'
]
=
{
194
[
"
0
"
]
=
"
٠
"
,
[
"
1
"
]
=
"
١
"
,
[
"
2
"
]
=
"
٢
"
,
[
"
3
"
]
=
"
٣
"
,
[
"
4
"
]
=
"
٤
"
,
195
[
"
5
"
]
=
"
٥
"
,
[
"
6
"
]
=
"
٦
"
,
[
"
7
"
]
=
"
٧
"
,
[
"
8
"
]
=
"
٨
"
,
[
"
9
"
]
=
"
٩
"
,
196
}
,
197
[
'
persian
'
]
=
{
198
[
"
0
"
]
=
"
۰
"
,
[
"
1
"
]
=
"
۱
"
,
[
"
2
"
]
=
"
۲
"
,
[
"
3
"
]
=
"
۳
"
,
[
"
4
"
]
=
"
۴
"
,
199
[
"
5
"
]
=
"
۵
"
,
[
"
6
"
]
=
"
۶
"
,
[
"
7
"
]
=
"
۷
"
,
[
"
8
"
]
=
"
۸
"
,
[
"
9
"
]
=
"
۹
"
,
200
}
201
}
202 203
languages
.
decimals
=
decimals
204 205
local
fallback
=
utfbyte
(
'
0
'
)
206 207
local
function
chr
(
n
,
m
)
208
return
(
n
>
0
and
n
<
27
and
utfchar
(
n
+
m
)
)
or
"
"
209
end
210 211
local
function
chrs
(
n
,
m
,
t
)
212
if
not
t
then
213
t
=
{
}
214
end
215
if
n
>
26
then
216
chrs
(
floor
(
(
n
-1
)
/
26
)
,
m
,
t
)
217
n
=
(
n
-1
)
%
26
+
1
218
end
219
if
n
~
=
0
then
220
t
[
#
t
+
1
]
=
utfchar
(
n
+
m
)
221
end
222
if
n
<
=
26
then
223
return
concat
(
t
)
224
end
225
end
226 227
local
function
maxchrs
(
n
,
m
,
cmd
,
t
)
228
if
not
t
then
229
t
=
{
}
230
end
231
if
n
>
m
then
232
maxchrs
(
floor
(
(
n
-1
)
/
m
)
,
m
,
cmd
)
233
n
=
(
n
-1
)
%
m
+
1
234
end
235
t
[
#
t
+
1
]
=
formatters
[
"
%s{%s}
"
]
(
cmd
,
n
)
236
if
n
<
=
m
then
237
return
concat
(
t
)
238
end
239
end
240 241
converters
.
chr
=
chr
242
converters
.
chrs
=
chrs
243
converters
.
maxchrs
=
maxchrs
244 245
local
lowercharacter
=
characters
.
lcchars
246
local
uppercharacter
=
characters
.
ucchars
247 248
local
defaultcounter
=
counters
.
default
249 250
local
function
do_alphabetic
(
n
,
mapping
,
mapper
,
t
)
-- todo: make zero based variant (initial n + 1)
251
if
not
t
then
252
t
=
{
}
253
end
254
local
max
=
#
mapping
255
if
n
>
max
then
256
do_alphabetic
(
floor
(
(
n
-1
)
/
max
)
,
mapping
,
mapper
,
t
)
257
n
=
(
n
-1
)
%
max
+
1
258
end
259
local
chr
=
mapping
[
n
]
or
fallback
260
t
[
#
t
+
1
]
=
mapper
and
mapper
[
chr
]
or
chr
261
if
n
<
=
max
then
262
return
concat
(
t
)
263
end
264
end
265 266
local
function
alphabetic
(
n
,
code
)
267
return
do_alphabetic
(
n
,
code
and
code
~
=
"
"
and
counters
[
code
]
or
defaultcounter
,
lowercharacter
)
268
end
269 270
local
function
Alphabetic
(
n
,
code
)
271
return
do_alphabetic
(
n
,
code
and
code
~
=
"
"
and
counters
[
code
]
or
defaultcounter
,
uppercharacter
)
272
end
273 274
converters
.
alphabetic
=
alphabetic
275
converters
.
Alphabetic
=
Alphabetic
276 277
-- we could make a replacer
278 279
local
function
todecimals
(
n
,
name
)
280
local
stream
=
tostring
(
n
)
281
local
mapping
=
decimals
[
name
]
282
return
mapping
and
gsub
(
stream
,
"
.
"
,
mapping
)
or
stream
283
end
284 285
converters
.
decimals
=
todecimals
286 287
local
lower_offset
=
96
288
local
upper_offset
=
64
289 290
function
converters
.
character
(
n
)
return
chr
(
n
,
lower_offset
)
end
291
function
converters
.
Character
(
n
)
return
chr
(
n
,
upper_offset
)
end
292
function
converters
.
characters
(
n
)
return
chrs
(
n
,
lower_offset
)
end
293
function
converters
.
Characters
(
n
)
return
chrs
(
n
,
upper_offset
)
end
294 295
implement
{
name
=
"
alphabetic
"
,
actions
=
{
alphabetic
,
context
}
,
arguments
=
{
"
integer
"
,
"
string
"
}
}
296
implement
{
name
=
"
Alphabetic
"
,
actions
=
{
Alphabetic
,
context
}
,
arguments
=
{
"
integer
"
,
"
string
"
}
}
297 298
implement
{
name
=
"
character
"
,
actions
=
{
chr
,
context
}
,
arguments
=
{
"
integer
"
,
lower_offset
}
}
299
implement
{
name
=
"
Character
"
,
actions
=
{
chr
,
context
}
,
arguments
=
{
"
integer
"
,
upper_offset
}
}
300
implement
{
name
=
"
characters
"
,
actions
=
{
chrs
,
context
}
,
arguments
=
{
"
integer
"
,
lower_offset
}
}
301
implement
{
name
=
"
Characters
"
,
actions
=
{
chrs
,
context
}
,
arguments
=
{
"
integer
"
,
upper_offset
}
}
302 303
implement
{
name
=
"
decimals
"
,
actions
=
{
todecimals
,
context
}
,
arguments
=
{
"
integer
"
,
"
string
"
}
}
304 305
local
weekday
=
os
.
weekday
-- moved to l-os
306
local
isleapyear
=
os
.
isleapyear
-- moved to l-os
307
local
nofdays
=
os
.
nofdays
-- moved to l-os
308 309
local
function
leapyear
(
year
)
310
return
isleapyear
(
year
)
and
1
or
0
311
end
312 313
local
function
textime
(
)
314
return
tonumber
(
osdate
(
"
%H
"
)
)
*
60
+
tonumber
(
osdate
(
"
%M
"
)
)
315
end
316 317
-- For consistenty we need to add day here but that conflicts with the current
318
-- serializer so then best is to have none from now on:
319 320
-- function converters.year () return osdate("%Y") end
321
-- function converters.month () return osdate("%m") end -- always two digits
322
-- function converters.day () return osdate("%d") end -- conflicts
323
-- function converters.hour () return osdate("%H") end
324
-- function converters.minute() return osdate("%M") end
325
-- function converters.second() return osdate("%S") end
326 327
converters
.
weekday
=
weekday
328
converters
.
isleapyear
=
isleapyear
329
converters
.
leapyear
=
leapyear
330
converters
.
nofdays
=
nofdays
331
converters
.
textime
=
textime
332 333
implement
{
name
=
"
weekday
"
,
actions
=
{
weekday
,
context
}
,
arguments
=
{
"
integer
"
,
"
integer
"
,
"
integer
"
}
}
334
implement
{
name
=
"
leapyear
"
,
actions
=
{
leapyear
,
context
}
,
arguments
=
"
integer
"
}
335
implement
{
name
=
"
nofdays
"
,
actions
=
{
nofdays
,
context
}
,
arguments
=
{
"
integer
"
,
"
integer
"
}
}
336 337
implement
{
name
=
"
year
"
,
actions
=
{
osdate
,
context
}
,
arguments
=
"
'%Y'
"
}
338
implement
{
name
=
"
month
"
,
actions
=
{
osdate
,
context
}
,
arguments
=
"
'%m'
"
}
339
implement
{
name
=
"
day
"
,
actions
=
{
osdate
,
context
}
,
arguments
=
"
'%d'
"
}
340
implement
{
name
=
"
hour
"
,
actions
=
{
osdate
,
context
}
,
arguments
=
"
'%H'
"
}
341
implement
{
name
=
"
minute
"
,
actions
=
{
osdate
,
context
}
,
arguments
=
"
'%M'
"
}
342
implement
{
name
=
"
second
"
,
actions
=
{
osdate
,
context
}
,
arguments
=
"
'%S'
"
}
343
implement
{
name
=
"
textime
"
,
actions
=
{
textime
,
context
}
}
344 345
implement
{
346
name
=
"
doifelseleapyear
"
,
347
actions
=
{
isleapyear
,
commands
.
doifelse
}
,
348
arguments
=
"
integer
"
349
}
350 351
local
roman
=
{
352
{
[
0
]
=
'
'
,
'
I
'
,
'
II
'
,
'
III
'
,
'
IV
'
,
'
V
'
,
'
VI
'
,
'
VII
'
,
'
VIII
'
,
'
IX
'
}
,
353
{
[
0
]
=
'
'
,
'
X
'
,
'
XX
'
,
'
XXX
'
,
'
XL
'
,
'
L
'
,
'
LX
'
,
'
LXX
'
,
'
LXXX
'
,
'
XC
'
}
,
354
{
[
0
]
=
'
'
,
'
C
'
,
'
CC
'
,
'
CCC
'
,
'
CD
'
,
'
D
'
,
'
DC
'
,
'
DCC
'
,
'
DCCC
'
,
'
CM
'
}
,
355
}
356 357
local
function
toroman
(
n
)
358
if
n
>
=
4000
then
359
return
toroman
(
floor
(
n
/
1000
)
)
.
.
"
"
.
.
toroman
(
n
%
1000
)
360
else
361
return
rep
(
"
M
"
,
floor
(
n
/
1000
)
)
.
.
roman
[
3
]
[
floor
(
(
n
%
1000
)
/
100
)
]
.
.
roman
[
2
]
[
floor
(
(
n
%
100
)
/
10
)
]
.
.
roman
[
1
]
[
floor
(
(
n
%
10
)
/
1
)
]
362
end
363
end
364 365
converters
.
toroman
=
toroman
366
converters
.
Romannumerals
=
toroman
367
converters
.
romannumerals
=
function
(
n
)
return
lower
(
toroman
(
n
)
)
end
368 369
converters
[
'
i
'
]
=
converters
.
romannumerals
370
converters
[
'
I
'
]
=
converters
.
Romannumerals
371
converters
[
'
r
'
]
=
converters
.
romannumerals
372
converters
[
'
R
'
]
=
converters
.
Romannumerals
373
converters
[
'
KR
'
]
=
converters
.
Romannumerals
374
converters
[
'
RK
'
]
=
converters
.
Romannumerals
375 376
implement
{
377
name
=
"
romannumerals
"
,
378
actions
=
{
toroman
,
lower
,
context
}
,
379
arguments
=
"
integer
"
,
380
}
381 382
implement
{
383
name
=
"
Romannumerals
"
,
384
actions
=
{
toroman
,
context
}
,
385
arguments
=
"
integer
"
,
386
}
387 388
--~ local small = {
389
--~ 0x0627, 0x066E, 0x062D, 0x062F, 0x0647, 0x0648, 0x0631
390
--~ }
391 392
--~ local large = {
393
--~ { 0x0627, 0x0628, 0x062C, 0x062F, 0x0647, 0x0648, 0x0632, 0x062D, 0x0637, },
394
--~ { 0x064A, 0x0643, 0x0644, 0x0645, 0x0646, 0x0633, 0x0639, 0x0641, 0x0635, },
395
--~ { 0x0642, 0x0631, 0x0634, 0x062A, 0x062B, 0x062E, 0x0630, 0x0636, 0x0638, },
396
--~ { 0x063A },
397
--~ }
398 399
local
small
=
{
400
"
ا
"
,
"
ٮ
"
,
"
ح
"
,
"
د
"
,
"
ه
"
,
"
و
"
,
"
ر
"
,
401
}
402 403
local
medium
=
{
404
"
ا
"
,
"
ب
"
,
"
ج
"
,
"
د
"
,
"
ه
"
,
"
و
"
,
"
ز
"
,
"
ح
"
,
"
ط
"
,
405
"
ي
"
,
"
ك
"
,
"
ل
"
,
"
م
"
,
"
ن
"
,
"
س
"
,
"
ع
"
,
"
ف
"
,
"
ص
"
,
406
"
ق
"
,
"
ر
"
,
"
ش
"
,
"
ت
"
,
"
ث
"
,
"
خ
"
,
"
ذ
"
,
"
ض
"
,
"
ظ
"
,
407
"
غ
"
,
408
}
409 410
local
large
=
{
411
{
"
ا
"
,
"
ب
"
,
"
ج
"
,
"
د
"
,
"
ه
"
,
"
و
"
,
"
ز
"
,
"
ح
"
,
"
ط
"
}
,
412
{
"
ي
"
,
"
ك
"
,
"
ل
"
,
"
م
"
,
"
ن
"
,
"
س
"
,
"
ع
"
,
"
ف
"
,
"
ص
"
}
,
413
{
"
ق
"
,
"
ر
"
,
"
ش
"
,
"
ت
"
,
"
ث
"
,
"
خ
"
,
"
ذ
"
,
"
ض
"
,
"
ظ
"
}
,
414
{
"
غ
"
}
,
415
}
416 417
local
function
toabjad
(
n
,
what
)
418
if
n
<
=
0
or
n
>
=
2000
then
419
return
tostring
(
n
)
420
elseif
what
=
=
2
and
n
<
=
7
then
421
return
small
[
n
]
422
elseif
what
=
=
3
and
n
<
=
28
then
423
return
medium
[
n
]
424
else
425
local
a
,
b
,
c
,
d
426
a
,
n
=
floor
(
n
/
1000
)
,
n
%
1000
-- mod(n,1000)
427
b
,
n
=
floor
(
n
/
100
)
,
n
%
100
-- mod(n, 100)
428
c
,
n
=
floor
(
n
/
10
)
,
n
%
10
-- mod(n, 10)
429
d
,
n
=
floor
(
n
/
1
)
,
n
%
1
-- mod(n, 1)
430
return
(
large
[
4
]
[
a
]
or
"
"
)
.
.
(
large
[
3
]
[
b
]
or
"
"
)
.
.
(
large
[
2
]
[
c
]
or
"
"
)
.
.
(
large
[
1
]
[
d
]
or
"
"
)
431
end
432
end
433 434
converters
.
toabjad
=
toabjad
435 436
function
converters
.
abjadnumerals
(
n
)
return
toabjad
(
n
,
false
)
end
437
function
converters
.
abjadnodotnumerals
(
n
)
return
toabjad
(
n
,
true
)
end
438 439
implement
{
440
name
=
"
abjadnumerals
"
,
441
actions
=
{
toabjad
,
context
}
,
442
arguments
=
{
"
integer
"
,
false
}
443
}
444 445
implement
{
446
name
=
"
abjadnodotnumerals
"
,
447
actions
=
{
toabjad
,
context
}
,
448
arguments
=
{
"
integer
"
,
true
}
449
}
450 451
-- -- - hebrew and jiddish -- -- --
452 453
local
trace_hebrew
trackers
.
register
(
"
converters.hebrew
"
,
function
(
v
)
454
trace_hebrew
=
v
455
end
)
456 457
local
list
=
{
458
{
400
,
"
ת
"
}
,
{
300
,
"
ש
"
}
,
{
200
,
"
ר
"
}
,
{
100
,
"
ק
"
}
,
459
{
90
,
"
צ
"
}
,
{
80
,
"
פ
"
}
,
{
70
,
"
ע
"
}
,
{
60
,
"
ס
"
}
,
{
50
,
"
נ
"
}
,
{
40
,
"
מ
"
}
,
{
30
,
"
ל
"
}
,
{
20
,
"
כ
"
}
,
{
10
,
"
י
"
}
,
460
{
9
,
"
ט
"
}
,
{
8
,
"
ח
"
}
,
{
7
,
"
ז
"
,
}
,
{
6
,
"
ו
"
,
}
,
{
5
,
"
ה
"
}
,
{
4
,
"
ד
"
}
,
{
3
,
"
ג
"
}
,
{
2
,
"
ב
"
}
,
{
1
,
"
א
"
}
,
461
}
462 463
local
special
=
{
464
[
15
]
=
"
ט״ו
"
,
-- exception: avoid mixup with God יה
465
[
16
]
=
"
ט״ז
"
,
-- exception: avoid mixup with God יו
466
}
467 468
local
function
tohebrew
(
n
,
gershayim
,
geresh
)
469
local
split
=
{
}
470
local
size
=
0
471
while
n
>
1000
do
472
size
=
size
+
1
473
split
[
size
]
=
n
%
1000
474
n
=
floor
(
n
/
1000
)
475
end
476
size
=
size
+
1
477
split
[
size
]
=
n
478
for
i
=
1
,
size
do
479
local
t
=
{
}
480
local
n
=
0
481
local
s
=
split
[
i
]
482
while
s
>
0
do
483
for
i
=
1
,
#
list
do
484
::
again
::
485
local
li
=
list
[
i
]
486
local
l1
=
li
[
1
]
487
local
s1
=
special
[
l1
]
488
if
s1
then
489
s
=
s
-
l1
490
n
=
n
+
1
491
t
[
n
]
=
s1
492
goto
again
493
elseif
s
>
=
l1
then
494
s
=
s
-
l1
495
n
=
n
+
1
496
t
[
n
]
=
li
[
2
]
497
goto
again
498
end
499
end
500
end
501
::
done
::
502
split
[
i
]
=
t
503
end
504
if
gershayim
then
505
for
i
=
1
,
size
do
506
local
si
=
split
[
i
]
507
local
ni
=
#
si
508
if
ni
>
=
2
then
509
local
s
=
"
״
"
510
insert
(
split
[
i
]
,
ni
,
trace_hebrew
and
(
"
{\\red
"
.
.
s
.
.
"
}
"
)
or
s
)
511
end
512
end
513
end
514
if
geresh
then
515
for
i
=
2
,
#
split
do
516
local
s
=
rep
(
"
׳
"
,
i
-1
)
517
insert
(
split
[
i
]
,
trace_hebrew
and
(
"
{\\blue
"
.
.
s
.
.
"
}
"
)
or
s
)
518
end
519
end
520
for
i
=
1
,
size
do
521
split
[
i
]
=
concat
(
split
[
i
]
)
522
end
523
return
concat
(
reverse
(
split
)
)
524
end
525 526
converters
.
tohebrew
=
tohebrew
527
converters
.
hebrewnumerals
=
converters
.
tohebrew
528 529
-- converters['alphabetic:hb'] = converters.hebrewnumerals
530 531
interfaces
.
implement
{
532
name
=
"
hebrewnumerals
"
,
533
actions
=
{
tohebrew
,
context
}
,
534
arguments
=
{
"
integer
"
,
true
,
true
}
535
}
536 537
-- -- --
538 539
local
vector
=
{
540
normal
=
{
541
[
0
]
=
"
"
,
542
[
1
]
=
"
"
,
543
[
2
]
=
"
"
,
544
[
3
]
=
"
"
,
545
[
4
]
=
"
"
,
546
[
5
]
=
"
"
,
547
[
6
]
=
"
"
,
548
[
7
]
=
"
"
,
549
[
8
]
=
"
"
,
550
[
9
]
=
"
"
,
551
[
10
]
=
"
"
,
552
[
100
]
=
"
"
,
553
[
1000
]
=
"
"
,
554
[
10000
]
=
"
"
,
555
[
100000000
]
=
"
亿
"
,
556
}
,
557
cap
=
{
558
[
0
]
=
"
"
,
559
[
1
]
=
"
"
,
560
[
2
]
=
"
"
,
561
[
3
]
=
"
"
,
562
[
4
]
=
"
"
,
563
[
5
]
=
"
"
,
564
[
6
]
=
"
"
,
565
[
7
]
=
"
"
,
566
[
8
]
=
"
"
,
567
[
9
]
=
"
"
,
568
[
10
]
=
"
"
,
569
[
100
]
=
"
"
,
570
[
1000
]
=
"
"
,
571
[
10000
]
=
"
"
,
572
[
100000000
]
=
"
亿
"
,
573
}
,
574
all
=
{
575
[
0
]
=
"
"
,
576
[
1
]
=
"
"
,
577
[
2
]
=
"
"
,
578
[
3
]
=
"
"
,
579
[
4
]
=
"
"
,
580
[
5
]
=
"
"
,
581
[
6
]
=
"
"
,
582
[
7
]
=
"
"
,
583
[
8
]
=
"
"
,
584
[
9
]
=
"
"
,
585
[
10
]
=
"
"
,
586
[
20
]
=
"
廿
"
,
587
[
30
]
=
"
"
,
588
[
100
]
=
"
"
,
589
[
1000
]
=
"
"
,
590
[
10000
]
=
"
"
,
591
[
100000000
]
=
"
亿
"
,
592
}
593
}
594 595
local
function
tochinese
(
n
,
name
)
-- normal, caps, all
596
-- improved version by Li Yanrui
597
local
result
,
r
=
{
}
,
0
598
local
vector
=
vector
[
name
]
or
vector
.
normal
599
while
true
do
600
if
n
=
=
0
then
601
break
602
elseif
n
>
=
100000000
then
603
local
m
=
floor
(
n
/
100000000
)
604
r
=
r
+
1
;
result
[
r
]
=
tochinese
(
m
,
name
)
605
r
=
r
+
1
;
result
[
r
]
=
vector
[
100000000
]
606
local
z
=
n
-
m
*
100000000
607
if
z
>
0
and
z
<
10000000
then
r
=
r
+
1
;
result
[
r
]
=
vector
[
0
]
end
608
n
=
n
%
100000000
609
elseif
n
>
=
10000000
then
610
local
m
=
floor
(
n
/
10000
)
611
r
=
r
+
1
;
result
[
r
]
=
tochinese
(
m
,
name
)
612
r
=
r
+
1
;
result
[
r
]
=
vector
[
10000
]
613
local
z
=
n
-
m
*
10000
614
if
z
>
0
and
z
<
1000
then
r
=
r
+
1
;
result
[
r
]
=
vector
[
0
]
end
615
n
=
n
%
10000
616
elseif
n
>
=
1000000
then
617
local
m
=
floor
(
n
/
10000
)
618
r
=
r
+
1
;
result
[
r
]
=
tochinese
(
m
,
name
)
619
r
=
r
+
1
;
result
[
r
]
=
vector
[
10000
]
620
local
z
=
n
-
m
*
10000
621
if
z
>
0
and
z
<
1000
then
r
=
r
+
1
;
result
[
r
]
=
vector
[
0
]
end
622
n
=
n
%
10000
623
elseif
n
>
=
100000
then
624
local
m
=
floor
(
n
/
10000
)
625
r
=
r
+
1
;
result
[
r
]
=
tochinese
(
m
,
name
)
626
r
=
r
+
1
;
result
[
r
]
=
vector
[
10000
]
627
local
z
=
n
-
m
*
10000
628
if
z
>
0
and
z
<
1000
then
r
=
r
+
1
;
result
[
r
]
=
vector
[
0
]
end
629
n
=
n
%
10000
630
elseif
n
>
=
10000
then
631
local
m
=
floor
(
n
/
10000
)
632
r
=
r
+
1
;
result
[
r
]
=
vector
[
m
]
633
r
=
r
+
1
;
result
[
r
]
=
vector
[
10000
]
634
local
z
=
n
-
m
*
10000
635
if
z
>
0
and
z
<
1000
then
r
=
r
+
1
;
result
[
r
]
=
vector
[
0
]
end
636
n
=
n
%
10000
637
elseif
n
>
=
1000
then
638
local
m
=
floor
(
n
/
1000
)
639
r
=
r
+
1
;
result
[
r
]
=
vector
[
m
]
640
r
=
r
+
1
;
result
[
r
]
=
vector
[
1000
]
641
local
z
=
n
-
m
*
1000
642
if
z
>
0
and
z
<
100
then
r
=
r
+
1
;
result
[
r
]
=
vector
[
0
]
end
643
n
=
n
%
1000
644
elseif
n
>
=
100
then
645
local
m
=
floor
(
n
/
100
)
646
r
=
r
+
1
;
result
[
r
]
=
vector
[
m
]
647
r
=
r
+
1
;
result
[
r
]
=
vector
[
100
]
648
local
z
=
n
-
m
*
100
649
if
z
>
0
and
z
<
10
then
r
=
r
+
1
;
result
[
r
]
=
vector
[
0
]
end
650
n
=
n
%
100
651
elseif
n
>
=
10
then
652
local
m
=
floor
(
n
/
10
)
653
if
m
>
1
and
vector
[
m
*
10
]
then
654
r
=
r
+
1
;
result
[
r
]
=
vector
[
m
*
10
]
655
else
656
r
=
r
+
1
;
result
[
r
]
=
vector
[
m
]
657
r
=
r
+
1
;
result
[
r
]
=
vector
[
10
]
658
end
659
n
=
n
%
10
660
else
661
r
=
r
+
1
;
result
[
r
]
=
vector
[
n
]
662
break
663
end
664
end
665
if
(
result
[
1
]
=
=
vector
[
1
]
and
result
[
2
]
=
=
vector
[
10
]
)
then
666
result
[
1
]
=
"
"
667
end
668
return
concat
(
result
)
669
end
670 671
-- local t = { 1,10,15,25,35,45,11,100,111,1111,10000,11111,100000,111111,1111111,11111111,111111111,100000000,1111111111,11111111111,111111111111,1111111111111 }
672
-- for k=1,#t do
673
-- local v = t[k]
674
-- print(v,tochinese(v),tochinese(v,"all"),tochinese(v,"cap"))
675
-- end
676 677
converters
.
tochinese
=
tochinese
678 679
function
converters
.
chinesenumerals
(
n
,
how
)
return
tochinese
(
n
,
how
or
"
normal
"
)
end
680
function
converters
.
chinesecapnumerals
(
n
)
return
tochinese
(
n
,
"
cap
"
)
end
681
function
converters
.
chineseallnumerals
(
n
)
return
tochinese
(
n
,
"
all
"
)
end
682 683
converters
[
'
cn
'
]
=
converters
.
chinesenumerals
684
converters
[
'
cn-c
'
]
=
converters
.
chinesecapnumerals
685
converters
[
'
cn-a
'
]
=
converters
.
chineseallnumerals
686 687
implement
{
688
name
=
"
chinesenumerals
"
,
689
actions
=
{
tochinese
,
context
}
,
690
arguments
=
{
"
integer
"
,
"
string
"
}
691
}
692 693
-- this is a temporary solution: we need a better solution when we have
694
-- more languages
695 696
converters
[
'
a
'
]
=
converters
.
characters
697
converters
[
'
A
'
]
=
converters
.
Characters
698
converters
[
'
AK
'
]
=
converters
.
Characters
-- obsolete
699
converters
[
'
KA
'
]
=
converters
.
Characters
-- obsolete
700 701
function
converters
.
spanishnumerals
(
n
)
return
alphabetic
(
n
,
"
es
"
)
end
702
function
converters
.
Spanishnumerals
(
n
)
return
Alphabetic
(
n
,
"
es
"
)
end
703
function
converters
.
sloveniannumerals
(
n
)
return
alphabetic
(
n
,
"
sl
"
)
end
704
function
converters
.
Sloveniannumerals
(
n
)
return
Alphabetic
(
n
,
"
sl
"
)
end
705
function
converters
.
russiannumerals
(
n
)
return
alphabetic
(
n
,
"
ru
"
)
end
706
function
converters
.
Russiannumerals
(
n
)
return
Alphabetic
(
n
,
"
ru
"
)
end
707 708
converters
[
'
alphabetic:es
'
]
=
converters
.
spanishnumerals
709
converters
[
'
alphabetic:sl
'
]
=
converters
.
sloveniannumerals
710
converters
[
'
alphabetic:ru
'
]
=
converters
.
russiannumerals
711 712
converters
[
'
Alphabetic:es
'
]
=
converters
.
Spanishnumerals
713
converters
[
'
Alphabetic:sl
'
]
=
converters
.
Sloveniannumerals
714
converters
[
'
Alphabetic:ru
'
]
=
converters
.
Russiannumerals
715 716
-- bonus
717 718
converters
[
'
a:es
'
]
=
converters
.
spanishnumerals
719
converters
[
'
a:sl
'
]
=
converters
.
sloveniannumerals
720
converters
[
'
a:ru
'
]
=
converters
.
russiannumerals
721
converters
[
'
A:es
'
]
=
converters
.
Spanishnumerals
722
converters
[
'
A:sl
'
]
=
converters
.
Sloveniannumerals
723
converters
[
'
A:ru
'
]
=
converters
.
Russiannumerals
724 725
-- end of bonus
726 727
converters
.
sequences
=
converters
.
sequences
or
{
}
728
local
sequences
=
converters
.
sequences
729 730
storage
.
register
(
"
converters/sequences
"
,
sequences
,
"
converters.sequences
"
)
731 732
function
converters
.
define
(
name
,
set
)
-- ,language)
733
-- if language then
734
-- name = name .. ":" .. language
735
-- end
736
sequences
[
name
]
=
settings_to_array
(
set
)
737
end
738 739
function
converters
.
max
(
name
)
740
local
s
=
sequences
[
name
]
741
return
s
and
#
s
or
0
742
end
743 744
implement
{
745
name
=
"
defineconversion
"
,
746
actions
=
converters
.
define
,
747
arguments
=
"
2 strings
"
,
748
}
749 750
implement
{
751
name
=
"
nofconversions
"
,
752
actions
=
{
converters
.
max
,
context
}
,
753
arguments
=
"
string
"
,
754
}
755 756
local
function
convert
(
method
,
n
,
language
)
757
local
converter
=
language
and
converters
[
method
.
.
"
:
"
.
.
language
]
or
converters
[
method
]
758
if
converter
then
759
return
converter
(
n
)
760
else
761
local
lowermethod
=
lower
(
method
)
762
local
linguistic
=
counters
[
lowermethod
]
763
if
linguistic
then
764
return
do_alphabetic
(
n
,
linguistic
,
lowermethod
=
=
method
and
lowercharacter
or
uppercharacter
)
765
end
766
local
sequence
=
sequences
[
method
]
767
if
sequence
then
768
local
max
=
#
sequence
769
if
n
>
max
then
770
return
sequence
[
(
n
-1
)
%
max
+
1
]
771
else
772
return
sequence
[
n
]
773
end
774
end
775
return
n
776
end
777
end
778 779
converters
.
convert
=
convert
780 781
local
function
valid
(
method
,
language
)
782
return
converters
[
method
.
.
"
:
"
.
.
language
]
or
converters
[
method
]
or
sequences
[
method
]
783
end
784 785
implement
{
786
name
=
"
doifelseconverter
"
,
787
actions
=
{
valid
,
commands
.
doifelse
}
,
788
arguments
=
"
2 strings
"
,
789
}
790 791
implement
{
792
name
=
"
checkedconversion
"
,
793
actions
=
{
convert
,
context
}
,
794
arguments
=
{
"
string
"
,
"
integer
"
}
795
}
796 797
-- hebrew data conversion
798 799
local
gregorian_to_hebrew
do
800 801
-- The next code is based on the c code at https://github.com/hebcal/hebcal
802
--
803
-- Hebcal : A Jewish Calendar Generator
804
-- Copyright : 1994 - 2004 Danny Sadinoff, 2002 Michael J. Radwin
805
-- License : GPL
806
--
807
-- Because we only need simple dates, we use part of the code. There is more
808
-- at that github place.
809
--
810
-- The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
811
-- The Gregorian date Sunday, December 31, 1 BC is imaginary.
812
--
813
-- The code is luafied and a little different because we have no assignments
814
-- in loops and such. We could speed up the code but then we divert from the
815
-- original. This is not that critical anyway.
816 817
local
NISAN
=
1
818
local
IYYAR
=
2
819
local
SIVAN
=
3
820
local
TAMUZ
=
4
821
local
AV
=
5
822
local
ELUL
=
6
823
local
TISHREI
=
7
824
local
CHESHVAN
=
8
825
local
KISLEV
=
9
826
local
TEVET
=
10
827
local
SHVAT
=
11
828
local
ADAR_I
=
12
829
local
ADAR_II
=
13
830 831
local
mmap
=
{
832
KISLEV
,
833
TEVET
,
834
SHVAT
,
835
ADAR_I
,
836
NISAN
,
837
IYYAR
,
838
SIVAN
,
839
TAMUZ
,
840
TISHREI
,
841
TISHREI
,
842
TISHREI
,
843
CHESHVAN
844
}
845 846
local
function
greg2abs
(
year
,
month
,
day
)
847
local
y
=
year
-
1
848
return
y
*
365
+
div
(
y
,
4
)
-
div
(
y
,
100
)
+
div
(
y
,
400
)
+
os
.
nofdays
(
year
,
month
,
day
)
849
end
850 851
local
function
abs2greg
(
abs
)
852 853
local
d0
=
abs
-
1
854 855
local
n400
=
div
(
d0
,
146097
)
856
local
d1
=
mod
(
d0
,
146097
)
857
local
n100
=
div
(
d1
,
36524
)
858
local
d2
=
mod
(
d1
,
36524
)
859
local
n4
=
div
(
d2
,
1461
)
860
local
d3
=
mod
(
d2
,
1461
)
861
local
n1
=
div
(
d3
,
365
)
862 863
local
day
=
mod
(
d3
,
365
)
+
1
864
local
year
=
400
*
n400
+
100
*
n100
+
4
*
n4
+
n1
865 866
if
n100
=
=
4
or
n1
=
=
4
then
867
return
year
,
12
,
31
868
else
869
year
=
year
+
1
870
month
=
1
871
while
true
do
872
local
mlen
=
os
.
nofdays
(
year
,
month
)
873
if
mlen
<
day
then
874
day
=
day
-
mlen
875
month
=
month
+
1
876
else
877
break
878
end
879
end
880
return
year
,
month
,
day
881
end
882
end
883 884
local
function
hebrew_leapyear
(
year
)
885
return
mod
(
1
+
year
*
7
,
19
)
<
7
886
end
887 888
local
function
hebrew_months_in_year
(
year
)
889
return
hebrew_leapyear
(
year
)
and
13
or
12
890
end
891 892
local
function
hebrew_elapsed_days
(
year
)
893
local
y
=
year
-
1
894
local
m_elapsed
=
235
*
div
(
y
,
19
)
+
12
*
mod
(
y
,
19
)
+
div
(
(
(
mod
(
y
,
19
)
*
7
)
+
1
)
,
19
)
895
local
p_elapsed
=
204
+
793
*
mod
(
m_elapsed
,
1080
)
896
local
h_elapsed
=
5
+
12
*
m_elapsed
+
793
*
div
(
m_elapsed
,
1080
)
+
div
(
p_elapsed
,
1080
)
897
local
parts
=
mod
(
p_elapsed
,
1080
)
+
1080
*
mod
(
h_elapsed
,
24
)
898
local
day
=
1
+
29
*
m_elapsed
+
div
(
h_elapsed
,
24
)
899
local
d
=
mod
(
day
,
7
)
900
local
alt_day
=
day
901
if
parts
>
=
19440
902
or
(
parts
>
=
9924
and
d
=
=
2
and
not
(
hebrew_leapyear
(
year
)
)
)
903
or
(
parts
>
=
16789
and
d
=
=
1
and
hebrew_leapyear
(
y
)
)
then
904
alt_day
=
alt_day
+
1
905
end
906
d
=
mod
(
alt_day
,
7
)
907
if
d
=
=
0
or
d
=
=
3
or
d
=
=
5
then
908
alt_day
=
alt_day
+
1
909
end
910
return
alt_day
911
end
912 913
local
function
days_in_hebrew_year
(
year
)
914
return
hebrew_elapsed_days
(
year
+
1
)
-
hebrew_elapsed_days
(
year
)
915
end
916 917
local
function
long_cheshvan
(
year
)
918
return
mod
(
days_in_hebrew_year
(
year
)
,
10
)
=
=
5
919
end
920 921
local
function
short_kislev
(
year
)
922
return
mod
(
days_in_hebrew_year
(
year
)
,
10
)
=
=
3
923
end
924 925
local
function
max_days_in_heb_month
(
month
,
year
)
926
if
month
=
=
IYYAR
or
month
=
=
TAMUZ
or
month
=
=
ELUL
or
month
=
=
TEVET
or
month
=
=
ADAR_II
or
927
(
month
=
=
ADAR_I
and
not
hebrew_leapyear
(
year
)
)
or
928
(
month
=
=
CHESHVAN
and
not
long_cheshvan
(
year
)
)
or
929
(
month
=
=
KISLEV
and
short_kislev
(
year
)
)
then
930
return
29
931
else
932
return
30
933
end
934
end
935 936
local
function
hebrew2abs
(
year
,
month
,
day
)
937
if
month
<
TISHREI
then
938
for
m
=
TISHREI
,
hebrew_months_in_year
(
year
)
,
1
do
939
day
=
day
+
max_days_in_heb_month
(
m
,
year
)
940
end
941
for
m
=
NISAN
,
month
-
1
,
1
do
942
day
=
day
+
max_days_in_heb_month
(
m
,
year
)
943
end
944
else
945
for
m
=
TISHREI
,
month
-
1
,
1
do
946
day
=
day
+
max_days_in_heb_month
(
m
,
year
)
947
end
948
end
949
return
hebrew_elapsed_days
(
year
)
-
1373429
+
day
950
end
951 952
local
function
abs2hebrew
(
abs
)
953
local
yy
,
mm
,
dd
=
abs2greg
(
abs
)
954
local
day
=
1
955
local
month
=
TISHREI
956
local
year
=
3760
+
yy
957
while
abs
>
=
hebrew2abs
(
year
+
1
,
month
,
day
)
do
958
year
=
year
+
1
959
end
960
if
year
>
=
4635
and
year
<
10666
then
961
month
=
mmap
[
mm
]
962
end
963
while
abs
>
hebrew2abs
(
year
,
month
,
max_days_in_heb_month
(
month
,
year
)
)
do
964
month
=
mod
(
month
,
hebrew_months_in_year
(
year
)
)
+
1
965
end
966
day
=
abs
-
hebrew2abs
(
year
,
month
,
1
)
+
1
967
return
year
,
month
,
day
968
end
969 970
-- months = { "ניסן" "אייר" "סיון" "תמוז" "אב" "אלול" "תשרי" "חשון" "כסלו" "טבת" "שבט" }
971 972
gregorian_to_hebrew
=
function
(
y
,
m
,
d
)
973
return
abs2hebrew
(
greg2abs
(
y
,
m
,
d
)
)
974
end
975 976
converters
.
gregorian_to_hebrew
=
gregorian_to_hebrew
977 978
end
979 980
local
gregorian_to_jalali
,
jalali_to_gregorian
do
981 982
-- Well, since the one asking for this didn't test it the following code is not
983
-- enabled.
984
--
985
-- -- This Lua version is based on a Javascript by Behdad Esfahbod which in turn
986
-- -- is based on GPL'd code by Roozbeh Pournader of the The FarsiWeb Project
987
-- -- Group: http://www.farsiweb.info/jalali/jalali.js.
988
-- --
989
-- -- We start tables at one, I kept it zero based in order to stay close to
990
-- -- the original.
991
-- --
992
-- -- Conversion by Hans Hagen
993 994
local
g_days_in_month
=
{
[
0
]
=
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
995
local
j_days_in_month
=
{
[
0
]
=
31
,
31
,
31
,
31
,
31
,
31
,
30
,
30
,
30
,
30
,
30
,
29
}
996 997 998
gregorian_to_jalali
=
function
(
gy
,
gm
,
gd
)
999
local
jy
,
jm
,
jd
,
g_day_no
,
j_day_no
,
j_np
,
i
1000
gy
,
gm
,
gd
=
gy
-
1600
,
gm
-
1
,
gd
-
1
1001
g_day_no
=
365
*
gy
+
div
(
(
gy
+
3
)
,
4
)
-
div
(
(
gy
+
99
)
,
100
)
+
div
(
(
gy
+
399
)
,
400
)
1002
i
=
0
1003
while
i
<
gm
do
1004
g_day_no
=
g_day_no
+
g_days_in_month
[
i
]
1005
i
=
i
+
1
1006
end
1007
if
(
gm
>
1
and
(
(
gy
%
4
=
=
0
and
gy
%
100
~
=
0
)
or
(
gy
%
400
=
=
0
)
)
)
then
1008
g_day_no
=
g_day_no
+
1
1009
end
1010
g_day_no
=
g_day_no
+
gd
1011
j_day_no
=
g_day_no
-
79
1012
j_np
=
div
(
j_day_no
,
12053
)
1013
j_day_no
=
mod
(
j_day_no
,
12053
)
1014
jy
=
979
+
33
*
j_np
+
4
*
div
(
j_day_no
,
1461
)
1015
j_day_no
=
mod
(
j_day_no
,
1461
)
1016
if
j_day_no
>
=
366
then
1017
jy
=
jy
+
div
(
(
j_day_no
-1
)
,
365
)
1018
j_day_no
=
mod
(
(
j_day_no
-1
)
,
365
)
1019
end
1020
i
=
0
1021
while
i
<
11
and
j_day_no
>
=
j_days_in_month
[
i
]
do
1022
j_day_no
=
j_day_no
-
j_days_in_month
[
i
]
1023
i
=
i
+
1
1024
end
1025
jm
=
i
+
1
1026
jd
=
j_day_no
+
1
1027
return
jy
,
jm
,
jd
1028
end
1029 1030
jalali_to_gregorian
=
function
(
jy
,
jm
,
jd
)
1031
local
gy
,
gm
,
gd
,
g_day_no
,
j_day_no
,
leap
,
i
1032
jy
,
jm
,
jd
=
jy
-
979
,
jm
-
1
,
jd
-
1
1033
j_day_no
=
365
*
jy
+
div
(
jy
,
33
)
*
8
+
div
(
(
mod
(
jy
,
33
)
+
3
)
,
4
)
1034
for
i
=
0
,
jm
-1
,
1
do
1035
j_day_no
=
j_day_no
+
j_days_in_month
[
i
]
1036
end
1037
j_day_no
=
j_day_no
+
jd
1038
g_day_no
=
j_day_no
+
79
1039
gy
=
1600
+
400
*
div
(
g_day_no
,
146097
)
1040
g_day_no
=
mod
(
g_day_no
,
146097
)
1041
leap
=
1
1042
if
g_day_no
>
=
36525
then
1043
g_day_no
=
g_day_no
-
1
1044
gy
=
gy
+
100
*
div
(
g_day_no
,
36524
)
1045
g_day_no
=
mod
(
g_day_no
,
36524
)
1046
if
g_day_no
>
=
365
then
1047
g_day_no
=
g_day_no
+
1
1048
else
1049
leap
=
0
1050
end
1051
end
1052
gy
=
gy
+
4
*
div
(
g_day_no
,
1461
)
1053
g_day_no
=
mod
(
g_day_no
,
1461
)
1054
if
g_day_no
>
=
366
then
1055
leap
=
0
1056
g_day_no
=
g_day_no
-
1
1057
gy
=
gy
+
div
(
g_day_no
,
365
)
1058
g_day_no
=
mod
(
g_day_no
,
365
)
1059
end
1060
i
=
0
1061
while
true
do
1062
local
d
=
g_days_in_month
[
i
]
+
(
(
i
=
=
1
and
leap
)
or
0
)
1063
if
g_day_no
>
=
d
then
1064
g_day_no
=
g_day_no
-
d
1065
i
=
i
+
1
1066
else
1067
break
1068
end
1069
end
1070
gm
=
i
+
1
1071
gd
=
g_day_no
+
1
1072
return
gy
,
gm
,
gd
1073
end
1074 1075
-- local function test(yg,mg,dg,yj,mj,dj)
1076
-- local y1, m1, d1 = jalali_to_gregorian(yj,mj,dj)
1077
-- local y2, m2, d2 = gregorian_to_jalali(yg,mg,dg)
1078
-- print(y1 == yg and m1 == mg and d1 == dg, yg,mg,dg, y1,m1,d1)
1079
-- print(y2 == yj and m2 == mj and d2 == dj, yj,mj,dj, y2,m2,d2)
1080
-- end
1081 1082
-- test(1953,08,19, 1332,05,28)
1083
-- test(1979,02,11, 1357,11,22)
1084
-- test(2000,02,28, 1378,12,09)
1085
-- test(2000,03,01, 1378,12,11)
1086
-- test(2009,02,24, 1387,12,06)
1087
-- test(2015,03,21, 1394,01,01)
1088
-- test(2016,03,20, 1395,01,01)
1089 1090
converters
.
gregorian_to_jalali
=
gregorian_to_jalali
1091
converters
.
jalali_to_gregorian
=
jalali_to_gregorian
1092 1093
end
1094 1095
-- -- more efficient but needs testing
1096 1097
-- local escapes = characters.filters.utf.private.escapes
1098 1099
-- local function do_alphabetic(n,mapping,chr)
1100
-- local max = #mapping
1101
-- if n > max then
1102
-- do_alphabetic(floor((n-1)/max),mapping,chr)
1103
-- n = (n-1)%max+1
1104
-- end
1105
-- n = chr(n,mapping)
1106
-- context(escapes[n] or utfchar(n))
1107
-- end
1108 1109
-- local lccodes, uccodes, safechar = characters.lccode, characters.uccode, commands.safechar
1110 1111
-- local function do_alphabetic(n,mapping,chr)
1112
-- local max = #mapping
1113
-- if n > max then
1114
-- do_alphabetic(floor((n-1)/max),mapping,chr)
1115
-- n = (n-1)%max+1
1116
-- end
1117
-- safechar(chr(n,mapping))
1118
-- end
1119 1120
-- local function lowercased(n,mapping) return characters.lccode(mapping[n] or fallback) end
1121
-- local function uppercased(n,mapping) return characters.uccode(mapping[n] or fallback) end
1122 1123
-- function converters.alphabetic(n,code)
1124
-- do_alphabetic(n,counters[code] or counters.default,lowercased) -- lccode catches wrong tables
1125
-- end
1126 1127
-- function converters.Alphabetic(n,code)
1128
-- do_alphabetic(n,counters[code] or counters.default,uppercased)
1129
-- end
1130 1131
local
ordinals
=
{
1132
english
=
function
(
n
)
1133
local
two
=
n
%
100
1134
if
two
=
=
11
or
two
=
=
12
or
two
=
=
13
then
1135
return
"
th
"
1136
else
1137
local
one
=
n
%
10
1138
if
one
=
=
1
then
1139
return
"
st
"
1140
elseif
one
=
=
2
then
1141
return
"
nd
"
1142
elseif
one
=
=
3
then
1143
return
"
rd
"
1144
else
1145
return
"
th
"
1146
end
1147
end
1148
end
,
1149
dutch
=
function
(
n
)
1150
return
"
e
"
1151
end
,
1152
french
=
function
(
n
)
1153
if
n
=
=
1
then
1154
return
"
er
"
1155
end
1156
end
,
1157
}
1158 1159
ordinals
.
en
=
ordinals
.
english
1160
ordinals
.
nl
=
ordinals
.
dutch
1161
ordinals
.
fr
=
ordinals
.
french
1162 1163
function
converters
.
ordinal
(
n
,
language
)
1164
local
t
=
language
and
ordinals
[
language
]
1165
return
t
and
t
(
n
)
1166
end
1167 1168
local
function
ctxordinal
(
n
,
language
)
1169
local
t
=
language
and
ordinals
[
language
]
1170
local
o
=
t
and
t
(
n
)
1171
context
(
n
)
1172
if
o
then
1173
ctx_highordinalstr
(
o
)
1174
end
1175
end
1176 1177
implement
{
1178
name
=
"
ordinal
"
,
1179
actions
=
ctxordinal
,
1180
arguments
=
{
"
integer
"
,
"
string
"
}
1181
}
1182 1183
-- verbose numbers
1184 1185
local
data
=
allocate
(
)
1186
local
verbose
=
{
data
=
data
}
1187
converters
.
verbose
=
verbose
1188 1189
-- verbose english
1190 1191
local
words
=
{
1192
[
0
]
=
"
zero
"
,
1193
[
1
]
=
"
one
"
,
1194
[
2
]
=
"
two
"
,
1195
[
3
]
=
"
three
"
,
1196
[
4
]
=
"
four
"
,
1197
[
5
]
=
"
five
"
,
1198
[
6
]
=
"
six
"
,
1199
[
7
]
=
"
seven
"
,
1200
[
8
]
=
"
eight
"
,
1201
[
9
]
=
"
nine
"
,
1202
[
10
]
=
"
ten
"
,
1203
[
11
]
=
"
eleven
"
,
1204
[
12
]
=
"
twelve
"
,
1205
[
13
]
=
"
thirteen
"
,
1206
[
14
]
=
"
fourteen
"
,
1207
[
15
]
=
"
fifteen
"
,
1208
[
16
]
=
"
sixteen
"
,
1209
[
17
]
=
"
seventeen
"
,
1210
[
18
]
=
"
eighteen
"
,
1211
[
19
]
=
"
nineteen
"
,
1212
[
20
]
=
"
twenty
"
,
1213
[
30
]
=
"
thirty
"
,
1214
[
40
]
=
"
forty
"
,
1215
[
50
]
=
"
fifty
"
,
1216
[
60
]
=
"
sixty
"
,
1217
[
70
]
=
"
seventy
"
,
1218
[
80
]
=
"
eighty
"
,
1219
[
90
]
=
"
ninety
"
,
1220
[
100
]
=
"
hundred
"
,
1221
[
1000
]
=
"
thousand
"
,
1222
[
1000000
]
=
"
million
"
,
1223
[
1000000000
]
=
"
billion
"
,
1224
[
1000000000000
]
=
"
trillion
"
,
1225
}
1226 1227
local
function
translate
(
n
)
1228
local
w
=
words
[
n
]
1229
if
w
then
1230
return
w
1231
end
1232
local
t
=
{
}
1233
local
function
compose_one
(
n
)
1234
local
w
=
words
[
n
]
1235
if
w
then
1236
t
[
#
t
+
1
]
=
w
1237
return
1238
end
1239
local
a
,
b
=
floor
(
n
/
100
)
,
n
%
100
1240
if
a
=
=
10
then
1241
t
[
#
t
+
1
]
=
words
[
1
]
1242
t
[
#
t
+
1
]
=
words
[
1000
]
1243
elseif
a
>
0
then
1244
t
[
#
t
+
1
]
=
words
[
a
]
1245
t
[
#
t
+
1
]
=
words
[
100
]
1246
-- don't say 'nine hundred zero'
1247
if
b
=
=
0
then
1248
return
1249
end
1250
end
1251
if
words
[
b
]
then
1252
t
[
#
t
+
1
]
=
words
[
b
]
1253
else
1254
a
,
b
=
floor
(
b
/
10
)
,
n
%
10
1255
t
[
#
t
+
1
]
=
words
[
a
*
10
]
1256
t
[
#
t
+
1
]
=
words
[
b
]
1257
end
1258
end
1259
local
function
compose_two
(
n
,
m
)
1260
if
n
>
(
m
-1
)
then
1261
local
a
,
b
=
floor
(
n
/
m
)
,
n
%
m
1262
if
a
>
0
then
1263
compose_one
(
a
)
1264
end
1265
t
[
#
t
+
1
]
=
words
[
m
]
1266
n
=
b
1267
end
1268
return
n
1269
end
1270
n
=
compose_two
(
n
,
1000000000000
)
1271
n
=
compose_two
(
n
,
1000000000
)
1272
n
=
compose_two
(
n
,
1000000
)
1273
n
=
compose_two
(
n
,
1000
)
1274
if
n
>
0
then
1275
compose_one
(
n
)
1276
end
1277
return
#
t
>
0
and
concat
(
t
,
"
"
)
or
tostring
(
n
)
1278
end
1279 1280
data
.
english
=
{
1281
words
=
words
,
1282
translate
=
translate
,
1283
}
1284 1285
data
.
en
=
data
.
english
1286 1287
-- print(translate(11111111))
1288
-- print(translate(2221101))
1289
-- print(translate(1111))
1290
-- print(translate(1218))
1291
-- print(translate(1234))
1292
-- print(translate(12345))
1293
-- print(translate(12345678900000))
1294 1295
-- verbose spanish (unchecked)
1296 1297
local
words
=
{
1298
[
1
]
=
"
uno
"
,
1299
[
2
]
=
"
dos
"
,
1300
[
3
]
=
"
tres
"
,
1301
[
4
]
=
"
cuatro
"
,
1302
[
5
]
=
"
cinco
"
,
1303
[
6
]
=
"
seis
"
,
1304
[
7
]
=
"
siete
"
,
1305
[
8
]
=
"
ocho
"
,
1306
[
9
]
=
"
nueve
"
,
1307
[
10
]
=
"
diez
"
,
1308
[
11
]
=
"
once
"
,
1309
[
12
]
=
"
doce
"
,
1310
[
13
]
=
"
trece
"
,
1311
[
14
]
=
"
catorce
"
,
1312
[
15
]
=
"
quince
"
,
1313
[
16
]
=
"
dieciséis
"
,
1314
[
17
]
=
"
diecisiete
"
,
1315
[
18
]
=
"
dieciocho
"
,
1316
[
19
]
=
"
diecinueve
"
,
1317
[
20
]
=
"
veinte
"
,
1318
[
21
]
=
"
veintiuno
"
,
1319
[
22
]
=
"
veintidós
"
,
1320
[
23
]
=
"
veintitrés
"
,
1321
[
24
]
=
"
veinticuatro
"
,
1322
[
25
]
=
"
veinticinco
"
,
1323
[
26
]
=
"
veintiséis
"
,
1324
[
27
]
=
"
veintisiete
"
,
1325
[
28
]
=
"
veintiocho
"
,
1326
[
29
]
=
"
veintinueve
"
,
1327
[
30
]
=
"
treinta
"
,
1328
[
40
]
=
"
cuarenta
"
,
1329
[
50
]
=
"
cincuenta
"
,
1330
[
60
]
=
"
sesenta
"
,
1331
[
70
]
=
"
setenta
"
,
1332
[
80
]
=
"
ochenta
"
,
1333
[
90
]
=
"
noventa
"
,
1334
[
100
]
=
"
ciento
"
,
1335
[
200
]
=
"
doscientos
"
,
1336
[
300
]
=
"
trescientos
"
,
1337
[
400
]
=
"
cuatrocientos
"
,
1338
[
500
]
=
"
quinientos
"
,
1339
[
600
]
=
"
seiscientos
"
,
1340
[
700
]
=
"
setecientos
"
,
1341
[
800
]
=
"
ochocientos
"
,
1342
[
900
]
=
"
novecientos
"
,
1343
[
1000
]
=
"
mil
"
,
1344
[
1000000
]
=
"
millón
"
,
1345
[
1000000000
]
=
"
mil millones
"
,
1346
[
1000000000000
]
=
"
billón
"
,
1347
}
1348 1349
local
function
translate
(
n
)
1350
local
w
=
words
[
n
]
1351
if
w
then
1352
return
w
1353
end
1354
local
t
=
{
}
1355
local
function
compose_one
(
n
)
1356
local
w
=
words
[
n
]
1357
if
w
then
1358
t
[
#
t
+
1
]
=
w
1359
return
1360
end
1361
-- a, b = hundreds, remainder
1362
local
a
,
b
=
floor
(
n
/
100
)
,
n
%
100
1363
-- one thousand
1364
if
a
=
=
10
then
1365
t
[
#
t
+
1
]
=
words
[
1
]
1366
t
[
#
t
+
1
]
=
words
[
1000
]
1367
-- x hundred (n.b. this will not give thirteen hundred because
1368
-- compose_one(n) is only called after
1369
-- n = compose(two(n, 1000))
1370
elseif
a
>
0
then
1371
t
[
#
t
+
1
]
=
words
[
a
*
100
]
1372
end
1373
-- the remainder
1374
if
words
[
b
]
then
1375
t
[
#
t
+
1
]
=
words
[
b
]
1376
else
1377
-- a, b = tens, remainder
1378
a
,
b
=
floor
(
b
/
10
)
,
n
%
10
1379
t
[
#
t
+
1
]
=
words
[
a
*
10
]
1380
t
[
#
t
+
1
]
=
"
y
"
1381
t
[
#
t
+
1
]
=
words
[
b
]
1382
end
1383
end
1384
-- compose_two handles x billion, ... x thousand. When 1000 or less is
1385
-- left, compose_one takes over.
1386
local
function
compose_two
(
n
,
m
)
1387
if
n
>
(
m
-1
)
then
1388
local
a
,
b
=
floor
(
n
/
m
)
,
n
%
m
1389
if
a
>
0
then
1390
compose_one
(
a
)
1391
end
1392
t
[
#
t
+
1
]
=
words
[
m
]
1393
n
=
b
1394
end
1395
return
n
1396
end
1397
n
=
compose_two
(
n
,
1000000000000
)
1398
n
=
compose_two
(
n
,
1000000000
)
1399
n
=
compose_two
(
n
,
1000000
)
1400
n
=
compose_two
(
n
,
1000
)
1401
if
n
>
0
then
1402
compose_one
(
n
)
1403
end
1404
return
#
t
>
0
and
concat
(
t
,
"
"
)
or
tostring
(
n
)
1405
end
1406 1407
data
.
spanish
=
{
1408
words
=
words
,
1409
translate
=
translate
,
1410
}
1411 1412
data
.
es
=
data
.
spanish
1413 1414
-- print(translate(31))
1415
-- print(translate(101))
1416
-- print(translate(199))
1417 1418
-- verbose handler:
1419 1420
function
converters
.
verbose
.
translate
(
n
,
language
)
1421
local
t
=
language
and
data
[
language
]
1422
return
t
and
t
.
translate
(
n
)
or
n
1423
end
1424 1425
local
function
verbose
(
n
,
language
)
1426
local
t
=
language
and
data
[
language
]
1427
context
(
t
and
t
.
translate
(
n
)
or
n
)
1428
end
1429 1430
implement
{
1431
name
=
"
verbose
"
,
1432
actions
=
verbose
,
1433
arguments
=
{
"
integer
"
,
"
string
"
}
1434
}
1435 1436
-- These are just helpers but not really for the tex end. Do we have to
1437
-- use translate here?
1438 1439
local
whitespace
=
lpegpatterns
.
whitespace
1440
local
word
=
lpegpatterns
.
utf8uppercharacter
^
-1
*
(
1
-
whitespace
)
^
1
1441
local
pattern_one
=
Cs
(
whitespace
^
0
*
word
^
-1
*
P
(
1
)
^
0
)
1442
local
pattern_all
=
Cs
(
(
whitespace
^
1
+
word
)
^
1
)
1443 1444
function
converters
.
word
(
s
)
return
s
end
-- dummies for typos
1445
function
converters
.
words
(
s
)
return
s
end
-- dummies for typos
1446 1447
local
function
Word
(
s
)
return
lpegmatch
(
pattern_one
,
s
)
or
s
end
1448
local
function
Words
(
s
)
return
lpegmatch
(
pattern_all
,
s
)
or
s
end
1449 1450
converters
.
Word
=
Word
1451
converters
.
Words
=
Words
1452 1453
converters
.
upper
=
characters
.
upper
1454
converters
.
lower
=
characters
.
lower
1455 1456
-- print(converters.Word("foo bar"))
1457
-- print(converters.Word(" foo bar"))
1458
-- print(converters.Word("123 foo bar"))
1459
-- print(converters.Word(" 123 foo bar"))
1460 1461
-- print(converters.Words("foo bar"))
1462
-- print(converters.Words(" foo bar"))
1463
-- print(converters.Words("123 foo bar"))
1464
-- print(converters.Words(" 123 foo bar"))
1465 1466
-- --
1467 1468
local
v_day
=
variables
.
day
1469
local
v_year
=
variables
.
year
1470
local
v_month
=
variables
.
month
1471
local
v_weekday
=
variables
.
weekday
1472
local
v_referral
=
variables
.
referral
1473
local
v_space
=
variables
.
space
1474 1475
local
v_MONTH
=
upper
(
v_month
)
1476
local
v_WEEKDAY
=
upper
(
v_weekday
)
1477 1478
local
convert
=
converters
.
convert
1479 1480
local
days
=
{
-- not variables
1481
"
sunday
"
,
1482
"
monday
"
,
1483
"
tuesday
"
,
1484
"
wednesday
"
,
1485
"
thursday
"
,
1486
"
friday
"
,
1487
"
saturday
"
,
1488
}
1489 1490
local
months
=
{
-- not variables
1491
"
january
"
,
1492
"
february
"
,
1493
"
march
"
,
1494
"
april
"
,
1495
"
may
"
,
1496
"
june
"
,
1497
"
july
"
,
1498
"
august
"
,
1499
"
september
"
,
1500
"
october
"
,
1501
"
november
"
,
1502
"
december
"
,
1503
}
1504 1505
local
monthmnems
=
{
-- not variables
1506
-- virtual table
1507
}
1508 1509
local
daymnems
=
{
-- not variables
1510
-- virtual table
1511
}
1512 1513
setmetatableindex
(
days
,
function
(
t
,
k
)
return
"
unknown
"
end
)
1514
setmetatableindex
(
daymnems
,
function
(
t
,
k
)
return
days
[
k
]
.
.
"
:mnem
"
end
)
1515
setmetatableindex
(
months
,
function
(
t
,
k
)
return
"
unknown
"
end
)
1516
setmetatableindex
(
monthmnems
,
function
(
t
,
k
)
return
months
[
k
]
.
.
"
:mnem
"
end
)
1517 1518
do
1519 1520
local
function
dayname
(
n
)
1521
ctx_labeltext
(
days
[
n
]
)
1522
end
1523 1524
local
function
daymnem
(
n
)
1525
ctx_labeltext
(
daymnems
[
n
]
)
1526
end
1527 1528
local
function
weekdayname
(
day
,
month
,
year
)
1529
ctx_labeltext
(
days
[
weekday
(
day
,
month
,
year
)
]
)
1530
end
1531 1532
local
function
monthname
(
n
)
1533
ctx_labeltext
(
months
[
n
]
)
1534
end
1535 1536
local
function
monthmnem
(
n
)
1537
ctx_labeltext
(
monthmnems
[
n
]
)
1538
end
1539 1540
implement
{
1541
name
=
"
dayname
"
,
1542
actions
=
dayname
,
1543
arguments
=
"
integer
"
,
1544
}
1545 1546
implement
{
1547
name
=
"
daymnem
"
,
1548
actions
=
daymnem
,
1549
arguments
=
"
integer
"
,
1550
}
1551 1552
implement
{
1553
name
=
"
weekdayname
"
,
1554
actions
=
weekdayname
,
1555
arguments
=
{
"
integer
"
,
"
integer
"
,
"
integer
"
}
1556
}
1557 1558
implement
{
1559
name
=
"
monthname
"
,
1560
actions
=
monthname
,
1561
arguments
=
"
integer
"
,
1562
}
1563 1564
implement
{
1565
name
=
"
monthmnem
"
,
1566
actions
=
monthmnem
,
1567
arguments
=
"
integer
"
,
1568
}
1569 1570
-- todo : short week days
1571 1572
local
f_monthlong
=
formatters
[
"
\\monthlong{%s}
"
]
1573
local
f_monthshort
=
formatters
[
"
\\monthshort{%s}
"
]
1574
local
f_daylong
=
formatters
[
"
\\daylong{%s}
"
]
1575
local
f_dayshort
=
formatters
[
"
\\dayshort{%s}
"
]
1576
local
f_weekday
=
formatters
[
"
\\weekday{%s}
"
]
1577
local
f_dayoftheweek
=
formatters
[
"
\\dayoftheweek{%s}{%s}{%s}
"
]
1578 1579
local
function
tomonthlong
(
m
)
return
f_monthlong
(
tonumber
(
m
)
or
1
)
end
1580
local
function
tomonthshort
(
m
)
return
f_monthshort
(
tonumber
(
m
)
or
1
)
end
1581
local
function
todaylong
(
d
)
return
f_daylong
(
tonumber
(
d
)
or
1
)
end
1582
local
function
todayshort
(
d
)
return
f_dayshort
(
tonumber
(
d
)
or
1
)
end
1583
local
function
toweekday
(
d
)
return
f_weekday
(
tonumber
(
d
)
or
1
)
end
1584 1585
local
function
todayoftheweek
(
d
,
m
,
y
)
1586
return
f_dayoftheweek
(
tonumber
(
d
)
or
1
,
tonumber
(
m
)
or
1
,
tonumber
(
y
)
or
2000
)
1587
end
1588 1589
addformatter
(
formatters
,
"
monthlong
"
,
[[
tomonthlong(%s)
]]
,
{
tomonthlong
=
tomonthlong
}
)
1590
addformatter
(
formatters
,
"
monthshort
"
,
[[
tomonthshort(%s)
]]
,
{
tomonthshort
=
tomonthshort
}
)
1591
addformatter
(
formatters
,
"
daylong
"
,
[[
todaylong(%s)
]]
,
{
todaylong
=
todaylong
}
)
1592
addformatter
(
formatters
,
"
dayshort
"
,
[[
todayshort(%s)
]]
,
{
todayshort
=
todayshort
}
)
1593
addformatter
(
formatters
,
"
weekday
"
,
[[
toweekday(%s)
]]
,
{
toweekday
=
toweekday
}
)
1594
addformatter
(
formatters
,
"
dayoftheweek
"
,
[[
todayoftheweek(%s,%s,%s)
]]
,
{
todayoftheweek
=
todayoftheweek
}
)
1595 1596
-- using %t is slower, even with caching as we seldom use > 3 items per epoch
1597 1598
local
function
toeyear
(
e
)
return
osdate
(
"
%Y
"
,
tonumber
(
e
)
)
end
1599
local
function
toemonth
(
e
)
return
osdate
(
"
%m
"
,
tonumber
(
e
)
)
end
1600
local
function
toeday
(
e
)
return
osdate
(
"
%d
"
,
tonumber
(
e
)
)
end
1601
local
function
toeminute
(
e
)
return
osdate
(
"
%M
"
,
tonumber
(
e
)
)
end
1602
local
function
toesecond
(
e
)
return
osdate
(
"
%S
"
,
tonumber
(
e
)
)
end
1603 1604
local
function
toemonthlong
(
e
)
1605
return
f_monthlong
(
tonumber
(
osdate
(
"
%m
"
,
tonumber
(
e
)
)
)
)
1606
end
1607 1608
local
function
toemonthshort
(
e
)
1609
return
f_monthshort
(
tonumber
(
osdate
(
"
%m
"
,
tonumber
(
e
)
)
)
)
1610
end
1611 1612
local
function
toedaylong
(
e
)
1613
return
f_datlong
(
tonumber
(
osdate
(
"
%w
"
,
tonumber
(
e
)
)
)
)
1614
end
1615 1616
local
function
toedayshort
(
e
)
1617
return
f_dayshort
(
tonumber
(
osdate
(
"
%w
"
,
tonumber
(
e
)
)
)
)
1618
end
1619 1620
local
function
toeweek
(
e
)
-- we run from 1-7 not 0-6
1621
return
tostring
(
tonumber
(
osdate
(
"
%w
"
,
tonumber
(
e
)
)
)
+
1
)
1622
end
1623 1624
local
function
toeweekday
(
e
)
1625
return
f_weekday
(
tonumber
(
osdate
(
"
%w
"
,
tonumber
(
e
)
)
)
+
1
)
1626
end
1627 1628
local
function
toedate
(
format
,
e
)
1629
return
osdate
(
format
,
tonumber
(
e
)
)
1630
end
1631 1632
addformatter
(
formatters
,
"
eyear
"
,
[[
toeyear(%s)
]]
,
{
toeyear
=
toeyear
}
)
1633
addformatter
(
formatters
,
"
emonth
"
,
[[
toemonth(%s)
]]
,
{
toemonth
=
toemonth
}
)
1634
addformatter
(
formatters
,
"
eday
"
,
[[
toeday(%s)
]]
,
{
toeday
=
toeday
}
)
1635
addformatter
(
formatters
,
"
eweek
"
,
[[
toeweek(%s)
]]
,
{
toeweek
=
toeweek
}
)
1636
addformatter
(
formatters
,
"
eminute
"
,
[[
toeminute(%s)
]]
,
{
toeminute
=
toeminute
}
)
1637
addformatter
(
formatters
,
"
esecond
"
,
[[
toesecond(%s)
]]
,
{
toesecond
=
toesecond
}
)
1638 1639
addformatter
(
formatters
,
"
emonthlong
"
,
[[
toemonthlong(%s)
]]
,
{
toemonthlong
=
toemonthlong
}
)
1640
addformatter
(
formatters
,
"
emonthshort
"
,
[[
toemonthshort(%s)
]]
,
{
toemonthshort
=
toemonthshort
}
)
1641
addformatter
(
formatters
,
"
edaylong
"
,
[[
toedaylong(%s)
]]
,
{
toedaylong
=
toedaylong
}
)
1642
addformatter
(
formatters
,
"
edayshort
"
,
[[
toedayshort(%s)
]]
,
{
toedayshort
=
toedayshort
}
)
1643
addformatter
(
formatters
,
"
eweekday
"
,
[[
toeweekday(%s)
]]
,
{
toeweekday
=
toeweekday
}
)
1644 1645
addformatter
(
formatters
,
"
edate
"
,
[[
toedate(%s,%s)
]]
,
{
toedate
=
toedate
}
)
1646 1647
end
1648 1649
-- a prelude to a function that we can use at the lua end
1650 1651
-- day:ord month:mmem
1652
-- j and jj obsolete
1653 1654
local
spaced
=
{
1655
[
v_year
]
=
true
,
1656
[
v_month
]
=
true
,
1657
[
v_MONTH
]
=
true
,
1658
[
v_day
]
=
true
,
1659
[
v_weekday
]
=
true
,
1660
[
v_WEEKDAY
]
=
true
,
1661
}
1662 1663
local
dateconverters
=
{
1664
[
"
hebrew:to
"
]
=
gregorian_to_hebrew
,
1665
[
"
jalali:to
"
]
=
gregorian_to_jalali
,
1666
[
"
jalali:from
"
]
=
jalali_to_gregorian
,
1667
}
1668 1669
local
variants
=
{
1670
mnem
=
{
1671
month
=
monthmnems
,
1672
day
=
daymnems
,
1673
}
,
1674
hebrew
=
{
1675
month
=
setmetatableindex
(
function
(
t
,
k
)
return
months
[
k
]
.
.
"
:hebrew
"
end
)
,
1676
day
=
setmetatableindex
(
function
(
t
,
k
)
return
days
[
k
]
.
.
"
:hebrew
"
end
)
,
1677
}
,
1678
jalali
=
{
1679
month
=
setmetatableindex
(
function
(
t
,
k
)
return
months
[
k
]
.
.
"
:jalali
"
end
)
,
1680
day
=
setmetatableindex
(
function
(
t
,
k
)
return
days
[
k
]
.
.
"
:jalali
"
end
)
,
1681
}
,
1682
}
1683 1684
do
1685 1686
local
function
currentdate
(
str
,
currentlanguage
,
year
,
month
,
day
)
-- second argument false : no label
1687
local
list
=
utilities
.
parsers
.
settings_to_array
(
str
)
1688
local
splitlabel
=
languages
.
labels
.
split
or
string
.
itself
-- we need to get the loading order right
1689
-- local year = tex.year
1690
-- local month = tex.month
1691
-- local day = tex.day
1692
local
auto
=
true
1693
if
currentlanguage
=
=
"
"
then
1694
currentlanguage
=
false
1695
end
1696
for
i
=
1
,
#
list
do
1697
local
entry
=
list
[
i
]
1698
local
convert
=
dateconverters
[
entry
]
1699
if
convert
then
1700
year
,
month
,
day
=
convert
(
year
,
month
,
day
)
1701
else
1702
local
tag
,
plus
=
splitlabel
(
entry
)
1703
local
ordinal
,
mnemonic
,
whatordinal
,
highordinal
=
false
,
false
,
nil
,
false
1704
if
not
tag
then
1705
tag
=
entry
1706
elseif
plus
=
=
"
+
"
or
plus
=
=
"
ord
"
then
1707
ordinal
=
true
1708
elseif
plus
=
=
"
++
"
or
plus
=
=
"
highord
"
then
1709
ordinal
=
true
1710
highordinal
=
true
1711
elseif
plus
then
-- mnem MNEM etc
1712
mnemonic
=
variants
[
plus
]
1713
end
1714
if
not
auto
and
spaced
[
tag
]
then
1715
ctx_space
(
)
1716
end
1717
auto
=
false
1718
if
tag
=
=
v_year
or
tag
=
=
"
y
"
or
tag
=
=
"
Y
"
then
1719
if
plus
then
1720
plus
=
converters
[
plus
]
1721
end
1722
if
plus
then
1723
context
(
plus
(
year
)
)
1724
elseif
currentlanguage
=
=
false
then
1725
context
(
year
)
1726
else
1727
ctx_convertnumber
(
v_year
,
year
)
1728
end
1729
elseif
tag
=
=
"
yy
"
or
tag
=
=
"
YY
"
then
1730
context
(
"
%02i
"
,
year
%
100
)
1731
elseif
tag
=
=
v_month
or
tag
=
=
"
m
"
then
1732
if
currentlanguage
=
=
false
then
1733
context
(
Word
(
months
[
month
]
)
)
1734
else
1735
if
type
(
mnemonic
)
=
=
"
table
"
then
1736
mnemonic
=
mnemonic
.
month
1737
end
1738
if
mnemonic
then
1739
ctx_labeltext
(
variables
[
mnemonic
[
month
]
]
)
1740
else
1741
ctx_labeltext
(
variables
[
months
[
month
]
]
)
1742
end
1743
end
1744
elseif
tag
=
=
v_MONTH
then
1745
if
currentlanguage
=
=
false
then
1746
context
(
Word
(
variables
[
months
[
month
]
]
)
)
1747
else
1748
if
type
(
mnemonic
)
=
=
"
table
"
then
1749
mnemonic
=
mnemonic
.
month
1750
end
1751
if
mnemonic
then
1752
ctx_LABELTEXT
(
variables
[
mnemonic
[
month
]
]
)
1753
else
1754
ctx_LABELTEXT
(
variables
[
months
[
month
]
]
)
1755
end
1756
end
1757
elseif
tag
=
=
"
mm
"
then
1758
context
(
"
%02i
"
,
month
)
1759
elseif
tag
=
=
"
M
"
then
1760
context
(
month
)
1761
elseif
tag
=
=
v_day
or
tag
=
=
"
d
"
then
1762
if
plus
then
1763
plus
=
converters
[
plus
]
1764
end
1765
if
plus
then
1766
context
(
plus
(
day
)
)
1767
elseif
currentlanguage
=
=
false
then
1768
context
(
day
)
1769
else
1770
ctx_convertnumber
(
v_day
,
day
)
1771
end
1772
whatordinal
=
day
1773
elseif
tag
=
=
"
dd
"
then
1774
context
(
"
%02i
"
,
day
)
1775
whatordinal
=
day
1776
elseif
tag
=
=
"
D
"
then
1777
context
(
day
)
1778
whatordinal
=
day
1779
elseif
tag
=
=
v_weekday
or
tag
=
=
"
w
"
then
1780
local
wd
=
weekday
(
day
,
month
,
year
)
1781
if
currentlanguage
=
=
false
then
1782
context
(
Word
(
days
[
wd
]
)
)
1783
else
1784
if
type
(
mnemonic
)
=
=
"
table
"
then
1785
mnemonic
=
mnemonic
.
day
1786
end
1787
if
mnemonic
then
1788
ctx_labeltext
(
variables
[
mnemonic
[
wd
]
]
)
1789
else
1790
ctx_labeltext
(
variables
[
days
[
wd
]
]
)
1791
end
1792
end
1793
elseif
tag
=
=
v_WEEKDAY
then
1794
local
wd
=
weekday
(
day
,
month
,
year
)
1795
if
currentlanguage
=
=
false
then
1796
context
(
Word
(
days
[
wd
]
)
)
1797
else
1798
if
type
(
mnemonic
)
=
=
"
table
"
then
1799
mnemonic
=
mnemonic
.
day
1800
end
1801
if
mnemonic
then
1802
ctx_LABELTEXT
(
variables
[
mnemonic
[
wd
]
]
)
1803
else
1804
ctx_LABELTEXT
(
variables
[
days
[
wd
]
]
)
1805
end
1806
end
1807
elseif
tag
=
=
"
W
"
then
1808
context
(
weekday
(
day
,
month
,
year
)
)
1809
elseif
tag
=
=
v_referral
then
1810
context
(
"
%04i%02i%02i
"
,
year
,
month
,
day
)
1811
elseif
tag
=
=
v_space
or
tag
=
=
"
\\
"
then
1812
ctx_space
(
)
1813
auto
=
true
1814
elseif
tag
~
=
"
"
then
1815
context
(
tag
)
1816
auto
=
true
1817
end
1818
if
ordinal
and
whatordinal
then
1819
if
currentlanguage
=
=
false
then
1820
-- ignore
1821
else
1822
context
[
highordinal
and
"
highordinalstr
"
or
"
ordinalstr
"
]
(
converters
.
ordinal
(
whatordinal
,
currentlanguage
)
)
1823
end
1824
end
1825
end
1826
end
1827
end
1828 1829
implement
{
1830
name
=
"
currentdate
"
,
1831
arguments
=
{
"
string
"
,
"
string
"
,
"
string
"
,
"
integer
"
,
"
integer
"
,
"
integer
"
}
,
1832
actions
=
function
(
pattern
,
default
,
language
,
year
,
month
,
day
)
1833
currentdate
(
1834
pattern
=
=
"
"
and
default
or
pattern
,
1835
language
=
=
"
"
and
false
or
language
,
1836
year
,
month
,
day
1837
)
1838
end
,
1839
}
1840 1841
local
function
todate
(
s
,
y
,
m
,
d
)
1842
if
y
or
m
or
d
then
1843
return
formatters
[
"
\\date[y=%s,m=%s,d=%s][%s]\\relax
"
]
(
y
or
"
"
,
m
or
"
"
,
d
or
"
"
,
s
or
"
"
)
1844
else
1845
return
formatters
[
"
\\currentdate[%s]\\relax
"
]
(
s
)
1846
end
1847
end
1848 1849
addformatter
(
formatters
,
"
date
"
,
[[
todate(...)
]]
,
{
todate
=
todate
}
)
1850 1851
-- context("one: %4!date!","MONTH",2020,12,11) context.par()
1852
-- context("one: %4!date!","month",2020,12,11) context.par()
1853
-- context("one: %4!date!","year,-,mm,-,dd",2020,12,11) context.par()
1854 1855
-- context("two: %3!date!","MONTH",false,12) context.par()
1856
-- context("two: %3!date!","month",false,12) context.par()
1857
-- context("two: %3!date!","year,-,mm,-,dd",false,12) context.par()
1858 1859
end
1860 1861
implement
{
1862
name
=
"
unihex
"
,
1863
arguments
=
"
integer
"
,
1864
actions
=
{
formatters
[
"
U+%05X
"
]
,
context
}
,
1865
}
1866 1867
local
n
=
R
(
"
09
"
)
^
1
/
tonumber
1868 1869
local
p
=
Cf
(
Ct
(
"
"
)
1870
*
Cg
(
Cc
(
"
year
"
)
*
(
n
)
)
*
P
(
"
-
"
)
^
-1
1871
*
Cg
(
Cc
(
"
month
"
)
*
(
n
+
Cc
(
1
)
)
)
*
P
(
"
-
"
)
^
-1
1872
*
Cg
(
Cc
(
"
day
"
)
*
(
n
+
Cc
(
1
)
)
)
*
whitespace
^
-1
1873
*
Cg
(
Cc
(
"
hour
"
)
*
(
n
+
Cc
(
0
)
)
)
*
P
(
"
:
"
)
^
-1
1874
*
Cg
(
Cc
(
"
min
"
)
*
(
n
+
Cc
(
0
)
)
)
1875
,
rawset
)
1876 1877
function
converters
.
totime
(
s
)
1878
if
not
s
then
1879
return
1880
elseif
type
(
s
)
=
=
"
table
"
then
1881
return
s
1882
elseif
type
(
s
)
=
=
"
string
"
then
1883
return
lpegmatch
(
p
,
s
)
1884
end
1885
local
n
=
tonumber
(
s
)
1886
if
n
and
n
>
=
0
then
1887
return
date
(
"
*t
"
,
n
)
1888
end
1889
end
1890 1891
function
converters
.
settime
(
t
)
1892
if
type
(
t
)
~
=
"
table
"
then
1893
t
=
converters
.
totime
(
t
)
1894
end
1895
if
t
then
1896
texset
(
"
year
"
,
t
.
year
or
1000
)
1897
texset
(
"
month
"
,
t
.
month
or
1
)
1898
texset
(
"
day
"
,
t
.
day
or
1
)
1899
texset
(
"
time
"
,
(
t
.
hour
or
0
)
*
60
+
(
t
.
min
or
0
)
)
1900
end
1901
end
1902 1903
-- taken from x-asciimath (where we needed it for a project)
1904 1905
local
d_one
=
lpegpatterns
.
digit
1906
local
d_two
=
d_one
*
d_one
1907
local
d_three
=
d_two
*
d_one
1908
local
d_four
=
d_three
*
d_one
1909
local
d_split
=
P
(
-1
)
+
Carg
(
2
)
*
(
lpegpatterns
.
period
/
"
"
)
1910 1911
local
d_spaced
=
(
Carg
(
1
)
*
d_three
)
^
1
1912 1913
local
digitized_1
=
Cs
(
(
1914
d_three
*
d_spaced
*
d_split
+
1915
d_two
*
d_spaced
*
d_split
+
1916
d_one
*
d_spaced
*
d_split
+
1917
P
(
1
)
1918
)
^
1
)
1919 1920
local
p_fourbefore
=
d_four
*
d_split
1921
local
p_fourafter
=
d_four
*
P
(
-1
)
1922 1923
local
p_beforesplit
=
d_three
*
d_spaced
^
0
*
d_split
1924
+
d_two
*
d_spaced
^
0
*
d_split
1925
+
d_one
*
d_spaced
^
0
*
d_split
1926
+
d_one
*
d_split
1927 1928
local
p_aftersplit
=
p_fourafter
1929
+
d_three
*
d_spaced
1930
+
d_two
*
d_spaced
1931
+
d_one
*
d_spaced
1932 1933
local
digitized_2
=
Cs
(
1934
p_fourbefore
*
(
p_aftersplit
^
0
)
+
1935
p_beforesplit
*
(
(
p_aftersplit
+
d_one
^
1
)
^
0
)
1936
)
1937 1938
local
p_fourbefore
=
d_four
*
d_split
1939
local
p_fourafter
=
d_four
1940
local
d_spaced
=
(
Carg
(
1
)
*
(
d_three
+
d_two
+
d_one
)
)
^
1
1941
local
p_aftersplit
=
p_fourafter
*
P
(
-1
)
1942
+
d_three
*
d_spaced
*
P
(
1
)
^
0
1943
+
d_one
^
1
1944 1945
local
digitized_3
=
Cs
(
(
p_fourbefore
+
p_beforesplit
)
*
p_aftersplit
^
0
)
1946 1947
local
digits_space
=
utfchar
(
0x2008
)
1948 1949
local
splitmethods
=
{
1950
digitized_1
,
1951
digitized_2
,
1952
digitized_3
,
1953
}
1954 1955
local
replacers
=
table
.
setmetatableindex
(
function
(
t
,
k
)
1956
local
v
=
lpeg
.
replacer
(
"
.
"
,
k
)
1957
t
[
k
]
=
v
1958
return
v
1959
end
)
1960 1961
function
converters
.
spaceddigits
(
settings
,
data
)
1962
local
data
=
tostring
(
data
or
settings
.
data
or
"
"
)
1963
if
data
~
=
"
"
then
1964
local
method
=
settings
.
method
1965
local
split
=
splitmethods
[
tonumber
(
method
)
or
1
]
1966
if
split
then
1967
local
symbol
=
settings
.
symbol
1968
local
separator
=
settings
.
separator
1969
if
not
symbol
or
symbol
=
=
"
"
then
1970
symbol
=
"
.
"
1971
end
1972
if
type
(
separator
)
~
=
"
string
"
or
separator
=
=
"
"
then
1973
separator
=
digits_space
1974
end
1975
local
result
=
lpegmatch
(
split
,
data
,
1
,
separator
,
symbol
)
1976
if
not
result
and
symbol
~
=
"
.
"
then
1977
result
=
lpegmatch
(
replacers
[
symbol
]
,
data
)
1978
end
1979
if
result
then
1980
-- print(method,symbol,separator,data,result)
1981
return
result
1982
end
1983
end
1984
end
1985
return
str
1986
end
1987 1988
-- method 2 : split 3 before and 3 after
1989
-- method 3 : split 3 before and 3 after with > 4 before
1990 1991
-- symbols is extra split (in addition to period)
1992 1993
-- local setup = { splitmethod = 3, symbol = "," }
1994
-- local setup = { splitmethod = 2, symbol = "," }
1995
-- local setup = { splitmethod = 1, symbol = "," }
1996
--
1997
-- local t = {
1998
-- "0.00002",
1999
-- "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678", "123456789",
2000
-- "1.1",
2001
-- "12.12",
2002
-- "123.123",
2003
-- "1234.123",
2004
-- "1234.1234",
2005
-- "12345.1234",
2006
-- "1234.12345",
2007
-- "12345.12345",
2008
-- "123456.123456",
2009
-- "1234567.1234567",
2010
-- "12345678.12345678",
2011
-- "123456789.123456789",
2012
-- "0.1234",
2013
-- "1234.0",
2014
-- "1234.00",
2015
-- "0.123456789",
2016
-- "100.00005",
2017
-- "0.80018",
2018
-- "10.80018",
2019
-- "100.80018",
2020
-- "1000.80018",
2021
-- "10000.80018",
2022
-- }
2023
--
2024
-- for i=1,#t do
2025
-- print(formatters["%-20s : [%s]"](t[i],converters.spaceddigits(setup,t[i])))
2026
-- end
2027 2028
implement
{
2029
name
=
"
spaceddigits
"
,
2030
actions
=
{
converters
.
spaceddigits
,
context
}
,
2031
arguments
=
{
2032
{
2033
{
"
symbol
"
}
,
2034
{
"
separator
"
}
,
2035
{
"
data
"
}
,
2036
{
"
method
"
}
,
2037
}
2038
}
2039
}
2040 2041
local
function
field
(
n
)
return
context
(
osdate
(
"
*t
"
)
[
n
]
)
end
2042 2043
implement
{
name
=
"
actualday
"
,
public
=
true
,
actions
=
function
(
)
field
(
"
day
"
)
end
}
2044
implement
{
name
=
"
actualmonth
"
,
public
=
true
,
actions
=
function
(
)
field
(
"
month
"
)
end
}
2045
implement
{
name
=
"
actualyear
"
,
public
=
true
,
actions
=
function
(
)
field
(
"
year
"
)
end
}
2046