core-con.lua /size: 68 Kb    last modification: 2021-10-28 13:50
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
,
ostimezone
=
os
.
date
,
os
.
time
,
os
.
timezone
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
else
1156
return
"
e
"
1157
end
1158
end
,
1159
}
1160 1161
ordinals
.
en
=
ordinals
.
english
1162
ordinals
.
nl
=
ordinals
.
dutch
1163
ordinals
.
fr
=
ordinals
.
french
1164 1165
function
converters
.
ordinal
(
n
,
language
)
1166
local
t
=
language
and
ordinals
[
language
]
1167
return
t
and
t
(
n
)
1168
end
1169 1170
local
function
ctxordinal
(
n
,
language
)
1171
local
t
=
language
and
ordinals
[
language
]
1172
local
o
=
t
and
t
(
n
)
1173
context
(
n
)
1174
if
o
then
1175
ctx_highordinalstr
(
o
)
1176
end
1177
end
1178 1179
implement
{
1180
name
=
"
ordinal
"
,
1181
actions
=
ctxordinal
,
1182
arguments
=
{
"
integer
"
,
"
string
"
}
1183
}
1184 1185
-- verbose numbers
1186 1187
local
data
=
allocate
(
)
1188
local
verbose
=
{
data
=
data
}
1189
converters
.
verbose
=
verbose
1190 1191
-- verbose english
1192 1193
local
words
=
{
1194
[
0
]
=
"
zero
"
,
1195
[
1
]
=
"
one
"
,
1196
[
2
]
=
"
two
"
,
1197
[
3
]
=
"
three
"
,
1198
[
4
]
=
"
four
"
,
1199
[
5
]
=
"
five
"
,
1200
[
6
]
=
"
six
"
,
1201
[
7
]
=
"
seven
"
,
1202
[
8
]
=
"
eight
"
,
1203
[
9
]
=
"
nine
"
,
1204
[
10
]
=
"
ten
"
,
1205
[
11
]
=
"
eleven
"
,
1206
[
12
]
=
"
twelve
"
,
1207
[
13
]
=
"
thirteen
"
,
1208
[
14
]
=
"
fourteen
"
,
1209
[
15
]
=
"
fifteen
"
,
1210
[
16
]
=
"
sixteen
"
,
1211
[
17
]
=
"
seventeen
"
,
1212
[
18
]
=
"
eighteen
"
,
1213
[
19
]
=
"
nineteen
"
,
1214
[
20
]
=
"
twenty
"
,
1215
[
30
]
=
"
thirty
"
,
1216
[
40
]
=
"
forty
"
,
1217
[
50
]
=
"
fifty
"
,
1218
[
60
]
=
"
sixty
"
,
1219
[
70
]
=
"
seventy
"
,
1220
[
80
]
=
"
eighty
"
,
1221
[
90
]
=
"
ninety
"
,
1222
[
100
]
=
"
hundred
"
,
1223
[
1000
]
=
"
thousand
"
,
1224
[
1000000
]
=
"
million
"
,
1225
[
1000000000
]
=
"
billion
"
,
1226
[
1000000000000
]
=
"
trillion
"
,
1227
}
1228 1229
local
function
translate
(
n
,
connector
)
1230
local
w
=
words
[
n
]
1231
if
w
then
1232
return
w
1233
end
1234
local
t
=
{
}
1235
local
function
compose_one
(
n
)
1236
local
w
=
words
[
n
]
1237
if
w
then
1238
t
[
#
t
+
1
]
=
w
1239
return
1240
end
1241
local
a
,
b
=
floor
(
n
/
100
)
,
n
%
100
1242
if
a
=
=
10
then
1243
t
[
#
t
+
1
]
=
words
[
1
]
1244
t
[
#
t
+
1
]
=
words
[
1000
]
1245
elseif
a
>
0
then
1246
t
[
#
t
+
1
]
=
words
[
a
]
1247
t
[
#
t
+
1
]
=
words
[
100
]
1248
-- don't say 'nine hundred zero'
1249
if
b
=
=
0
then
1250
return
1251
end
1252
end
1253
if
words
[
b
]
then
1254
t
[
#
t
+
1
]
=
words
[
b
]
1255
else
1256
a
,
b
=
floor
(
b
/
10
)
,
n
%
10
1257
t
[
#
t
+
1
]
=
words
[
a
*
10
]
1258
t
[
#
t
+
1
]
=
words
[
b
]
1259
end
1260
end
1261
local
function
compose_two
(
n
,
m
)
1262
if
n
>
(
m
-1
)
then
1263
local
a
,
b
=
floor
(
n
/
m
)
,
n
%
m
1264
if
a
>
0
then
1265
compose_one
(
a
)
1266
end
1267
t
[
#
t
+
1
]
=
words
[
m
]
1268
n
=
b
1269
end
1270
return
n
1271
end
1272
n
=
compose_two
(
n
,
1000000000000
)
1273
n
=
compose_two
(
n
,
1000000000
)
1274
n
=
compose_two
(
n
,
1000000
)
1275
n
=
compose_two
(
n
,
1000
)
1276
if
n
>
0
then
1277
compose_one
(
n
)
1278
end
1279
return
#
t
>
0
and
concat
(
t
,
connector
or
"
"
)
or
tostring
(
n
)
1280
end
1281 1282
data
.
english
=
{
1283
words
=
words
,
1284
translate
=
translate
,
1285
}
1286 1287
data
.
en
=
data
.
english
1288 1289
-- print(translate(11111111))
1290
-- print(translate(2221101))
1291
-- print(translate(1111))
1292
-- print(translate(1218))
1293
-- print(translate(1234))
1294
-- print(translate(12345))
1295
-- print(translate(12345678900000))
1296 1297
-- verbose spanish (unchecked)
1298 1299
local
words
=
{
1300
[
1
]
=
"
uno
"
,
1301
[
2
]
=
"
dos
"
,
1302
[
3
]
=
"
tres
"
,
1303
[
4
]
=
"
cuatro
"
,
1304
[
5
]
=
"
cinco
"
,
1305
[
6
]
=
"
seis
"
,
1306
[
7
]
=
"
siete
"
,
1307
[
8
]
=
"
ocho
"
,
1308
[
9
]
=
"
nueve
"
,
1309
[
10
]
=
"
diez
"
,
1310
[
11
]
=
"
once
"
,
1311
[
12
]
=
"
doce
"
,
1312
[
13
]
=
"
trece
"
,
1313
[
14
]
=
"
catorce
"
,
1314
[
15
]
=
"
quince
"
,
1315
[
16
]
=
"
dieciséis
"
,
1316
[
17
]
=
"
diecisiete
"
,
1317
[
18
]
=
"
dieciocho
"
,
1318
[
19
]
=
"
diecinueve
"
,
1319
[
20
]
=
"
veinte
"
,
1320
[
21
]
=
"
veintiuno
"
,
1321
[
22
]
=
"
veintidós
"
,
1322
[
23
]
=
"
veintitrés
"
,
1323
[
24
]
=
"
veinticuatro
"
,
1324
[
25
]
=
"
veinticinco
"
,
1325
[
26
]
=
"
veintiséis
"
,
1326
[
27
]
=
"
veintisiete
"
,
1327
[
28
]
=
"
veintiocho
"
,
1328
[
29
]
=
"
veintinueve
"
,
1329
[
30
]
=
"
treinta
"
,
1330
[
40
]
=
"
cuarenta
"
,
1331
[
50
]
=
"
cincuenta
"
,
1332
[
60
]
=
"
sesenta
"
,
1333
[
70
]
=
"
setenta
"
,
1334
[
80
]
=
"
ochenta
"
,
1335
[
90
]
=
"
noventa
"
,
1336
[
100
]
=
"
ciento
"
,
1337
[
200
]
=
"
doscientos
"
,
1338
[
300
]
=
"
trescientos
"
,
1339
[
400
]
=
"
cuatrocientos
"
,
1340
[
500
]
=
"
quinientos
"
,
1341
[
600
]
=
"
seiscientos
"
,
1342
[
700
]
=
"
setecientos
"
,
1343
[
800
]
=
"
ochocientos
"
,
1344
[
900
]
=
"
novecientos
"
,
1345
[
1000
]
=
"
mil
"
,
1346
[
1000000
]
=
"
millón
"
,
1347
[
1000000000
]
=
"
mil millones
"
,
1348
[
1000000000000
]
=
"
billón
"
,
1349
}
1350 1351
local
function
translate
(
n
,
connector
)
1352
local
w
=
words
[
n
]
1353
if
w
then
1354
return
w
1355
end
1356
local
t
=
{
}
1357
local
function
compose_one
(
n
)
1358
local
w
=
words
[
n
]
1359
if
w
then
1360
t
[
#
t
+
1
]
=
w
1361
return
1362
end
1363
-- a, b = hundreds, remainder
1364
local
a
,
b
=
floor
(
n
/
100
)
,
n
%
100
1365
-- one thousand
1366
if
a
=
=
10
then
1367
t
[
#
t
+
1
]
=
words
[
1
]
1368
t
[
#
t
+
1
]
=
words
[
1000
]
1369
-- x hundred (n.b. this will not give thirteen hundred because
1370
-- compose_one(n) is only called after
1371
-- n = compose(two(n, 1000))
1372
elseif
a
>
0
then
1373
t
[
#
t
+
1
]
=
words
[
a
*
100
]
1374
end
1375
-- the remainder
1376
if
words
[
b
]
then
1377
t
[
#
t
+
1
]
=
words
[
b
]
1378
else
1379
-- a, b = tens, remainder
1380
a
,
b
=
floor
(
b
/
10
)
,
n
%
10
1381
t
[
#
t
+
1
]
=
words
[
a
*
10
]
1382
t
[
#
t
+
1
]
=
"
y
"
1383
t
[
#
t
+
1
]
=
words
[
b
]
1384
end
1385
end
1386
-- compose_two handles x billion, ... x thousand. When 1000 or less is
1387
-- left, compose_one takes over.
1388
local
function
compose_two
(
n
,
m
)
1389
if
n
>
(
m
-1
)
then
1390
local
a
,
b
=
floor
(
n
/
m
)
,
n
%
m
1391
if
a
>
0
then
1392
compose_one
(
a
)
1393
end
1394
t
[
#
t
+
1
]
=
words
[
m
]
1395
n
=
b
1396
end
1397
return
n
1398
end
1399
n
=
compose_two
(
n
,
1000000000000
)
1400
n
=
compose_two
(
n
,
1000000000
)
1401
n
=
compose_two
(
n
,
1000000
)
1402
n
=
compose_two
(
n
,
1000
)
1403
if
n
>
0
then
1404
compose_one
(
n
)
1405
end
1406
return
#
t
>
0
and
concat
(
t
,
connector
or
"
"
)
or
tostring
(
n
)
1407
end
1408 1409
data
.
spanish
=
{
1410
words
=
words
,
1411
translate
=
translate
,
1412
}
1413 1414
data
.
es
=
data
.
spanish
1415 1416
-- print(translate(31))
1417
-- print(translate(101))
1418
-- print(translate(199))
1419 1420
-- verbose swedish by Peter Kvillegard
1421 1422
do
1423 1424
local
words
=
{
1425
[
0
]
=
"
noll
"
,
1426
[
1
]
=
"
ett
"
,
1427
[
2
]
=
"
två
"
,
1428
[
3
]
=
"
tre
"
,
1429
[
4
]
=
"
fyra
"
,
1430
[
5
]
=
"
fem
"
,
1431
[
6
]
=
"
sex
"
,
1432
[
7
]
=
"
sju
"
,
1433
[
8
]
=
"
åtta
"
,
1434
[
9
]
=
"
nio
"
,
1435
[
10
]
=
"
tio
"
,
1436
[
11
]
=
"
elva
"
,
1437
[
12
]
=
"
tolv
"
,
1438
[
13
]
=
"
tretton
"
,
1439
[
14
]
=
"
fjorton
"
,
1440
[
15
]
=
"
femton
"
,
1441
[
16
]
=
"
sexton
"
,
1442
[
17
]
=
"
sjutton
"
,
1443
[
18
]
=
"
arton
"
,
1444
[
19
]
=
"
nitton
"
,
1445
[
20
]
=
"
tjugo
"
,
1446
[
30
]
=
"
trettio
"
,
1447
[
40
]
=
"
fyrtio
"
,
1448
[
50
]
=
"
femtio
"
,
1449
[
60
]
=
"
sextio
"
,
1450
[
70
]
=
"
sjuttio
"
,
1451
[
80
]
=
"
åttio
"
,
1452
[
90
]
=
"
nittio
"
,
1453
[
100
]
=
"
hundra
"
,
1454
[
10
^
3
]
=
"
tusen
"
,
1455
[
10
^
6
]
=
"
miljon
"
,
1456
[
10
^
9
]
=
"
miljard
"
,
1457
[
10
^
12
]
=
"
biljon
"
,
1458
[
10
^
15
]
=
"
biljard
"
,
1459
}
1460 1461
local
function
translate
(
n
,
connector
)
1462
local
w
=
words
[
n
]
1463
if
w
then
1464
return
w
1465
else
1466
local
t
=
{
}
1467
local
l
=
0
1468
-- group of three digits to words, e.g. 123 -> etthundratjugotre
1469
local
function
triplets
(
n
)
1470
if
floor
(
n
/
100
)
>
0
then
1471
l
=
l
+
1
;
t
[
l
]
=
words
[
floor
(
n
/
100
)
]
1472
l
=
l
+
1
;
t
[
l
]
=
words
[
100
]
1473
end
1474
if
n
%
100
>
20
then
1475
l
=
l
+
1
;
t
[
l
]
=
words
[
n
%
100
-
n
%
10
]
1476
if
n
%
10
>
0
then
1477
l
=
l
+
1
;
t
[
l
]
=
words
[
n
%
10
]
1478
end
1479
elseif
n
%
100
>
0
then
1480
l
=
l
+
1
;
t
[
l
]
=
words
[
n
%
100
]
1481
end
1482
end
1483
-- loops through 10^15,10^12,...10^3, extracting groups of three digits
1484
-- to make words from, then adding names for order of magnitude
1485
for
i
=
15
,
3
,
-3
do
1486
local
triplet
=
floor
(
n
/
10
^
i
)
%
10
^
3
1487
if
triplet
>
0
then
1488
-- grammar: "en" instead of "ett"
1489
if
i
>
3
and
triplet
=
=
1
then
1490
l
=
l
+
1
;
t
[
l
]
=
"
en
"
1491
else
1492
triplets
(
triplet
)
1493
end
1494
-- grammar: plural form of "millions" etc
1495
l
=
l
+
1
;
t
[
l
]
=
words
[
10
^
i
]
1496
if
i
>
3
and
triplet
>
1
then
1497
l
=
l
+
1
;
t
[
l
]
=
"
er
"
1498
end
1499
end
1500
end
1501
-- add last group of three numbers (no word for magnitude)
1502
n
=
n
%
1000
1503
if
n
>
0
then
1504
triplets
(
n
)
1505
end
1506
t
=
concat
(
t
,
"
"
)
1507
-- grammar: spacing for numbers < 10^6 and repeated letters
1508
if
n
<
10
^
6
then
1509
t
=
gsub
(
t
,
"
%stusen%s
"
,
"
tusen
"
)
1510
t
=
gsub
(
t
,
"
etttusen
"
,
"
ettusen
"
)
1511
end
1512
return
t
1513
end
1514
end
1515 1516
data
.
swedish
=
{
1517
words
=
words
,
1518
translate
=
translate
,
1519
}
1520 1521
data
.
sv
=
data
.
swedish
1522 1523
end
1524 1525
-- verbose handler:
1526 1527
function
converters
.
verbose
.
translate
(
n
,
language
,
connector
)
1528
local
t
=
language
and
data
[
language
]
1529
return
t
and
t
.
translate
(
n
,
connector
)
or
n
1530
end
1531 1532
local
function
verbose
(
n
,
language
,
connector
)
1533
local
t
=
language
and
data
[
language
]
1534
context
(
t
and
t
.
translate
(
n
,
connector
)
or
n
)
1535
end
1536 1537
implement
{
1538
name
=
"
verbose
"
,
1539
actions
=
verbose
,
1540
arguments
=
{
"
integer
"
,
"
string
"
,
"
string
"
}
1541
}
1542 1543
-- These are just helpers but not really for the tex end. Do we have to
1544
-- use translate here?
1545 1546
local
whitespace
=
lpegpatterns
.
whitespace
1547
local
word
=
lpegpatterns
.
utf8uppercharacter
^
-1
*
(
1
-
whitespace
)
^
1
1548
local
pattern_one
=
Cs
(
whitespace
^
0
*
word
^
-1
*
P
(
1
)
^
0
)
1549
local
pattern_all
=
Cs
(
(
whitespace
^
1
+
word
)
^
1
)
1550 1551
function
converters
.
word
(
s
)
return
s
end
-- dummies for typos
1552
function
converters
.
words
(
s
)
return
s
end
-- dummies for typos
1553 1554
local
function
Word
(
s
)
return
lpegmatch
(
pattern_one
,
s
)
or
s
end
1555
local
function
Words
(
s
)
return
lpegmatch
(
pattern_all
,
s
)
or
s
end
1556 1557
converters
.
Word
=
Word
1558
converters
.
Words
=
Words
1559 1560
converters
.
upper
=
characters
.
upper
1561
converters
.
lower
=
characters
.
lower
1562 1563
-- print(converters.Word("foo bar"))
1564
-- print(converters.Word(" foo bar"))
1565
-- print(converters.Word("123 foo bar"))
1566
-- print(converters.Word(" 123 foo bar"))
1567 1568
-- print(converters.Words("foo bar"))
1569
-- print(converters.Words(" foo bar"))
1570
-- print(converters.Words("123 foo bar"))
1571
-- print(converters.Words(" 123 foo bar"))
1572 1573
-- --
1574 1575
local
v_day
=
variables
.
day
1576
local
v_year
=
variables
.
year
1577
local
v_month
=
variables
.
month
1578
local
v_weekday
=
variables
.
weekday
1579
local
v_referral
=
variables
.
referral
1580
local
v_space
=
variables
.
space
1581 1582
local
v_MONTH
=
upper
(
v_month
)
1583
local
v_WEEKDAY
=
upper
(
v_weekday
)
1584 1585
local
convert
=
converters
.
convert
1586 1587
local
days
=
{
-- not variables
1588
"
sunday
"
,
1589
"
monday
"
,
1590
"
tuesday
"
,
1591
"
wednesday
"
,
1592
"
thursday
"
,
1593
"
friday
"
,
1594
"
saturday
"
,
1595
}
1596 1597
local
months
=
{
-- not variables
1598
"
january
"
,
1599
"
february
"
,
1600
"
march
"
,
1601
"
april
"
,
1602
"
may
"
,
1603
"
june
"
,
1604
"
july
"
,
1605
"
august
"
,
1606
"
september
"
,
1607
"
october
"
,
1608
"
november
"
,
1609
"
december
"
,
1610
}
1611 1612
local
monthmnems
=
{
-- not variables
1613
-- virtual table
1614
}
1615 1616
local
daymnems
=
{
-- not variables
1617
-- virtual table
1618
}
1619 1620
setmetatableindex
(
days
,
function
(
t
,
k
)
return
"
unknown
"
end
)
1621
setmetatableindex
(
daymnems
,
function
(
t
,
k
)
return
days
[
k
]
.
.
"
:mnem
"
end
)
1622
setmetatableindex
(
months
,
function
(
t
,
k
)
return
"
unknown
"
end
)
1623
setmetatableindex
(
monthmnems
,
function
(
t
,
k
)
return
months
[
k
]
.
.
"
:mnem
"
end
)
1624 1625
do
1626 1627
local
function
dayname
(
n
)
1628
ctx_labeltext
(
days
[
n
]
)
1629
end
1630 1631
local
function
daymnem
(
n
)
1632
ctx_labeltext
(
daymnems
[
n
]
)
1633
end
1634 1635
local
function
weekdayname
(
day
,
month
,
year
)
1636
ctx_labeltext
(
days
[
weekday
(
day
,
month
,
year
)
]
)
1637
end
1638 1639
local
function
monthname
(
n
)
1640
ctx_labeltext
(
months
[
n
]
)
1641
end
1642 1643
local
function
monthmnem
(
n
)
1644
ctx_labeltext
(
monthmnems
[
n
]
)
1645
end
1646 1647
implement
{
1648
name
=
"
dayname
"
,
1649
actions
=
dayname
,
1650
arguments
=
"
integer
"
,
1651
}
1652 1653
implement
{
1654
name
=
"
daymnem
"
,
1655
actions
=
daymnem
,
1656
arguments
=
"
integer
"
,
1657
}
1658 1659
implement
{
1660
name
=
"
weekdayname
"
,
1661
actions
=
weekdayname
,
1662
arguments
=
{
"
integer
"
,
"
integer
"
,
"
integer
"
}
1663
}
1664 1665
implement
{
1666
name
=
"
monthname
"
,
1667
actions
=
monthname
,
1668
arguments
=
"
integer
"
,
1669
}
1670 1671
implement
{
1672
name
=
"
monthmnem
"
,
1673
actions
=
monthmnem
,
1674
arguments
=
"
integer
"
,
1675
}
1676 1677
-- todo : short week days
1678 1679
local
f_monthlong
=
formatters
[
"
\\monthlong{%s}
"
]
1680
local
f_monthshort
=
formatters
[
"
\\monthshort{%s}
"
]
1681
local
f_daylong
=
formatters
[
"
\\daylong{%s}
"
]
1682
local
f_dayshort
=
formatters
[
"
\\dayshort{%s}
"
]
1683
local
f_weekday
=
formatters
[
"
\\weekday{%s}
"
]
1684
local
f_dayoftheweek
=
formatters
[
"
\\dayoftheweek{%s}{%s}{%s}
"
]
1685 1686
local
function
tomonthlong
(
m
)
return
f_monthlong
(
tonumber
(
m
)
or
1
)
end
1687
local
function
tomonthshort
(
m
)
return
f_monthshort
(
tonumber
(
m
)
or
1
)
end
1688
local
function
todaylong
(
d
)
return
f_daylong
(
tonumber
(
d
)
or
1
)
end
1689
local
function
todayshort
(
d
)
return
f_dayshort
(
tonumber
(
d
)
or
1
)
end
1690
local
function
toweekday
(
d
)
return
f_weekday
(
tonumber
(
d
)
or
1
)
end
1691 1692
local
function
todayoftheweek
(
d
,
m
,
y
)
1693
return
f_dayoftheweek
(
tonumber
(
d
)
or
1
,
tonumber
(
m
)
or
1
,
tonumber
(
y
)
or
2000
)
1694
end
1695 1696
addformatter
(
formatters
,
"
monthlong
"
,
[[
tomonthlong(%s)
]]
,
{
tomonthlong
=
tomonthlong
}
)
1697
addformatter
(
formatters
,
"
monthshort
"
,
[[
tomonthshort(%s)
]]
,
{
tomonthshort
=
tomonthshort
}
)
1698
addformatter
(
formatters
,
"
daylong
"
,
[[
todaylong(%s)
]]
,
{
todaylong
=
todaylong
}
)
1699
addformatter
(
formatters
,
"
dayshort
"
,
[[
todayshort(%s)
]]
,
{
todayshort
=
todayshort
}
)
1700
addformatter
(
formatters
,
"
weekday
"
,
[[
toweekday(%s)
]]
,
{
toweekday
=
toweekday
}
)
1701
addformatter
(
formatters
,
"
dayoftheweek
"
,
[[
todayoftheweek(%s,%s,%s)
]]
,
{
todayoftheweek
=
todayoftheweek
}
)
1702 1703
-- using %t is slower, even with caching as we seldom use > 3 items per epoch
1704 1705
local
function
toeyear
(
e
)
return
osdate
(
"
%Y
"
,
tonumber
(
e
)
)
end
1706
local
function
toemonth
(
e
)
return
osdate
(
"
%m
"
,
tonumber
(
e
)
)
end
1707
local
function
toeday
(
e
)
return
osdate
(
"
%d
"
,
tonumber
(
e
)
)
end
1708
local
function
toeminute
(
e
)
return
osdate
(
"
%M
"
,
tonumber
(
e
)
)
end
1709
local
function
toesecond
(
e
)
return
osdate
(
"
%S
"
,
tonumber
(
e
)
)
end
1710 1711
local
function
toemonthlong
(
e
)
1712
return
f_monthlong
(
tonumber
(
osdate
(
"
%m
"
,
tonumber
(
e
)
)
)
)
1713
end
1714 1715
local
function
toemonthshort
(
e
)
1716
return
f_monthshort
(
tonumber
(
osdate
(
"
%m
"
,
tonumber
(
e
)
)
)
)
1717
end
1718 1719
local
function
toedaylong
(
e
)
1720
return
f_datlong
(
tonumber
(
osdate
(
"
%w
"
,
tonumber
(
e
)
)
)
)
1721
end
1722 1723
local
function
toedayshort
(
e
)
1724
return
f_dayshort
(
tonumber
(
osdate
(
"
%w
"
,
tonumber
(
e
)
)
)
)
1725
end
1726 1727
local
function
toeweek
(
e
)
-- we run from 1-7 not 0-6
1728
return
tostring
(
tonumber
(
osdate
(
"
%w
"
,
tonumber
(
e
)
)
)
+
1
)
1729
end
1730 1731
local
function
toeweekday
(
e
)
1732
return
f_weekday
(
tonumber
(
osdate
(
"
%w
"
,
tonumber
(
e
)
)
)
+
1
)
1733
end
1734 1735
local
function
toedate
(
format
,
e
)
1736
return
osdate
(
format
,
tonumber
(
e
)
)
1737
end
1738 1739
addformatter
(
formatters
,
"
eyear
"
,
[[
toeyear(%s)
]]
,
{
toeyear
=
toeyear
}
)
1740
addformatter
(
formatters
,
"
emonth
"
,
[[
toemonth(%s)
]]
,
{
toemonth
=
toemonth
}
)
1741
addformatter
(
formatters
,
"
eday
"
,
[[
toeday(%s)
]]
,
{
toeday
=
toeday
}
)
1742
addformatter
(
formatters
,
"
eweek
"
,
[[
toeweek(%s)
]]
,
{
toeweek
=
toeweek
}
)
1743
addformatter
(
formatters
,
"
eminute
"
,
[[
toeminute(%s)
]]
,
{
toeminute
=
toeminute
}
)
1744
addformatter
(
formatters
,
"
esecond
"
,
[[
toesecond(%s)
]]
,
{
toesecond
=
toesecond
}
)
1745 1746
addformatter
(
formatters
,
"
emonthlong
"
,
[[
toemonthlong(%s)
]]
,
{
toemonthlong
=
toemonthlong
}
)
1747
addformatter
(
formatters
,
"
emonthshort
"
,
[[
toemonthshort(%s)
]]
,
{
toemonthshort
=
toemonthshort
}
)
1748
addformatter
(
formatters
,
"
edaylong
"
,
[[
toedaylong(%s)
]]
,
{
toedaylong
=
toedaylong
}
)
1749
addformatter
(
formatters
,
"
edayshort
"
,
[[
toedayshort(%s)
]]
,
{
toedayshort
=
toedayshort
}
)
1750
addformatter
(
formatters
,
"
eweekday
"
,
[[
toeweekday(%s)
]]
,
{
toeweekday
=
toeweekday
}
)
1751 1752
addformatter
(
formatters
,
"
edate
"
,
[[
toedate(%s,%s)
]]
,
{
toedate
=
toedate
}
)
1753 1754
end
1755 1756
-- a prelude to a function that we can use at the lua end
1757 1758
-- day:ord month:mmem
1759
-- j and jj obsolete
1760 1761
local
spaced
=
{
1762
[
v_year
]
=
true
,
1763
[
v_month
]
=
true
,
1764
[
v_MONTH
]
=
true
,
1765
[
v_day
]
=
true
,
1766
[
v_weekday
]
=
true
,
1767
[
v_WEEKDAY
]
=
true
,
1768
}
1769 1770
local
dateconverters
=
{
1771
[
"
hebrew:to
"
]
=
gregorian_to_hebrew
,
1772
[
"
jalali:to
"
]
=
gregorian_to_jalali
,
1773
[
"
jalali:from
"
]
=
jalali_to_gregorian
,
1774
}
1775 1776
local
variants
=
{
1777
mnem
=
{
1778
month
=
monthmnems
,
1779
day
=
daymnems
,
1780
}
,
1781
hebrew
=
{
1782
month
=
setmetatableindex
(
function
(
t
,
k
)
return
months
[
k
]
.
.
"
:hebrew
"
end
)
,
1783
day
=
setmetatableindex
(
function
(
t
,
k
)
return
days
[
k
]
.
.
"
:hebrew
"
end
)
,
1784
}
,
1785
jalali
=
{
1786
month
=
setmetatableindex
(
function
(
t
,
k
)
return
months
[
k
]
.
.
"
:jalali
"
end
)
,
1787
day
=
setmetatableindex
(
function
(
t
,
k
)
return
days
[
k
]
.
.
"
:jalali
"
end
)
,
1788
}
,
1789
}
1790 1791
do
1792 1793
local
function
currentdate
(
str
,
currentlanguage
,
year
,
month
,
day
)
-- second argument false : no label
1794
local
list
=
utilities
.
parsers
.
settings_to_array
(
str
)
1795
local
splitlabel
=
languages
.
labels
.
split
or
string
.
itself
-- we need to get the loading order right
1796
-- local year = tex.year
1797
-- local month = tex.month
1798
-- local day = tex.day
1799
local
auto
=
true
1800
if
currentlanguage
=
=
"
"
then
1801
currentlanguage
=
false
1802
end
1803
for
i
=
1
,
#
list
do
1804
local
entry
=
list
[
i
]
1805
local
convert
=
dateconverters
[
entry
]
1806
if
convert
then
1807
year
,
month
,
day
=
convert
(
year
,
month
,
day
)
1808
else
1809
local
tag
,
plus
=
splitlabel
(
entry
)
1810
local
ordinal
,
mnemonic
,
whatordinal
,
highordinal
=
false
,
false
,
nil
,
false
1811
if
not
tag
then
1812
tag
=
entry
1813
elseif
plus
=
=
"
+
"
or
plus
=
=
"
ord
"
then
1814
ordinal
=
true
1815
elseif
plus
=
=
"
++
"
or
plus
=
=
"
highord
"
then
1816
ordinal
=
true
1817
highordinal
=
true
1818
elseif
plus
then
-- mnem MNEM etc
1819
mnemonic
=
variants
[
plus
]
1820
end
1821
if
not
auto
and
spaced
[
tag
]
then
1822
ctx_space
(
)
1823
end
1824
auto
=
false
1825
if
tag
=
=
v_year
or
tag
=
=
"
y
"
or
tag
=
=
"
Y
"
then
1826
if
plus
then
1827
plus
=
converters
[
plus
]
1828
end
1829
if
plus
then
1830
context
(
plus
(
year
)
)
1831
elseif
currentlanguage
=
=
false
then
1832
context
(
year
)
1833
else
1834
ctx_convertnumber
(
v_year
,
year
)
1835
end
1836
elseif
tag
=
=
"
yy
"
or
tag
=
=
"
YY
"
then
1837
context
(
"
%02i
"
,
year
%
100
)
1838
elseif
tag
=
=
v_month
or
tag
=
=
"
m
"
then
1839
if
currentlanguage
=
=
false
then
1840
context
(
Word
(
months
[
month
]
)
)
1841
else
1842
if
type
(
mnemonic
)
=
=
"
table
"
then
1843
mnemonic
=
mnemonic
.
month
1844
end
1845
if
mnemonic
then
1846
ctx_labeltext
(
variables
[
mnemonic
[
month
]
]
)
1847
else
1848
ctx_labeltext
(
variables
[
months
[
month
]
]
)
1849
end
1850
end
1851
elseif
tag
=
=
v_MONTH
then
1852
if
currentlanguage
=
=
false
then
1853
context
(
Word
(
variables
[
months
[
month
]
]
)
)
1854
else
1855
if
type
(
mnemonic
)
=
=
"
table
"
then
1856
mnemonic
=
mnemonic
.
month
1857
end
1858
if
mnemonic
then
1859
ctx_LABELTEXT
(
variables
[
mnemonic
[
month
]
]
)
1860
else
1861
ctx_LABELTEXT
(
variables
[
months
[
month
]
]
)
1862
end
1863
end
1864
elseif
tag
=
=
"
mm
"
then
1865
context
(
"
%02i
"
,
month
)
1866
elseif
tag
=
=
"
M
"
then
1867
context
(
month
)
1868
elseif
tag
=
=
v_day
or
tag
=
=
"
d
"
then
1869
if
plus
then
1870
plus
=
converters
[
plus
]
1871
end
1872
if
plus
then
1873
context
(
plus
(
day
)
)
1874
elseif
currentlanguage
=
=
false
then
1875
context
(
day
)
1876
else
1877
ctx_convertnumber
(
v_day
,
day
)
1878
end
1879
whatordinal
=
day
1880
elseif
tag
=
=
"
dd
"
then
1881
context
(
"
%02i
"
,
day
)
1882
whatordinal
=
day
1883
elseif
tag
=
=
"
D
"
then
1884
context
(
day
)
1885
whatordinal
=
day
1886
elseif
tag
=
=
v_weekday
or
tag
=
=
"
w
"
then
1887
local
wd
=
weekday
(
day
,
month
,
year
)
1888
if
currentlanguage
=
=
false
then
1889
context
(
Word
(
days
[
wd
]
)
)
1890
else
1891
if
type
(
mnemonic
)
=
=
"
table
"
then
1892
mnemonic
=
mnemonic
.
day
1893
end
1894
if
mnemonic
then
1895
ctx_labeltext
(
variables
[
mnemonic
[
wd
]
]
)
1896
else
1897
ctx_labeltext
(
variables
[
days
[
wd
]
]
)
1898
end
1899
end
1900
elseif
tag
=
=
v_WEEKDAY
then
1901
local
wd
=
weekday
(
day
,
month
,
year
)
1902
if
currentlanguage
=
=
false
then
1903
context
(
Word
(
days
[
wd
]
)
)
1904
else
1905
if
type
(
mnemonic
)
=
=
"
table
"
then
1906
mnemonic
=
mnemonic
.
day
1907
end
1908
if
mnemonic
then
1909
ctx_LABELTEXT
(
variables
[
mnemonic
[
wd
]
]
)
1910
else
1911
ctx_LABELTEXT
(
variables
[
days
[
wd
]
]
)
1912
end
1913
end
1914
elseif
tag
=
=
"
W
"
then
1915
context
(
weekday
(
day
,
month
,
year
)
)
1916
elseif
tag
=
=
v_referral
then
1917
context
(
"
%04i%02i%02i
"
,
year
,
month
,
day
)
1918
elseif
tag
=
=
v_space
or
tag
=
=
"
\\
"
then
1919
ctx_space
(
)
1920
auto
=
true
1921
elseif
tag
~
=
"
"
then
1922
context
(
tag
)
1923
auto
=
true
1924
end
1925
if
ordinal
and
whatordinal
then
1926
if
currentlanguage
=
=
false
then
1927
-- ignore
1928
else
1929
context
[
highordinal
and
"
highordinalstr
"
or
"
ordinalstr
"
]
(
converters
.
ordinal
(
whatordinal
,
currentlanguage
)
)
1930
end
1931
end
1932
end
1933
end
1934
end
1935 1936
implement
{
1937
name
=
"
currentdate
"
,
1938
arguments
=
{
"
string
"
,
"
string
"
,
"
string
"
,
"
integer
"
,
"
integer
"
,
"
integer
"
}
,
1939
actions
=
function
(
pattern
,
default
,
language
,
year
,
month
,
day
)
1940
currentdate
(
1941
pattern
=
=
"
"
and
default
or
pattern
,
1942
language
=
=
"
"
and
false
or
language
,
1943
year
,
month
,
day
1944
)
1945
end
,
1946
}
1947 1948
local
function
todate
(
s
,
y
,
m
,
d
)
1949
if
y
or
m
or
d
then
1950
return
formatters
[
"
\\date[y=%s,m=%s,d=%s][%s]\\relax
"
]
(
y
or
"
"
,
m
or
"
"
,
d
or
"
"
,
s
or
"
"
)
1951
else
1952
return
formatters
[
"
\\currentdate[%s]\\relax
"
]
(
s
)
1953
end
1954
end
1955 1956
addformatter
(
formatters
,
"
date
"
,
[[
todate(...)
]]
,
{
todate
=
todate
}
)
1957 1958
-- context("one: %4!date!","MONTH",2020,12,11) context.par()
1959
-- context("one: %4!date!","month",2020,12,11) context.par()
1960
-- context("one: %4!date!","year,-,mm,-,dd",2020,12,11) context.par()
1961 1962
-- context("two: %3!date!","MONTH",false,12) context.par()
1963
-- context("two: %3!date!","month",false,12) context.par()
1964
-- context("two: %3!date!","year,-,mm,-,dd",false,12) context.par()
1965 1966
end
1967 1968
implement
{
1969
name
=
"
unihex
"
,
1970
arguments
=
"
integer
"
,
1971
actions
=
{
formatters
[
"
U+%05X
"
]
,
context
}
,
1972
}
1973 1974
-- totime might move to utilities.parsers as more general helper
1975 1976
local
n
=
R
(
"
09
"
)
^
1
/
tonumber
-- lpegpatterns.digit
1977 1978
local
p
=
Cf
(
Ct
(
"
"
)
1979
-- year is mandate, month and day are optional
1980
*
Cg
(
Cc
(
"
year
"
)
*
n
)
1981
*
S
(
"
-/
"
)
^
-1
1982
*
Cg
(
Cc
(
"
month
"
)
*
(
n
+
Cc
(
1
)
)
)
1983
*
S
(
"
-/
"
)
^
-1
1984
*
Cg
(
Cc
(
"
day
"
)
*
(
n
+
Cc
(
1
)
)
)
1985
-- time is optional, hour and minuta are mandate, seconds are optional
1986
*
(
1987
whitespace
^
0
1988
*
P
(
"
T
"
)
^
-1
1989
*
whitespace
^
0
1990
*
Cg
(
Cc
(
"
hour
"
)
*
n
)
1991
*
P
(
"
:
"
)
^
-1
1992
*
Cg
(
Cc
(
"
min
"
)
*
n
)
1993
*
P
(
"
:
"
)
^
-1
1994
*
Cg
(
Cc
(
"
sec
"
)
*
(
n
+
Cc
(
0
)
)
)
1995
)
^
-1
1996
-- zone is optional, hour is mandate, minutes are optional
1997
*
(
1998
whitespace
^
0
1999
*
Cg
(
Cc
(
"
tzs
"
)
*
(
P
(
"
+
"
)
*
Cc
(
1
)
+
P
(
"
-
"
)
*
Cc
(
-1
)
+
Cc
(
1
)
)
)
2000
*
whitespace
^
0
2001
*
Cg
(
Cc
(
"
tzh
"
)
*
n
)
2002
*
P
(
"
:
"
)
^
-1
2003
*
Cg
(
Cc
(
"
tzm
"
)
*
(
n
+
Cc
(
0
)
)
)
2004
)
^
-1
2005
,
rawset
)
2006 2007
function
converters
.
totime
(
s
)
2008
if
not
s
then
2009
return
2010
elseif
type
(
s
)
=
=
"
table
"
then
2011
return
s
2012
elseif
type
(
s
)
=
=
"
string
"
then
2013
local
t
=
lpegmatch
(
p
,
s
)
2014
if
not
t
then
2015
logs
.
report
(
"
system
"
,
"
invalid time specification %a
"
,
s
)
2016
elseif
t
.
tzh
then
2017
local
localtzh
,
localtzm
=
ostimezone
(
true
)
2018
t
.
hour
=
t
.
hour
+
localtzh
-
t
.
tzs
*
t
.
tzh
2019
t
.
min
=
t
.
min
+
localtzm
-
t
.
tzs
*
t
.
tzm
2020
end
2021
return
t
2022
end
2023
local
n
=
tonumber
(
s
)
2024
if
n
and
n
>
=
0
then
2025
return
osdate
(
"
*t
"
,
n
)
2026
end
2027
end
2028 2029
function
converters
.
settime
(
t
)
2030
if
type
(
t
)
~
=
"
table
"
then
2031
t
=
converters
.
totime
(
t
)
2032
end
2033
if
t
then
2034
texset
(
"
year
"
,
t
.
year
or
1000
)
2035
texset
(
"
month
"
,
t
.
month
or
1
)
2036
texset
(
"
day
"
,
t
.
day
or
1
)
2037
texset
(
"
time
"
,
(
t
.
hour
or
0
)
*
60
+
(
t
.
min
or
0
)
)
2038
end
2039
end
2040 2041
-- taken from x-asciimath (where we needed it for a project)
2042 2043
local
d_one
=
lpegpatterns
.
digit
2044
local
d_two
=
d_one
*
d_one
2045
local
d_three
=
d_two
*
d_one
2046
local
d_four
=
d_three
*
d_one
2047
local
d_split
=
P
(
-1
)
+
Carg
(
2
)
*
(
lpegpatterns
.
period
/
"
"
)
2048 2049
local
d_spaced
=
(
Carg
(
1
)
*
d_three
)
^
1
2050 2051
local
digitized_1
=
Cs
(
(
2052
d_three
*
d_spaced
*
d_split
+
2053
d_two
*
d_spaced
*
d_split
+
2054
d_one
*
d_spaced
*
d_split
+
2055
P
(
1
)
2056
)
^
1
)
2057 2058
local
p_fourbefore
=
d_four
*
d_split
2059
local
p_fourafter
=
d_four
*
P
(
-1
)
2060 2061
local
p_beforesplit
=
d_three
*
d_spaced
^
0
*
d_split
2062
+
d_two
*
d_spaced
^
0
*
d_split
2063
+
d_one
*
d_spaced
^
0
*
d_split
2064
+
d_one
*
d_split
2065 2066
local
p_aftersplit
=
p_fourafter
2067
+
d_three
*
d_spaced
2068
+
d_two
*
d_spaced
2069
+
d_one
*
d_spaced
2070 2071
local
digitized_2
=
Cs
(
2072
p_fourbefore
*
(
p_aftersplit
^
0
)
+
2073
p_beforesplit
*
(
(
p_aftersplit
+
d_one
^
1
)
^
0
)
2074
)
2075 2076
local
p_fourbefore
=
d_four
*
d_split
2077
local
p_fourafter
=
d_four
2078
local
d_spaced
=
(
Carg
(
1
)
*
(
d_three
+
d_two
+
d_one
)
)
^
1
2079
local
p_aftersplit
=
p_fourafter
*
P
(
-1
)
2080
+
d_three
*
d_spaced
*
P
(
1
)
^
0
2081
+
d_one
^
1
2082 2083
local
digitized_3
=
Cs
(
(
p_fourbefore
+
p_beforesplit
)
*
p_aftersplit
^
0
)
2084 2085
local
digits_space
=
utfchar
(
0x2008
)
2086 2087
local
splitmethods
=
{
2088
digitized_1
,
2089
digitized_2
,
2090
digitized_3
,
2091
}
2092 2093
local
replacers
=
table
.
setmetatableindex
(
function
(
t
,
k
)
2094
local
v
=
lpeg
.
replacer
(
"
.
"
,
k
)
2095
t
[
k
]
=
v
2096
return
v
2097
end
)
2098 2099
function
converters
.
spaceddigits
(
settings
,
data
)
2100
local
data
=
tostring
(
data
or
settings
.
data
or
"
"
)
2101
if
data
~
=
"
"
then
2102
local
method
=
settings
.
method
2103
local
split
=
splitmethods
[
tonumber
(
method
)
or
1
]
2104
if
split
then
2105
local
symbol
=
settings
.
symbol
2106
local
separator
=
settings
.
separator
2107
if
not
symbol
or
symbol
=
=
"
"
then
2108
symbol
=
"
.
"
2109
end
2110
if
type
(
separator
)
~
=
"
string
"
or
separator
=
=
"
"
then
2111
separator
=
digits_space
2112
end
2113
local
result
=
lpegmatch
(
split
,
data
,
1
,
separator
,
symbol
)
2114
if
not
result
and
symbol
~
=
"
.
"
then
2115
result
=
lpegmatch
(
replacers
[
symbol
]
,
data
)
2116
end
2117
if
result
then
2118
-- print(method,symbol,separator,data,result)
2119
return
result
2120
end
2121
end
2122
end
2123
return
str
2124
end
2125 2126
-- method 2 : split 3 before and 3 after
2127
-- method 3 : split 3 before and 3 after with > 4 before
2128 2129
-- symbols is extra split (in addition to period)
2130 2131
-- local setup = { splitmethod = 3, symbol = "," }
2132
-- local setup = { splitmethod = 2, symbol = "," }
2133
-- local setup = { splitmethod = 1, symbol = "," }
2134
--
2135
-- local t = {
2136
-- "0.00002",
2137
-- "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678", "123456789",
2138
-- "1.1",
2139
-- "12.12",
2140
-- "123.123",
2141
-- "1234.123",
2142
-- "1234.1234",
2143
-- "12345.1234",
2144
-- "1234.12345",
2145
-- "12345.12345",
2146
-- "123456.123456",
2147
-- "1234567.1234567",
2148
-- "12345678.12345678",
2149
-- "123456789.123456789",
2150
-- "0.1234",
2151
-- "1234.0",
2152
-- "1234.00",
2153
-- "0.123456789",
2154
-- "100.00005",
2155
-- "0.80018",
2156
-- "10.80018",
2157
-- "100.80018",
2158
-- "1000.80018",
2159
-- "10000.80018",
2160
-- }
2161
--
2162
-- for i=1,#t do
2163
-- print(formatters["%-20s : [%s]"](t[i],converters.spaceddigits(setup,t[i])))
2164
-- end
2165 2166
implement
{
2167
name
=
"
spaceddigits
"
,
2168
actions
=
{
converters
.
spaceddigits
,
context
}
,
2169
arguments
=
{
2170
{
2171
{
"
symbol
"
}
,
2172
{
"
separator
"
}
,
2173
{
"
data
"
}
,
2174
{
"
method
"
}
,
2175
}
2176
}
2177
}
2178 2179
local
function
field
(
n
)
return
context
(
osdate
(
"
*t
"
)
[
n
]
)
end
2180 2181
implement
{
name
=
"
actualday
"
,
public
=
true
,
actions
=
function
(
)
field
(
"
day
"
)
end
}
2182
implement
{
name
=
"
actualmonth
"
,
public
=
true
,
actions
=
function
(
)
field
(
"
month
"
)
end
}
2183
implement
{
name
=
"
actualyear
"
,
public
=
true
,
actions
=
function
(
)
field
(
"
year
"
)
end
}
2184 2185
implement
{
2186
name
=
"
uuid
"
,
2187
public
=
true
,
2188
actions
=
{
os
.
uuid
,
context
}
,
2189
}
2190