* [NTG-context] Weird date output
@ 2025-01-11 5:08 autumnus
2025-01-11 17:17 ` [NTG-context] " Wolfgang Schuster
0 siblings, 1 reply; 11+ messages in thread
From: autumnus @ 2025-01-11 5:08 UTC (permalink / raw)
To: ntg-context
hi,
When I try to output the Chinese date with the command below,
I find that it doesn't process the month at all. No matter how
I try any of the "month,month:cn-a,month:cn-c,month:cn-d" conversions
Unless I pre-set the labeltext for the Chinese month.
%%%%
\definedfont[name:adobesongstdlight]
\currentdate[year:cn-d,年,month:cn-a,day:cn,号] %output : 二〇二五年January 十一号
\setuplabeltext [en][january={一月},]
\currentdate[year:cn-d,年,month:cn-a,day:cn,号] %output : 二〇二五年一月 十一号
%%%%
If so, then when should I use those conversion method ?
(At present, the output of "month:cn-d" is only suitable for the year, not the month and day.
Its naming is somewhat misleading)
What's more, there seems to be a strange space here between the month and the day.
It should output 二〇二五年一月十一号 instead 二〇二五年一月 十一号
autumnus
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-11 5:08 [NTG-context] Weird date output autumnus
@ 2025-01-11 17:17 ` Wolfgang Schuster
2025-01-12 5:16 ` autumnus
0 siblings, 1 reply; 11+ messages in thread
From: Wolfgang Schuster @ 2025-01-11 17:17 UTC (permalink / raw)
To: mailing list for ConTeXt users, autumnus
Am 11.01.2025 um 06:08 schrieb autumnus:
> hi,
>
> When I try to output the Chinese date with the command below,
> I find that it doesn't process the month at all. No matter how
> I try any of the "month,month:cn-a,month:cn-c,month:cn-d" conversions
> Unless I pre-set the labeltext for the Chinese month.
>
> %%%%
> \definedfont[name:adobesongstdlight]
> \currentdate[year:cn-d,年,month:cn-a,day:cn,号] %output : 二〇二五年January 十一号
>
> \setuplabeltext [en][january={一月},]
> \currentdate[year:cn-d,年,month:cn-a,day:cn,号] %output : 二〇二五年一月 十一号
> %%%%
>
> If so, then when should I use those conversion method ?
> (At present, the output of "month:cn-d" is only suitable for the year, not the month and day.
> Its naming is somewhat misleading)
>
> What's more, there seems to be a strange space here between the month and the day.
> It should output 二〇二五年一月十一号 instead 二〇二五年一月 十一号
1. You can't apply a number conversion for months.
2. You can switch languages to get label texts for chinese.
\starttext
\currentdate[month,day]
\language[cn]
\definedfont[name:adobesongstdlight]
\currentdate[month,day:cn]
\stoptext
3. The space after the month is inserted on purpose to get a space
between the month and day as can be seen in the example above. To
prevent this auto space for chinese a language check can be added to the
date command.
Wolfgang
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-11 17:17 ` [NTG-context] " Wolfgang Schuster
@ 2025-01-12 5:16 ` autumnus
2025-01-12 11:11 ` Tomáš Hála
2025-01-13 16:43 ` Wolfgang Schuster
0 siblings, 2 replies; 11+ messages in thread
From: autumnus @ 2025-01-12 5:16 UTC (permalink / raw)
To: ntg-context
Thank you for your explanation.
Regarding the space after the month,
will it be added to the ConTeXt in the future?
I'm worried that after I patch it,
it will be overwritten when I update it later.
autumnus
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-12 5:16 ` autumnus
@ 2025-01-12 11:11 ` Tomáš Hála
2025-01-12 13:27 ` autumnus
2025-01-13 16:43 ` Wolfgang Schuster
1 sibling, 1 reply; 11+ messages in thread
From: Tomáš Hála @ 2025-01-12 11:11 UTC (permalink / raw)
To: mailing list for ConTeXt users
Hi autumnus,
I have got no experience with Chinese but I think it is possible to change it for the future.
The current settings for Chinese has been defined as (file tex/texmf-context/tex/context/base/mkxl/lang-def.mkxl, line no. 655):
\c!date={\v!year,年,\space,\v!month,\v!day,日}
You can change it to how the date is correctly written,
and send it to me, please, I will prepare new files for Hans.
Tomáš
On Sun, Jan 12, 2025 at 05:16:50AM -0000, autumnus wrote:
> Thank you for your explanation.
> Regarding the space after the month,
> will it be added to the ConTeXt in the future?
> I'm worried that after I patch it,
> it will be overwritten when I update it later.
>
> autumnus
> ___________________________________________________________________________________
> If your question is of interest to others as well, please add an entry to the Wiki!
>
> maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
> webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
> archive : https://github.com/contextgarden/context
> wiki : https://wiki.contextgarden.net
> ___________________________________________________________________________________
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-12 11:11 ` Tomáš Hála
@ 2025-01-12 13:27 ` autumnus
2025-01-12 13:31 ` autumnus
0 siblings, 1 reply; 11+ messages in thread
From: autumnus @ 2025-01-12 13:27 UTC (permalink / raw)
To: ntg-context
hi, Tomáš
Thank you for your help.
The format that is currently more commonly used is the first one.
%%%%
\starttext
\language[cn]
\definedfont[name:adobesongstdlight]
modern and mostly used : \currentdate[year,年,M,月,day,日] : 2025年1月12日
traditional and special case: \currentdate[year:cn-d,年,month,day:cn,日] : 二〇二五年一月十二日
The addition of spaces should only be added between numbers and kanji.
The addition of spaces should take effect not only in the date, but in all texts.
If you add a space it should be:
2025 年 1 月 12 日 (between numbers and kanji)
二〇二五年一月十二日 (no space added)
\stoptext
%%%%
autumnus
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-12 13:27 ` autumnus
@ 2025-01-12 13:31 ` autumnus
0 siblings, 0 replies; 11+ messages in thread
From: autumnus @ 2025-01-12 13:31 UTC (permalink / raw)
To: ntg-context
I don't know why, the text is automatically added with spaces.
The correct one should be:
\currentdate[year,年,M,月,day,日]
\currentdate[year:cn-d,年,month,day:cn,日]
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-12 5:16 ` autumnus
2025-01-12 11:11 ` Tomáš Hála
@ 2025-01-13 16:43 ` Wolfgang Schuster
2025-01-13 18:02 ` Hans Hagen
1 sibling, 1 reply; 11+ messages in thread
From: Wolfgang Schuster @ 2025-01-13 16:43 UTC (permalink / raw)
To: autumnus, ntg-context
Am 12.01.2025 um 06:16 schrieb autumnus:
> Thank you for your explanation.
> Regarding the space after the month,
> will it be added to the ConTeXt in the future?
> I'm worried that after I patch it,
> it will be overwritten when I update it later.
It depends whether Hans includes the fix or not.
Wolfgang
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-13 16:43 ` Wolfgang Schuster
@ 2025-01-13 18:02 ` Hans Hagen
2025-01-13 19:09 ` Wolfgang Schuster
0 siblings, 1 reply; 11+ messages in thread
From: Hans Hagen @ 2025-01-13 18:02 UTC (permalink / raw)
To: ntg-context
On 1/13/2025 5:43 PM, Wolfgang Schuster wrote:
> Am 12.01.2025 um 06:16 schrieb autumnus:
>> Thank you for your explanation.
>> Regarding the space after the month,
>> will it be added to the ConTeXt in the future?
>> I'm worried that after I patch it,
>> it will be overwritten when I update it later.
>
> It depends whether Hans includes the fix or not.
You mean this?
\c!date={\v!year,年,\space,\v!month,\v!day,日}
It also depends on Tomas who deals with languages,
Hans
-----------------------------------------------------------------
Hans Hagen | PRAGMA ADE
Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-13 18:02 ` Hans Hagen
@ 2025-01-13 19:09 ` Wolfgang Schuster
2025-01-13 20:33 ` Hans Hagen
0 siblings, 1 reply; 11+ messages in thread
From: Wolfgang Schuster @ 2025-01-13 19:09 UTC (permalink / raw)
To: mailing list for ConTeXt users, Hans Hagen
[-- Attachment #1: Type: text/plain, Size: 845 bytes --]
Am 13.01.2025 um 19:02 schrieb Hans Hagen:
> On 1/13/2025 5:43 PM, Wolfgang Schuster wrote:
>> Am 12.01.2025 um 06:16 schrieb autumnus:
>>> Thank you for your explanation.
>>> Regarding the space after the month,
>>> will it be added to the ConTeXt in the future?
>>> I'm worried that after I patch it,
>>> it will be overwritten when I update it later.
>>
>> It depends whether Hans includes the fix or not.
>
> You mean this?
>
> \c!date={\v!year,年,\space,\v!month,\v!day,日}
>
> It also depends on Tomas who deals with languages,
No, I sent a patched core-con.lmt in a previous mail where I added
local packed = { ["cn"] = true }
on line 1881 and changed line 1916 from
if not auto and spaced[tag] then
to
if not auto and not packed[currentlanguage] and spaced[tag] then
Wolfgang
[-- Attachment #2: core-con.lmt --]
[-- Type: text/plain, Size: 74995 bytes --]
if not modules then modules = { } end modules ['core-con'] = {
version = 1.001,
comment = "companion to core-con.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-- todo: split into lang-con.lua and core-con.lua
-- This module implements a bunch of conversions. Some are more efficient than their
-- TeX counterpart, some are even slower but look nicer this way. Some code may move
-- to a module in the language namespace.
local floor = math.floor
local osdate, ostime, ostimezone = os.date, os.time, os.timezone
local concat, insert, reverse = table.concat, table.insert, table.reverse
local lower, upper, rep, match, gsub, gmatch = string.lower, string.upper, string.rep, string.match, string.gsub, string.gmatch
local utfchar, utfbyte = utf.char, utf.byte
local tonumber, tostring, type, rawset = tonumber, tostring, type, rawset
local P, S, R, Cc, Ct, Cs, C, V, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.Ct, lpeg.Cs, lpeg.C, lpeg.V, lpeg.Carg
----- Cf, Cg = lpeg.Cf, lpeg.Cg
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local div, mod = math.div, math.mod
local context = context
local commands = commands
local implement = interfaces.implement
local settings_to_array = utilities.parsers.settings_to_array
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
local variables = interfaces.variables
local constants = interfaces.constants
local addformatter = utilities.strings.formatters.add
local texset = tex.set
converters = converters or { }
local converters = converters
languages = languages or { }
local languages = languages
local helpers = converters.helpers or { }
converters.helpers = helpers
local ctx_labeltext = context.labeltext
local ctx_LABELTEXT = context.LABELTEXT
local ctx_space = context.space
local ctx_convertnumber = context.convertnumber
local ctx_highordinalstr = context.highordinalstr
converters.number = tonumber
converters.numbers = tonumber
implement { name = "number", actions = context }
implement { name = "numbers", actions = context }
-- to be reconsidered ... languages namespace here, might become local plus a register command
local counters = allocate {
['default'] = { -- no metatable as we do a test on keys
0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
0x0075, 0x0076, 0x0077, 0x0078, 0x0079,
0x007A
},
['slovenian'] = {
0x0061, 0x0062, 0x0063, 0x010D, 0x0064,
0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
0x006A, 0x006B, 0x006C, 0x006D, 0x006E,
0x006F, 0x0070, 0x0072, 0x0073, 0x0161,
0x0074, 0x0075, 0x0076, 0x007A, 0x017E
},
['spanish'] = {
0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
0x006B, 0x006C, 0x006D, 0x006E, 0x00F1,
0x006F, 0x0070, 0x0071, 0x0072, 0x0073,
0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
0x0079, 0x007A
},
['russian'] = {
0x0430, 0x0431, 0x0432, 0x0433, 0x0434,
0x0435, 0x0436, 0x0437, 0x0438, 0x043a,
0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444,
0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
0x044d, 0x044e, 0x044f
},
['greek'] = { -- this should be the lowercase table
-- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
-- 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
-- 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
-- 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
-- 0x03A6, 0x03A7, 0x03A8, 0x03A9
0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5,
0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA,
0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5,
0x03C6, 0x03C7, 0x03C8, 0x03C9,
},
['arabic'] = {
0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
0x0643, 0x0644, 0x0645, 0x0646, 0x0633,
0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
0x0636, 0x0638, 0x063A,
},
['persian'] = {
0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
0x06A9, 0x0644, 0x0645, 0x0646, 0x0633,
0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
0x0636, 0x0638, 0x063A,
},
['thai'] = {
0xE050, 0xE051, 0xE052, 0xE053, 0xE054,
0xE055, 0xE056, 0xE057, 0xE058, 0xE059
},
['devanagari'] = {
-- ० १ २ ३ ४ ५ ६ ७ ८ ९
0x0966, 0x0967, 0x0968, 0x0969, 0x096A,
0x096B, 0x096C, 0x096D, 0x096E, 0x096F
},
['gurmurkhi'] = {
0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A,
0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F
},
['gujarati'] = {
0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA,
0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF
},
['tibetan'] = {
0x0F20, 0x0F21, 0x0F22, 0x0F23, 0x0F24,
0x0F25, 0x0F26, 0x0F27, 0x0F28, 0x0F29
},
['korean'] = {
0x3131, 0x3134, 0x3137, 0x3139, 0x3141,
0x3142, 0x3145, 0x3147, 0x3148, 0x314A,
0x314B, 0x314C, 0x314D, 0x314E
},
['korean-parenthesis'] = { --
0x3200, 0x3201, 0x3202, 0x3203, 0x3204,
0x3205, 0x3206, 0x3207, 0x3208, 0x3209,
0x320A, 0x320B, 0x320C, 0x320D
},
['korean-circle'] = { -- circled
0x3260, 0x3261, 0x3262, 0x3263, 0x3264,
0x3265, 0x3266, 0x3267, 0x3268, 0x3269,
0x326A, 0x326B, 0x326C, 0x326D
},
['hiragana'] = {
0x3042, 0x3044, 0x3046, 0x3048, 0x304A,
0x304B, 0x304D, 0x304F, 0x3051, 0x3053,
0x3055, 0x3057, 0x3059, 0x305B, 0x305D,
0x305F, 0x3061, 0x3064, 0x3066, 0x3068,
0x306A, 0x306B, 0x306C, 0x306D, 0x306E,
0x306F, 0x3072, 0x3075, 0x3078, 0x307B,
0x307E, 0x307F, 0x3080, 0x3081, 0x3082,
0x3084, 0x3086, 0x3088,
0x3089, 0x308A, 0x308B, 0x308C, 0x308D,
0x308F, 0x3090, 0x3091, 0x3092,
0x3093
},
['hiragana-iroha'] = {
0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068,
0x3061, 0x308A, 0x306C, 0x308B, 0x3092,
0x308F, 0x304B, 0x3088, 0x305F, 0x308C, 0x305D,
0x3064, 0x306D, 0x306A, 0x3089, 0x3080,
0x3046, 0x3090, 0x306E, 0x304A, 0x304F, 0x3084, 0x307E,
0x3051, 0x3075, 0x3053, 0x3048, 0x3066,
0x3042, 0x3055, 0x304D, 0x3086, 0x3081, 0x307F, 0x3057,
0x3091, 0x3072, 0x3082, 0x305B, 0x3059
},
['katakana'] = {
0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA,
0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3,
0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD,
0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8,
0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE,
0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB,
0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2,
0x30E4, 0x30E6, 0x30E8,
0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED,
0x30EF, 0x30F0, 0x30F1, 0x30F2,
0x30F3
},
['katakana-iroha'] = {
0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8,
0x30C1, 0x30EA, 0x30CC, 0x30EB, 0x30F2,
0x30EF, 0x30AB, 0x30E8, 0x30BF, 0x30EC, 0x30BD,
0x30C4, 0x30CD, 0x30CA, 0x30E9, 0x30E0,
0x30A6, 0x30F0, 0x30CE, 0x30AA, 0x30AF, 0x30E4, 0x30DE,
0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6,
0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, 0x30DF, 0x30B7,
0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x30B9
},
}
languages.counters = counters
counters['ar'] = counters['arabic']
counters['gr'] = counters['greek']
counters['g'] = counters['greek']
counters['sl'] = counters['slovenian']
counters['es'] = counters['spanish']
counters['ru'] = counters['russian']
counters['kr'] = counters['korean']
counters['kr-p'] = counters['korean-parenthesis']
counters['kr-c'] = counters['korean-circle']
counters['thainumerals'] = counters['thai']
counters['devanagarinumerals'] = counters['devanagari']
counters['gurmurkhinumerals'] = counters['gurmurkhi']
counters['gujaratinumerals'] = counters['gujarati']
counters['tibetannumerals'] = counters['tibetan']
counters['greeknumerals'] = counters['greek']
counters['arabicnumerals'] = counters['arabic']
counters['persiannumerals'] = counters['persian']
counters['arabicexnumerals'] = counters['persian']
counters['koreannumerals'] = counters['korean']
counters['koreanparenthesisnumerals'] = counters['korean-parenthesis']
counters['koreancirclenumerals'] = counters['korean-circle']
counters['sloveniannumerals'] = counters['slovenian']
counters['spanishnumerals'] = counters['spanish']
counters['russiannumerals'] = counters['russian']
local decimals = allocate {
['arabic'] = {
["0"] = "٠", ["1"] = "١", ["2"] = "٢", ["3"] = "٣", ["4"] = "٤",
["5"] = "٥", ["6"] = "٦", ["7"] = "٧", ["8"] = "٨", ["9"] = "٩",
},
['persian'] = {
["0"] = "۰", ["1"] = "۱", ["2"] = "۲", ["3"] = "۳", ["4"] = "۴",
["5"] = "۵", ["6"] = "۶", ["7"] = "۷", ["8"] = "۸", ["9"] = "۹",
},
['devanagari'] = {
["0"] = "०", ["1"] = "१", ["2"] = "२", ["3"] = "३", ["4"] = "४",
["5"] = "५", ["6"] = "६", ["7"] = "७", ["8"] = "८", ["9"] = "९",
},
['malayalam'] = {
["0"] = "൦", ["1"] = "൧", ["2"] = "൨", ["3"] = "൩", ["4"] = "൪",
["5"] = "൫", ["6"] = "൬", ["7"] = "൭", ["8"] = "൮", ["9"] = "൯",
},
['tamil'] = {
["0"] = "௦", ["1"] = "௧", ["2"] = "௨", ["3"] = "௩", ["4"] = "௪",
["5"] = "௫", ["6"] = "௬", ["7"] = "௭", ["8"] = "௮", ["9"] = "௯",
},
['kannada'] = {
["0"] = "೦", ["1"] = "೧", ["2"] = "೨", ["3"] = "೩", ["4"] = "೪",
["5"] = "೫", ["6"] = "೬", ["7"] = "೭", ["8"] = "೮", ["9"] = "೯",
},
['telugu'] = {
["0"] = "౦", ["1"] = "౧", ["2"] = "౨", ["3"] = "౩", ["4"] = "౪",
["5"] = "౫", ["6"] = "౬", ["7"] = "౭", ["8"] = "౮", ["9"] = "౯",
},
['bengali'] = {
["0"] = "০", ["1"] = "১", ["2"] = "২", ["3"] = "৩", ["4"] = "৪",
["5"] = "৫", ["6"] = "৬", ["7"] = "৭", ["8"] = "৮", ["9"] = "৯",
},
['gujarati'] = {
["0"] = "૦", ["1"] = "૧", ["2"] = "૨", ["3"] = "૩", ["4"] = "૪",
["5"] = "૫", ["6"] = "૬", ["7"] = "૭", ["8"] = "૮", ["9"] = "૯",
},
['gurmurkhi'] = {
["0"] = "੦", ["1"] = "੧", ["2"] = "੨", ["3"] = "੩", ["4"] = "੪",
["5"] = "੫", ["6"] = "੬", ["7"] = "੭", ["8"] = "੮", ["9"] = "੯",
},
}
languages.decimals = decimals
local fallback = utfbyte('0')
local function chr(n,m)
return (n > 0 and n < 27 and utfchar(n+m)) or ""
end
local function chrs(n,m,t)
if not t then
t = { }
end
if n > 26 then
chrs(floor((n-1)/26),m,t)
n = (n-1)%26 + 1
end
if n ~= 0 then
t[#t+1] = utfchar(n+m)
end
if n <= 26 then
return concat(t)
end
end
local function maxchrs(n,m,cmd,t)
if not t then
t = { }
end
if n > m then
maxchrs(floor((n-1)/m),m,cmd)
n = (n-1)%m + 1
end
t[#t+1] = formatters["%s{%s}"](cmd,n)
if n <= m then
return concat(t)
end
end
converters.chr = chr
converters.chrs = chrs
converters.maxchrs = maxchrs
local lowercharacter = characters.lcchars
local uppercharacter = characters.ucchars
local defaultcounter = counters.default
local function do_alphabetic(n,mapping,mapper,t) -- todo: make zero based variant (initial n + 1)
if not t then
t = { }
end
local max = #mapping
if n > max then
do_alphabetic(floor((n-1)/max),mapping,mapper,t)
n = (n-1) % max + 1
end
local chr = mapping[n] or fallback
t[#t+1] = mapper and mapper[chr] or chr
if n <= max then
return concat(t)
end
end
local function alphabetic(n,code)
return do_alphabetic(n,code and code ~= "" and counters[code] or defaultcounter,lowercharacter)
end
local function Alphabetic(n,code)
return do_alphabetic(n,code and code ~= "" and counters[code] or defaultcounter,uppercharacter)
end
converters.alphabetic = alphabetic
converters.Alphabetic = Alphabetic
-- we could make a replacer
local function todecimals(n,name)
local stream = tostring(n)
local mapping = decimals[name]
return mapping and gsub(stream,".",mapping) or stream
end
converters.decimals = todecimals
local lower_offset = 96
local upper_offset = 64
function converters.character (n) return chr (n,lower_offset) end
function converters.Character (n) return chr (n,upper_offset) end
function converters.characters(n) return chrs(n,lower_offset) end
function converters.Characters(n) return chrs(n,upper_offset) end
implement { name = "alphabetic", actions = { alphabetic, context }, arguments = { "integer", "string" } }
implement { name = "Alphabetic", actions = { Alphabetic, context }, arguments = { "integer", "string" } }
implement { name = "character", actions = { chr, context }, arguments = { "integer", lower_offset } }
implement { name = "Character", actions = { chr, context }, arguments = { "integer", upper_offset } }
implement { name = "characters", actions = { chrs, context }, arguments = { "integer", lower_offset } }
implement { name = "Characters", actions = { chrs, context }, arguments = { "integer", upper_offset } }
implement { name = "decimals", actions = { todecimals, context }, arguments = { "integer", "string" } }
local weekday = os.weekday -- moved to l-os
local isleapyear = os.isleapyear -- moved to l-os
local nofdays = os.nofdays -- moved to l-os
local function leapyear(year)
return isleapyear(year) and 1 or 0
end
local function textime()
return tonumber(osdate("%H")) * 60 + tonumber(osdate("%M"))
end
-- For consistenty we need to add day here but that conflicts with the current
-- serializer so then best is to have none from now on:
-- function converters.year () return osdate("%Y") end
-- function converters.month () return osdate("%m") end -- always two digits
-- function converters.day () return osdate("%d") end -- conflicts
-- function converters.hour () return osdate("%H") end
-- function converters.minute() return osdate("%M") end
-- function converters.second() return osdate("%S") end
converters.weekday = weekday
converters.isleapyear = isleapyear
converters.leapyear = leapyear
converters.nofdays = nofdays
converters.textime = textime
implement { name = "weekday", actions = { weekday, context }, arguments = { "integer", "integer", "integer" } }
implement { name = "leapyear", actions = { leapyear, context }, arguments = "integer" }
implement { name = "nofdays", actions = { nofdays, context }, arguments = { "integer", "integer" } }
implement { name = "year", actions = { osdate, context }, arguments = "'%Y'" }
implement { name = "month", actions = { osdate, context }, arguments = "'%m'" }
implement { name = "day", actions = { osdate, context }, arguments = "'%d'" }
implement { name = "hour", actions = { osdate, context }, arguments = "'%H'" }
implement { name = "minute", actions = { osdate, context }, arguments = "'%M'" }
implement { name = "second", actions = { osdate, context }, arguments = "'%S'" }
implement { name = "textime", actions = { textime, context } }
implement {
name = "doifelseleapyear",
actions = { isleapyear, commands.doifelse },
arguments = "integer"
}
local roman = {
{ [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' },
{ [0] = '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC' },
{ [0] = '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM' },
}
local function toroman(n)
if n >= 4000 then
return toroman(floor(n/1000)) .. " " .. toroman(n%1000)
else
return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] .. roman[2][floor((n%100)/10)] .. roman[1][floor((n%10)/1)]
end
end
converters.toroman = toroman
converters.Romannumerals = toroman
converters.romannumerals = function(n) return lower(toroman(n)) end
converters['i'] = converters.romannumerals
converters['I'] = converters.Romannumerals
converters['r'] = converters.romannumerals
converters['R'] = converters.Romannumerals
converters['KR'] = converters.Romannumerals
converters['RK'] = converters.Romannumerals
implement {
name = "romannumerals",
actions = { toroman, lower, context },
arguments = "integer",
}
implement {
name = "Romannumerals",
actions = { toroman, context },
arguments = "integer",
}
--~ local small = {
--~ 0x0627, 0x066E, 0x062D, 0x062F, 0x0647, 0x0648, 0x0631
--~ }
--~ local large = {
--~ { 0x0627, 0x0628, 0x062C, 0x062F, 0x0647, 0x0648, 0x0632, 0x062D, 0x0637, },
--~ { 0x064A, 0x0643, 0x0644, 0x0645, 0x0646, 0x0633, 0x0639, 0x0641, 0x0635, },
--~ { 0x0642, 0x0631, 0x0634, 0x062A, 0x062B, 0x062E, 0x0630, 0x0636, 0x0638, },
--~ { 0x063A },
--~ }
local small = {
"ا", "ٮ", "ح", "د", "ه", "و", "ر",
}
local medium = {
"ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" ,
"ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" ,
"ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" ,
"غ" ,
}
local large = {
{ "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" },
{ "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" },
{ "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" },
{ "غ" },
}
local function toabjad(n,what)
if n <= 0 or n >= 2000 then
return tostring(n)
elseif what == 2 and n <= 7 then
return small[n]
elseif what == 3 and n <= 28 then
return medium[n]
else
local a, b, c, d
a, n = floor(n/1000), n % 1000 -- mod(n,1000)
b, n = floor(n/ 100), n % 100 -- mod(n, 100)
c, n = floor(n/ 10), n % 10 -- mod(n, 10)
d, n = floor(n/ 1), n % 1 -- mod(n, 1)
return (large[4][a] or "") .. (large[3][b] or "") .. (large[2][c] or "") .. (large[1][d] or "")
end
end
converters.toabjad = toabjad
function converters.abjadnumerals (n) return toabjad(n,false) end
function converters.abjadnodotnumerals(n) return toabjad(n,true ) end
implement {
name = "abjadnumerals",
actions = { toabjad, context },
arguments = { "integer", false }
}
implement {
name = "abjadnodotnumerals",
actions = { toabjad, context },
arguments = { "integer", true }
}
-- -- - hebrew and jiddish -- -- --
local trace_hebrew trackers.register("converters.hebrew", function(v)
trace_hebrew = v
end)
local list = {
{ 400, "ת" }, { 300, "ש" }, { 200, "ר" }, { 100, "ק" },
{ 90, "צ" }, { 80, "פ" }, { 70, "ע" }, { 60, "ס "}, { 50, "נ" }, { 40, "מ" }, { 30, "ל" }, { 20, "כ" }, { 10, "י" },
{ 9, "ט" }, { 8, "ח" }, { 7, "ז", }, { 6, "ו", }, { 5, "ה" }, { 4, "ד" }, { 3, "ג" }, { 2, "ב" }, { 1, "א" },
}
local special = {
[15] = "ט״ו", -- exception: avoid mixup with God יה
[16] = "ט״ז", -- exception: avoid mixup with God יו
}
local function tohebrew(n,gershayim,geresh)
local split = { }
local size = 0
while n > 1000 do
size = size + 1
split[size] = n % 1000
n = floor(n/1000)
end
size = size + 1
split[size] = n
for i=1,size do
local t = { }
local n = 0
local s = split[i]
while s > 0 do
for i=1,#list do
::again::
local li = list[i]
local l1 = li[1]
local s1 = special[l1]
if s1 then
s = s - l1
n = n + 1
t[n] = s1
goto again
elseif s >= l1 then
s = s - l1
n = n + 1
t[n] = li[2]
goto again
end
end
end
::done::
split[i] = t
end
if gershayim then
for i=1,size do
local si = split[i]
local ni = #si
if ni >= 2 then
local s = "״"
insert(split[i],ni,trace_hebrew and ("{\\red "..s.."}") or s)
end
end
end
if geresh then
for i=2,#split do
local s = rep("׳",i-1)
insert(split[i],trace_hebrew and ("{\\blue "..s.."}") or s)
end
end
for i=1,size do
split[i] = concat(split[i])
end
return concat(reverse(split))
end
converters.tohebrew = tohebrew
converters.hebrewnumerals = converters.tohebrew
-- converters['alphabetic:hb'] = converters.hebrewnumerals
interfaces.implement {
name = "hebrewnumerals",
actions = { tohebrew, context },
arguments = { "integer", true, true }
}
-- -- --
local vector = {
normal = {
[0] = "〇",
[1] = "一",
[2] = "二",
[3] = "三",
[4] = "四",
[5] = "五",
[6] = "六",
[7] = "七",
[8] = "八",
[9] = "九",
[10] = "十",
[100] = "百",
[1000] = "千",
[10000] = "万",
[100000000] = "亿",
},
cap = {
[0] = "零",
[1] = "壹",
[2] = "贰",
[3] = "叁",
[4] = "肆",
[5] = "伍",
[6] = "陆",
[7] = "柒",
[8] = "捌",
[9] = "玖",
[10] = "拾",
[100] = "佰",
[1000] = "仟",
[10000] = "萬",
[100000000] = "亿",
},
all = {
[0] = "〇",
[1] = "一",
[2] = "二",
[3] = "三",
[4] = "四",
[5] = "五",
[6] = "六",
[7] = "七",
[8] = "八",
[9] = "九",
[10] = "十",
[20] = "廿",
[30] = "卅",
[100] = "百",
[1000] = "千",
[10000] = "万",
[100000000] = "亿",
}
}
local function tochinese(n,name) -- normal, caps, all, date
-- improved version by Li Yanrui, Song Yihan
local result, r = { }, 0
if name == "date" then
-- We could do some number juggling instead but this is fast enough. There is
-- no error checking here so we assume a proper year. Maybe a better name is
-- asis (so that it can be used for more than dates).
local vector = vector.normal
for s in gmatch(tostring(n),".") do
r = r + 1 ; result[r] = vector[tonumber(s)]
end
return concat(result)
end
local vector = vector[name] or vector.normal
while true do
if n == 0 then
break
elseif n >= 100000000 then
local m = floor(n/100000000)
r = r + 1 ; result[r] = tochinese(m,name)
r = r + 1 ; result[r] = vector[100000000]
local z = n - m * 100000000
if z > 0 and z < 10000000 then r = r + 1 ; result[r] = vector[0] end
n = n % 100000000
elseif n >= 10000000 then
local m = floor(n/10000)
r = r + 1 ; result[r] = tochinese(m,name)
r = r + 1 ; result[r] = vector[10000]
local z = n - m * 10000
if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
n = n % 10000
elseif n >= 1000000 then
local m = floor(n/10000)
r = r + 1 ; result[r] = tochinese(m,name)
r = r + 1 ; result[r] = vector[10000]
local z = n - m * 10000
if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
n = n % 10000
elseif n >= 100000 then
local m = floor(n/10000)
r = r + 1 ; result[r] = tochinese(m,name)
r = r + 1 ; result[r] = vector[10000]
local z = n - m * 10000
if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
n = n % 10000
elseif n >= 10000 then
local m = floor(n/10000)
r = r + 1 ; result[r] = vector[m]
r = r + 1 ; result[r] = vector[10000]
local z = n - m * 10000
if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
n = n % 10000
elseif n >= 1000 then
local m = floor(n/1000)
r = r + 1 ; result[r] = vector[m]
r = r + 1 ; result[r] = vector[1000]
local z = n - m * 1000
if z > 0 and z < 100 then r = r + 1 ; result[r] = vector[0] end
n = n % 1000
elseif n >= 100 then
local m = floor(n/100)
r = r + 1 ; result[r] = vector[m]
r = r + 1 ; result[r] = vector[100]
local z = n - m * 100
if z > 0 and z < 10 then r = r + 1 ; result[r] = vector[0] end
n = n % 100
elseif n >= 10 then
local m = floor(n/10)
if m > 1 and vector[m*10] then
r = r + 1 ; result[r] = vector[m*10]
else
r = r + 1 ; result[r] = vector[m]
r = r + 1 ; result[r] = vector[10]
end
n = n % 10
else
r = r + 1 ; result[r] = vector[n]
break
end
end
if (result[1] == vector[1] and result[2] == vector[10]) then
result[1] = ""
end
return concat(result)
end
-- local t = { 1,10,15,25,35,45,11,100,111,1111,10000,11111,100000,111111,1111111,11111111,111111111,100000000,1111111111,11111111111,111111111111,1111111111111 }
-- for k=1,#t do
-- local v = t[k]
-- print(v,tochinese(v),tochinese(v,"all"),tochinese(v,"cap"))
-- end
converters.tochinese = tochinese
function converters.chinesenumerals (n,how) return tochinese(n,how or "normal") end
function converters.chinesecapnumerals(n) return tochinese(n,"cap") end
function converters.chineseallnumerals(n) return tochinese(n,"all") end
function converters.chinesedatenumerals(n) return tochinese(n,"date") end
converters['cn'] = converters.chinesenumerals
converters['cn-c'] = converters.chinesecapnumerals
converters['cn-a'] = converters.chineseallnumerals
converters['cn-d'] = converters.chinesedatenumerals
implement {
name = "chinesenumerals",
actions = { tochinese, context },
arguments = { "integer", "string" }
}
-- this is a temporary solution: we need a better solution when we have
-- more languages
converters['a'] = converters.characters
converters['A'] = converters.Characters
converters['AK'] = converters.Characters -- obsolete
converters['KA'] = converters.Characters -- obsolete
function converters.spanishnumerals (n) return alphabetic(n,"es") end
function converters.Spanishnumerals (n) return Alphabetic(n,"es") end
function converters.sloveniannumerals(n) return alphabetic(n,"sl") end
function converters.Sloveniannumerals(n) return Alphabetic(n,"sl") end
function converters.russiannumerals (n) return alphabetic(n,"ru") end
function converters.Russiannumerals (n) return Alphabetic(n,"ru") end
converters['alphabetic:es'] = converters.spanishnumerals
converters['alphabetic:sl'] = converters.sloveniannumerals
converters['alphabetic:ru'] = converters.russiannumerals
converters['Alphabetic:es'] = converters.Spanishnumerals
converters['Alphabetic:sl'] = converters.Sloveniannumerals
converters['Alphabetic:ru'] = converters.Russiannumerals
-- bonus
converters['a:es'] = converters.spanishnumerals
converters['a:sl'] = converters.sloveniannumerals
converters['a:ru'] = converters.russiannumerals
converters['A:es'] = converters.Spanishnumerals
converters['A:sl'] = converters.Sloveniannumerals
converters['A:ru'] = converters.Russiannumerals
-- end of bonus
converters.sequences = converters.sequences or { }
local sequences = converters.sequences
storage.register("converters/sequences", sequences, "converters.sequences")
function converters.define(name,set) -- ,language)
-- if language then
-- name = name .. ":" .. language
-- end
sequences[name] = settings_to_array(set)
end
function converters.max(name)
local s = sequences[name]
return s and #s or 0
end
implement {
name = "defineconversion",
actions = converters.define,
arguments = "2 strings",
}
implement {
name = "nofconversions",
actions = { converters.max, context },
arguments = "string",
}
local function convert(method,n,language)
local converter = language and converters[method..":"..language] or converters[method]
if converter then
return converter(n)
else
local lowermethod = lower(method)
local linguistic = counters[lowermethod]
if linguistic then
return do_alphabetic(n,linguistic,lowermethod == method and lowercharacter or uppercharacter)
end
local sequence = sequences[method]
if sequence then
local max = #sequence
if n > max then
return sequence[(n-1) % max + 1]
else
return sequence[n]
end
end
return n
end
end
converters.convert = convert
local function valid(method,language)
return converters[method..":"..language] or converters[method] or sequences[method]
end
implement {
name = "doifelseconverter",
actions = { valid, commands.doifelse },
arguments = "2 strings",
}
implement {
name = "checkedconversion",
actions = { convert, context },
arguments = { "string", "integer" }
}
-- hebrew data conversion
local gregorian_to_hebrew do
-- The next code is based on the c code at https://github.com/hebcal/hebcal
--
-- Hebcal : A Jewish Calendar Generator
-- Copyright : 1994 - 2004 Danny Sadinoff, 2002 Michael J. Radwin
-- License : GPL
--
-- Because we only need simple dates, we use part of the code. There is more
-- at that github place.
--
-- The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
-- The Gregorian date Sunday, December 31, 1 BC is imaginary.
--
-- The code is luafied and a little different because we have no assignments
-- in loops and such. We could speed up the code but then we divert from the
-- original. This is not that critical anyway.
local NISAN = 1
local IYYAR = 2
local SIVAN = 3
local TAMUZ = 4
local AV = 5
local ELUL = 6
local TISHREI = 7
local CHESHVAN = 8
local KISLEV = 9
local TEVET = 10
local SHVAT = 11
local ADAR_I = 12
local ADAR_II = 13
local mmap = {
KISLEV,
TEVET,
SHVAT,
ADAR_I,
NISAN,
IYYAR,
SIVAN,
TAMUZ,
TISHREI,
TISHREI,
TISHREI,
CHESHVAN
}
local function greg2abs(year,month,day)
local y = year - 1
return y * 365 + div(y,4)- div(y,100) + div(y,400) + os.nofdays(year,month,day)
end
local function abs2greg(abs)
local d0 = abs - 1
local n400 = div(d0, 146097)
local d1 = mod(d0, 146097)
local n100 = div(d1, 36524)
local d2 = mod(d1, 36524)
local n4 = div(d2, 1461)
local d3 = mod(d2, 1461)
local n1 = div(d3, 365)
local day = mod(d3, 365) + 1
local year = 400 * n400 + 100 * n100 + 4 * n4 + n1
if n100 == 4 or n1 == 4 then
return year, 12, 31
else
year = year + 1
month = 1
while true do
local mlen = os.nofdays(year,month)
if mlen < day then
day = day - mlen
month = month + 1
else
break
end
end
return year, month, day
end
end
local function hebrew_leapyear(year)
return mod(1 + year * 7, 19) < 7
end
local function hebrew_months_in_year(year)
return hebrew_leapyear(year) and 13 or 12
end
local function hebrew_elapsed_days(year)
local y = year - 1
local m_elapsed = 235 * div(y,19) + 12 * mod(y,19) + div(((mod(y,19) * 7) + 1),19)
local p_elapsed = 204 + 793 * mod(m_elapsed,1080)
local h_elapsed = 5 + 12 * m_elapsed + 793 * div(m_elapsed,1080) + div(p_elapsed,1080)
local parts = mod(p_elapsed,1080) + 1080 * mod(h_elapsed,24)
local day = 1 + 29 * m_elapsed + div(h_elapsed,24)
local d = mod(day,7)
local alt_day = day
if parts >= 19440
or (parts >= 9924 and d == 2 and not (hebrew_leapyear(year)))
or (parts >= 16789 and d == 1 and hebrew_leapyear(y )) then
alt_day = alt_day + 1
end
d = mod(alt_day,7)
if d == 0 or d == 3 or d == 5 then
alt_day = alt_day + 1
end
return alt_day
end
local function days_in_hebrew_year(year)
return hebrew_elapsed_days(year + 1) - hebrew_elapsed_days(year)
end
local function long_cheshvan(year)
return mod(days_in_hebrew_year(year),10) == 5
end
local function short_kislev(year)
return mod(days_in_hebrew_year(year),10) == 3
end
local function max_days_in_heb_month(month,year)
if month == IYYAR or month == TAMUZ or month == ELUL or month == TEVET or month == ADAR_II or
(month == ADAR_I and not hebrew_leapyear(year)) or
(month == CHESHVAN and not long_cheshvan(year)) or
(month == KISLEV and short_kislev (year)) then
return 29
else
return 30
end
end
local function hebrew2abs(year,month,day)
if month < TISHREI then
for m=TISHREI, hebrew_months_in_year(year), 1 do
day = day + max_days_in_heb_month(m,year)
end
for m=NISAN, month - 1, 1 do
day = day + max_days_in_heb_month(m,year)
end
else
for m=TISHREI, month - 1, 1 do
day = day + max_days_in_heb_month(m,year)
end
end
return hebrew_elapsed_days(year) - 1373429 + day
end
local function abs2hebrew(abs)
local yy, mm, dd = abs2greg(abs)
local day = 1
local month = TISHREI
local year = 3760 + yy
while abs >= hebrew2abs(year+1,month,day) do
year = year + 1
end
if year >= 4635 and year < 10666 then
month = mmap[mm]
end
while abs > hebrew2abs(year,month,max_days_in_heb_month(month,year)) do
month = mod(month,hebrew_months_in_year(year)) + 1
end
day = abs - hebrew2abs(year,month,1) + 1
return year, month, day
end
-- months = { "ניסן" "אייר" "סיון" "תמוז" "אב" "אלול" "תשרי" "חשון" "כסלו" "טבת" "שבט" }
gregorian_to_hebrew = function(y,m,d)
return abs2hebrew(greg2abs(y,m,d))
end
converters.gregorian_to_hebrew = gregorian_to_hebrew
end
local gregorian_to_jalali, jalali_to_gregorian do
-- Well, since the one asking for this didn't test it the following code is not
-- enabled.
--
-- -- This Lua version is based on a Javascript by Behdad Esfahbod which in turn
-- -- is based on GPL'd code by Roozbeh Pournader of the The FarsiWeb Project
-- -- Group: http://www.farsiweb.info/jalali/jalali.js.
-- --
-- -- We start tables at one, I kept it zero based in order to stay close to
-- -- the original.
-- --
-- -- Conversion by Hans Hagen
local g_days_in_month = { [0] = 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
local j_days_in_month = { [0] = 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 }
gregorian_to_jalali = function(gy,gm,gd)
local jy, jm, jd, g_day_no, j_day_no, j_np, i
gy, gm, gd = gy - 1600, gm - 1, gd - 1
g_day_no = 365*gy + div((gy+3),4) - div((gy+99),100) + div((gy+399),400)
i = 0
while i < gm do
g_day_no = g_day_no + g_days_in_month[i]
i = i + 1
end
if (gm>1 and ((gy%4==0 and gy%100~=0) or (gy%400==0))) then
g_day_no = g_day_no + 1
end
g_day_no = g_day_no + gd
j_day_no = g_day_no - 79
j_np = div(j_day_no,12053)
j_day_no = mod(j_day_no,12053)
jy = 979 + 33*j_np + 4*div(j_day_no,1461)
j_day_no = mod(j_day_no,1461)
if j_day_no >= 366 then
jy = jy + div((j_day_no-1),365)
j_day_no = mod((j_day_no-1),365)
end
i = 0
while i < 11 and j_day_no >= j_days_in_month[i] do
j_day_no = j_day_no - j_days_in_month[i]
i = i + 1
end
jm = i + 1
jd = j_day_no + 1
return jy, jm, jd
end
jalali_to_gregorian = function(jy,jm,jd)
local gy, gm, gd, g_day_no, j_day_no, leap, i
jy, jm, jd = jy - 979, jm - 1, jd - 1
j_day_no = 365*jy + div(jy,33)*8 + div((mod(jy,33)+3),4)
for i=0,jm-1,1 do
j_day_no = j_day_no + j_days_in_month[i]
end
j_day_no = j_day_no + jd
g_day_no = j_day_no + 79
gy = 1600 + 400*div(g_day_no,146097)
g_day_no = mod(g_day_no, 146097)
leap = 1
if g_day_no >= 36525 then
g_day_no = g_day_no - 1
gy = gy + 100*div(g_day_no,36524)
g_day_no = mod(g_day_no, 36524)
if g_day_no >= 365 then
g_day_no = g_day_no + 1
else
leap = 0
end
end
gy = gy + 4*div(g_day_no,1461)
g_day_no = mod(g_day_no, 1461)
if g_day_no >= 366 then
leap = 0
g_day_no = g_day_no - 1
gy = gy + div(g_day_no, 365)
g_day_no = mod(g_day_no, 365)
end
i = 0
while true do
local d = g_days_in_month[i] + ((i == 1 and leap) or 0)
if g_day_no >= d then
g_day_no = g_day_no - d
i = i + 1
else
break
end
end
gm = i + 1
gd = g_day_no + 1
return gy, gm, gd
end
-- local function test(yg,mg,dg,yj,mj,dj)
-- local y1, m1, d1 = jalali_to_gregorian(yj,mj,dj)
-- local y2, m2, d2 = gregorian_to_jalali(yg,mg,dg)
-- print(y1 == yg and m1 == mg and d1 == dg, yg,mg,dg, y1,m1,d1)
-- print(y2 == yj and m2 == mj and d2 == dj, yj,mj,dj, y2,m2,d2)
-- end
-- test(1953,08,19, 1332,05,28)
-- test(1979,02,11, 1357,11,22)
-- test(2000,02,28, 1378,12,09)
-- test(2000,03,01, 1378,12,11)
-- test(2009,02,24, 1387,12,06)
-- test(2015,03,21, 1394,01,01)
-- test(2016,03,20, 1395,01,01)
converters.gregorian_to_jalali = gregorian_to_jalali
converters.jalali_to_gregorian = jalali_to_gregorian
end
-- -- more efficient but needs testing
-- local escapes = characters.filters.utf.private.escapes
-- local function do_alphabetic(n,mapping,chr)
-- local max = #mapping
-- if n > max then
-- do_alphabetic(floor((n-1)/max),mapping,chr)
-- n = (n-1)%max+1
-- end
-- n = chr(n,mapping)
-- context(escapes[n] or utfchar(n))
-- end
-- local lccodes, uccodes, safechar = characters.lccode, characters.uccode, commands.safechar
-- local function do_alphabetic(n,mapping,chr)
-- local max = #mapping
-- if n > max then
-- do_alphabetic(floor((n-1)/max),mapping,chr)
-- n = (n-1)%max+1
-- end
-- safechar(chr(n,mapping))
-- end
-- local function lowercased(n,mapping) return characters.lccode(mapping[n] or fallback) end
-- local function uppercased(n,mapping) return characters.uccode(mapping[n] or fallback) end
-- function converters.alphabetic(n,code)
-- do_alphabetic(n,counters[code] or counters.default,lowercased) -- lccode catches wrong tables
-- end
-- function converters.Alphabetic(n,code)
-- do_alphabetic(n,counters[code] or counters.default,uppercased)
-- end
local ordinals = {
english = function(n)
local two = n % 100
if two == 11 or two == 12 or two == 13 then
return "th"
else
local one = n % 10
if one == 1 then
return "st"
elseif one == 2 then
return "nd"
elseif one == 3 then
return "rd"
else
return "th"
end
end
end,
dutch = function(n)
return "e"
end,
french = function(n)
if n == 1 then
return "er"
else
return "e"
end
end,
}
ordinals.en = ordinals.english
ordinals.nl = ordinals.dutch
ordinals.fr = ordinals.french
function converters.ordinal(n,language)
local t = language and ordinals[language]
return t and t(n)
end
local function ctxordinal(n,language)
local t = language and ordinals[language]
local o = t and t(n)
context(n)
if o then
ctx_highordinalstr(o)
end
end
implement {
name = "ordinal",
actions = ctxordinal,
arguments = { "integer", "string" }
}
-- verbose numbers
local data = allocate()
local verbose = { data = data }
converters.verbose = verbose
-- verbose english
local words = {
[0] = "zero",
[1] = "one",
[2] = "two",
[3] = "three",
[4] = "four",
[5] = "five",
[6] = "six",
[7] = "seven",
[8] = "eight",
[9] = "nine",
[10] = "ten",
[11] = "eleven",
[12] = "twelve",
[13] = "thirteen",
[14] = "fourteen",
[15] = "fifteen",
[16] = "sixteen",
[17] = "seventeen",
[18] = "eighteen",
[19] = "nineteen",
[20] = "twenty",
[30] = "thirty",
[40] = "forty",
[50] = "fifty",
[60] = "sixty",
[70] = "seventy",
[80] = "eighty",
[90] = "ninety",
[100] = "hundred",
[1000] = "thousand",
[1000000] = "million",
[1000000000] = "billion",
[1000000000000] = "trillion",
}
local function translate(n,connector)
local w = words[n]
if w then
return w
end
local t = { }
local function compose_one(n)
local w = words[n]
if w then
t[#t+1] = w
return
end
local a, b = floor(n/100), n % 100
if a == 10 then
t[#t+1] = words[1]
t[#t+1] = words[1000]
elseif a > 0 then
t[#t+1] = words[a]
t[#t+1] = words[100]
-- don't say 'nine hundred zero'
if b == 0 then
return
end
end
if words[b] then
t[#t+1] = words[b]
else
a, b = floor(b/10), n % 10
t[#t+1] = words[a*10]
t[#t+1] = words[b]
end
end
local function compose_two(n,m)
if n > (m-1) then
local a, b = floor(n/m), n % m
if a > 0 then
compose_one(a)
end
t[#t+1] = words[m]
n = b
end
return n
end
n = compose_two(n,1000000000000)
n = compose_two(n,1000000000)
n = compose_two(n,1000000)
n = compose_two(n,1000)
if n > 0 then
compose_one(n)
end
return #t > 0 and concat(t,connector or " ") or tostring(n)
end
data.english = {
words = words,
translate = translate,
}
data.en = data.english
-- print(translate(11111111))
-- print(translate(2221101))
-- print(translate(1111))
-- print(translate(1218))
-- print(translate(1234))
-- print(translate(12345))
-- print(translate(12345678900000))
-- verbose spanish (unchecked)
local words = {
[1] = "uno",
[2] = "dos",
[3] = "tres",
[4] = "cuatro",
[5] = "cinco",
[6] = "seis",
[7] = "siete",
[8] = "ocho",
[9] = "nueve",
[10] = "diez",
[11] = "once",
[12] = "doce",
[13] = "trece",
[14] = "catorce",
[15] = "quince",
[16] = "dieciséis",
[17] = "diecisiete",
[18] = "dieciocho",
[19] = "diecinueve",
[20] = "veinte",
[21] = "veintiuno",
[22] = "veintidós",
[23] = "veintitrés",
[24] = "veinticuatro",
[25] = "veinticinco",
[26] = "veintiséis",
[27] = "veintisiete",
[28] = "veintiocho",
[29] = "veintinueve",
[30] = "treinta",
[40] = "cuarenta",
[50] = "cincuenta",
[60] = "sesenta",
[70] = "setenta",
[80] = "ochenta",
[90] = "noventa",
[100] = "ciento",
[200] = "doscientos",
[300] = "trescientos",
[400] = "cuatrocientos",
[500] = "quinientos",
[600] = "seiscientos",
[700] = "setecientos",
[800] = "ochocientos",
[900] = "novecientos",
[1000] = "mil",
[1000000] = "millón",
[1000000000] = "mil millones",
[1000000000000] = "billón",
}
local function translate(n,connector)
local w = words[n]
if w then
return w
end
local t = { }
local function compose_one(n)
local w = words[n]
if w then
t[#t+1] = w
return
end
-- a, b = hundreds, remainder
local a, b = floor(n/100), n % 100
-- one thousand
if a == 10 then
t[#t+1] = words[1]
t[#t+1] = words[1000]
-- x hundred (n.b. this will not give thirteen hundred because
-- compose_one(n) is only called after
-- n = compose(two(n, 1000))
elseif a > 0 then
t[#t+1] = words[a*100]
end
-- the remainder
if words[b] then
t[#t+1] = words[b]
else
-- a, b = tens, remainder
a, b = floor(b/10), n % 10
t[#t+1] = words[a*10]
t[#t+1] = "y"
t[#t+1] = words[b]
end
end
-- compose_two handles x billion, ... x thousand. When 1000 or less is
-- left, compose_one takes over.
local function compose_two(n,m)
if n > (m-1) then
local a, b = floor(n/m), n % m
if a > 0 then
compose_one(a)
end
t[#t+1] = words[m]
n = b
end
return n
end
n = compose_two(n,1000000000000)
n = compose_two(n,1000000000)
n = compose_two(n,1000000)
n = compose_two(n,1000)
if n > 0 then
compose_one(n)
end
return #t > 0 and concat(t,connector or " ") or tostring(n)
end
data.spanish = {
words = words,
translate = translate,
}
data.es = data.spanish
-- print(translate(31))
-- print(translate(101))
-- print(translate(199))
-- verbose swedish by Peter Kvillegard
do
local words = {
[0] = "noll",
[1] = "ett",
[2] = "två",
[3] = "tre",
[4] = "fyra",
[5] = "fem",
[6] = "sex",
[7] = "sju",
[8] = "åtta",
[9] = "nio",
[10] = "tio",
[11] = "elva",
[12] = "tolv",
[13] = "tretton",
[14] = "fjorton",
[15] = "femton",
[16] = "sexton",
[17] = "sjutton",
[18] = "arton",
[19] = "nitton",
[20] = "tjugo",
[30] = "trettio",
[40] = "fyrtio",
[50] = "femtio",
[60] = "sextio",
[70] = "sjuttio",
[80] = "åttio",
[90] = "nittio",
[100] = "hundra",
[10^3] = "tusen",
[10^6] = "miljon",
[10^9] = "miljard",
[10^12] = "biljon",
[10^15] = "biljard",
}
local function translate(n,connector)
local w = words[n]
if w then
return w
else
local t = { }
local l = 0
-- group of three digits to words, e.g. 123 -> etthundratjugotre
local function triplets(n)
if floor(n/100) > 0 then
l = l + 1 ; t[l] = words[floor(n/100)]
l = l + 1 ; t[l] = words[100]
end
if n%100 > 20 then
l = l + 1 ; t[l] = words[n%100-n%10]
if n%10 > 0 then
l = l + 1 ; t[l] = words[n%10]
end
elseif n%100 > 0 then
l = l + 1 ; t[l] = words[n%100]
end
end
-- loops through 10^15,10^12,...10^3, extracting groups of three digits
-- to make words from, then adding names for order of magnitude
for i=15,3,-3 do
local triplet = floor(n/10^i)%10^3
if triplet > 0 then
-- grammar: "en" instead of "ett"
if i > 3 and triplet == 1 then
l = l + 1 ; t[l] = "en"
else
triplets(triplet)
end
-- grammar: plural form of "millions" etc
l = l + 1 ; t[l] = words[10^i]
if i > 3 and triplet > 1 then
l = l + 1 ; t[l] = "er"
end
end
end
-- add last group of three numbers (no word for magnitude)
n = n%1000
if n > 0 then
triplets(n)
end
t = concat(t," ")
-- grammar: spacing for numbers < 10^6 and repeated letters
if n < 10^6 then
t = gsub(t,"%stusen%s","tusen")
t = gsub(t,"etttusen","ettusen")
end
return t
end
end
data.swedish = {
words = words,
translate = translate,
}
data.sv = data.swedish
end
-- verbose handler:
function converters.verbose.translate(n,language,connector)
local t = language and data[language]
return t and t.translate(n,connector) or n
end
local function verbose(n,language,connector)
local t = language and data[language]
context(t and t.translate(n,connector) or n)
end
implement {
name = "verbose",
actions = verbose,
arguments = { "integer", "string", "string" }
}
-- These are just helpers but not really for the tex end. Do we have to
-- use translate here?
local whitespace = lpegpatterns.whitespace
local word = lpegpatterns.utf8uppercharacter^-1 * (1-whitespace)^1
local pattern_one = Cs( whitespace^0 * word^-1 * P(1)^0)
local pattern_all = Cs((whitespace^1 + word)^1)
function converters.word (s) return s end -- dummies for typos
function converters.words(s) return s end -- dummies for typos
local function Word (s) return lpegmatch(pattern_one,s) or s end
local function Words(s) return lpegmatch(pattern_all,s) or s end
converters.Word = Word
converters.Words = Words
converters.upper = characters.upper
converters.lower = characters.lower
-- print(converters.Word("foo bar"))
-- print(converters.Word(" foo bar"))
-- print(converters.Word("123 foo bar"))
-- print(converters.Word(" 123 foo bar"))
-- print(converters.Words("foo bar"))
-- print(converters.Words(" foo bar"))
-- print(converters.Words("123 foo bar"))
-- print(converters.Words(" 123 foo bar"))
-- --
local v_day <const> = variables.day
local v_year <const> = variables.year
local v_month <const> = variables.month
local v_weekday <const> = variables.weekday
local v_referral <const> = variables.referral
local v_space <const> = variables.space
local v_MONTH = upper(v_month)
local v_WEEKDAY = upper(v_weekday)
local convert = converters.convert
local days = { -- not variables
"sunday",
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
}
local months = { -- not variables
"january",
"february",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december",
}
local monthmnems = { -- not variables
-- virtual table
}
local daymnems = { -- not variables
-- virtual table
}
setmetatableindex(days, function(t,k) return "unknown" end)
setmetatableindex(daymnems, function(t,k) return days[k] .. ":mnem" end)
setmetatableindex(months, function(t,k) return "unknown" end)
setmetatableindex(monthmnems, function(t,k) return months[k] .. ":mnem" end)
do
local function dayname(n)
ctx_labeltext(days[n])
end
local function daymnem(n)
ctx_labeltext(daymnems[n])
end
local function weekdayname(day,month,year)
ctx_labeltext(days[weekday(day,month,year)])
end
local function monthname(n)
ctx_labeltext(months[n])
end
local function monthmnem(n)
ctx_labeltext(monthmnems[n])
end
implement {
name = "dayname",
actions = dayname,
arguments = "integer",
}
implement {
name = "daymnem",
actions = daymnem,
arguments = "integer",
}
implement {
name = "weekdayname",
actions = weekdayname,
arguments = { "integer", "integer", "integer" }
}
implement {
name = "monthname",
actions = monthname,
arguments = "integer",
}
implement {
name = "monthmnem",
actions = monthmnem,
arguments = "integer",
}
-- todo : short week days
local f_monthlong = formatters["\\monthlong{%s}"]
local f_monthshort = formatters["\\monthshort{%s}"]
local f_daylong = formatters["\\daylong{%s}"]
local f_dayshort = formatters["\\dayshort{%s}"]
local f_weekday = formatters["\\weekday{%s}"]
local f_dayoftheweek = formatters["\\dayoftheweek{%s}{%s}{%s}"]
local function tomonthlong (m) return f_monthlong (tonumber(m) or 1) end
local function tomonthshort(m) return f_monthshort(tonumber(m) or 1) end
local function todaylong (d) return f_daylong (tonumber(d) or 1) end
local function todayshort (d) return f_dayshort (tonumber(d) or 1) end
local function toweekday (d) return f_weekday (tonumber(d) or 1) end
local function todayoftheweek(d,m,y)
return f_dayoftheweek(tonumber(d) or 1,tonumber(m) or 1,tonumber(y) or 2000)
end
addformatter(formatters,"monthlong", [[tomonthlong(%s)]], { tomonthlong = tomonthlong })
addformatter(formatters,"monthshort", [[tomonthshort(%s)]], { tomonthshort = tomonthshort })
addformatter(formatters,"daylong", [[todaylong(%s)]], { todaylong = todaylong })
addformatter(formatters,"dayshort", [[todayshort(%s)]], { todayshort = todayshort })
addformatter(formatters,"weekday", [[toweekday(%s)]], { toweekday = toweekday })
addformatter(formatters,"dayoftheweek",[[todayoftheweek(%s,%s,%s)]],{ todayoftheweek = todayoftheweek })
-- using %t is slower, even with caching as we seldom use > 3 items per epoch
local function toeyear (e) return osdate("%Y",tonumber(e)) end
local function toemonth (e) return osdate("%m",tonumber(e)) end
local function toeday (e) return osdate("%d",tonumber(e)) end
local function toeminute(e) return osdate("%M",tonumber(e)) end
local function toesecond(e) return osdate("%S",tonumber(e)) end
local function toemonthlong(e)
return f_monthlong(tonumber(osdate("%m",tonumber(e))))
end
local function toemonthshort(e)
return f_monthshort(tonumber(osdate("%m",tonumber(e))))
end
local function toedaylong(e)
return f_datlong(tonumber(osdate("%w",tonumber(e))))
end
local function toedayshort(e)
return f_dayshort(tonumber(osdate("%w",tonumber(e))))
end
local function toeweek(e) -- we run from 1-7 not 0-6
return tostring(tonumber(osdate("%w",tonumber(e)))+1)
end
local function toeweekday(e)
return f_weekday(tonumber(osdate("%w",tonumber(e)))+1)
end
local function toedate(format,e)
return osdate(format,tonumber(e))
end
addformatter(formatters,"eyear", [[toeyear(%s)]], { toeyear = toeyear })
addformatter(formatters,"emonth", [[toemonth(%s)]], { toemonth = toemonth })
addformatter(formatters,"eday", [[toeday(%s)]], { toeday = toeday })
addformatter(formatters,"eweek", [[toeweek(%s)]], { toeweek = toeweek })
addformatter(formatters,"eminute", [[toeminute(%s)]], { toeminute = toeminute })
addformatter(formatters,"esecond", [[toesecond(%s)]], { toesecond = toesecond })
addformatter(formatters,"emonthlong", [[toemonthlong(%s)]], { toemonthlong = toemonthlong })
addformatter(formatters,"emonthshort", [[toemonthshort(%s)]], { toemonthshort = toemonthshort })
addformatter(formatters,"edaylong", [[toedaylong(%s)]], { toedaylong = toedaylong })
addformatter(formatters,"edayshort", [[toedayshort(%s)]], { toedayshort = toedayshort })
addformatter(formatters,"eweekday", [[toeweekday(%s)]], { toeweekday = toeweekday })
addformatter(formatters,"edate", [[toedate(%s,%s)]], { toedate = toedate })
end
-- a prelude to a function that we can use at the lua end
-- day:ord month:mmem
-- j and jj obsolete
local spaced = {
[v_year] = true,
[v_month] = true,
[v_MONTH] = true,
[v_day] = true,
[v_weekday] = true,
[v_WEEKDAY] = true,
}
local dateconverters = {
["hebrew:to"] = gregorian_to_hebrew,
["jalali:to"] = gregorian_to_jalali,
["jalali:from"] = jalali_to_gregorian,
}
local variants = {
mnem = {
month = monthmnems,
day = daymnems,
},
hebrew = {
month = setmetatableindex(function(t,k) return months[k] .. ":hebrew" end),
day = setmetatableindex(function(t,k) return days [k] .. ":hebrew" end),
},
jalali = {
month = setmetatableindex(function(t,k) return months[k] .. ":jalali" end),
day = setmetatableindex(function(t,k) return days [k] .. ":jalali" end),
},
}
local packed = {
["cn"] = true,
["jp"] = true,
}
do
local function currentdate(str,currentlanguage,year,month,day) -- second argument false : no label
local list = utilities.parsers.settings_to_array(str)
local splitlabel = languages.labels.split or string.itself -- we need to get the loading order right
-- local year = tex.year
-- local month = tex.month
-- local day = tex.day
local auto = true
if currentlanguage == "" then
currentlanguage = false
end
for i=1,#list do
local entry = list[i]
local convert = dateconverters[entry]
if convert then
year, month, day = convert(year,month,day)
else
local tag, plus = splitlabel(entry)
local ordinal, mnemonic, whatordinal, highordinal = false, false, nil, false
if not tag then
tag = entry
elseif plus == "+" or plus == "ord" then
ordinal = true
elseif plus == "++" or plus == "highord" then
ordinal = true
highordinal = true
elseif plus then -- mnem MNEM etc
mnemonic = variants[plus]
end
if not auto and not packed[currentlanguage] and spaced[tag] then
ctx_space()
end
auto = false
if tag == v_year or tag == "y" or tag == "Y" then
if plus then
plus = converters[plus]
end
if plus then
context(plus(year))
elseif currentlanguage == false then
context(year)
else
ctx_convertnumber(v_year,year)
end
elseif tag == "yy" or tag == "YY" then
context("%02i",year % 100)
elseif tag == v_month or tag == "m" then
if currentlanguage == false then
context(Word(months[month]))
else
if type(mnemonic) == "table" then
mnemonic = mnemonic.month
end
if mnemonic then
ctx_labeltext(variables[mnemonic[month]])
else
ctx_labeltext(variables[months[month]])
end
end
elseif tag == v_MONTH then
if currentlanguage == false then
context(Word(variables[months[month]]))
else
if type(mnemonic) == "table" then
mnemonic = mnemonic.month
end
if mnemonic then
ctx_LABELTEXT(variables[mnemonic[month]])
else
ctx_LABELTEXT(variables[months[month]])
end
end
elseif tag == "mm" then
context("%02i",month)
elseif tag == "M" then
context(month)
elseif tag == v_day or tag == "d" then
if plus then
plus = converters[plus]
end
if plus then
context(plus(day))
elseif currentlanguage == false then
context(day)
else
ctx_convertnumber(v_day,day)
end
whatordinal = day
elseif tag == "dd" then
context("%02i",day)
whatordinal = day
elseif tag == "D" then
context(day)
whatordinal = day
elseif tag == v_weekday or tag == "w" then
local wd = weekday(day,month,year)
if currentlanguage == false then
context(Word(days[wd]))
else
if type(mnemonic) == "table" then
mnemonic = mnemonic.day
end
if mnemonic then
ctx_labeltext(variables[mnemonic[wd]])
else
ctx_labeltext(variables[days[wd]])
end
end
elseif tag == v_WEEKDAY then
local wd = weekday(day,month,year)
if currentlanguage == false then
context(Word(days[wd]))
else
if type(mnemonic) == "table" then
mnemonic = mnemonic.day
end
if mnemonic then
ctx_LABELTEXT(variables[mnemonic[wd]])
else
ctx_LABELTEXT(variables[days[wd]])
end
end
elseif tag == "W" then
context(weekday(day,month,year))
elseif tag == v_referral then
context("%04i%02i%02i",year,month,day)
elseif tag == v_space or tag == "\\ " then
ctx_space()
auto = true
elseif tag ~= "" then
context(tag)
auto = true
end
if ordinal and whatordinal then
if currentlanguage == false then
-- ignore
else
context[highordinal and "highordinalstr" or "ordinalstr"](converters.ordinal(whatordinal,currentlanguage))
end
end
end
end
end
implement {
name = "currentdate",
arguments = { "string", "string", "string", "integer", "integer", "integer" },
actions = function(pattern,default,language,year,month,day)
currentdate(
pattern == "" and default or pattern,
language == "" and false or language,
year, month, day
)
end,
}
local function todate(s,y,m,d)
if y or m or d then
return formatters["\\date[y=%s,m=%s,d=%s][%s]\\relax"](y or "",m or "",d or "",s or "")
else
return formatters["\\currentdate[%s]\\relax"](s)
end
end
addformatter(formatters,"date", [[todate(...)]], { todate = todate })
-- context("one: %4!date!","MONTH",2020,12,11) context.par()
-- context("one: %4!date!","month",2020,12,11) context.par()
-- context("one: %4!date!","year,-,mm,-,dd",2020,12,11) context.par()
-- context("two: %3!date!","MONTH",false,12) context.par()
-- context("two: %3!date!","month",false,12) context.par()
-- context("two: %3!date!","year,-,mm,-,dd",false,12) context.par()
end
implement {
name = "unihex",
arguments = "integer",
actions = { formatters["U+%05X"], context },
}
-- totime might move to utilities.parsers as more general helper
local n = R("09")^1 / tonumber -- lpegpatterns.digit
-- local p = Cf( Ct("")
-- -- year is mandate, month and day are optional
-- * Cg(Cc("year") * n)
-- * S("-/")^-1
-- * Cg(Cc("month") * (n + Cc(1)))
-- * S("-/")^-1
-- * Cg(Cc("day") * (n + Cc(1)))
-- -- time is optional, hour and minuta are mandate, seconds are optional
-- * (
-- whitespace^0
-- * P("T")^-1
-- * whitespace^0
-- * Cg(Cc("hour") * n)
-- * P(":")^-1
-- * Cg(Cc("min") * n)
-- * P(":")^-1
-- * Cg(Cc("sec") * (n + Cc(0)))
-- )^-1
-- -- zone is optional, hour is mandate, minutes are optional
-- * (
-- whitespace^0
-- * Cg(Cc("tzs") * (P("+") * Cc(1) + P("-") * Cc(-1) + Cc(1)))
-- * whitespace^0
-- * Cg(Cc("tzh") * n)
-- * P(":")^-1
-- * Cg(Cc("tzm") * (n + Cc(0)))
-- )^-1
-- , rawset)
local p = Ct("") * (
-- year is mandate, month and day are optional
(Cc("year") * n) % rawset
* S("-/")^-1
* (Cc("month") * (n + Cc(1))) % rawset
* S("-/")^-1
* (Cc("day") * (n + Cc(1))) % rawset
-- time is optional, hour and minuta are mandate, seconds are optional
* (
whitespace^0
* P("T")^-1
* whitespace^0
* (Cc("hour") * n) % rawset
* P(":")^-1
* (Cc("min") * n) % rawset
* P(":")^-1
* (Cc("sec") * (n + Cc(0))) % rawset
)^-1
-- zone is optional, hour is mandate, minutes are optional
* (
whitespace^0
* (Cc("tzs") * (P("+") * Cc(1) + P("-") * Cc(-1) + Cc(1))) % rawset
* whitespace^0
* (Cc("tzh") * n) % rawset
* P(":")^-1
* (Cc("tzm") * (n + Cc(0))) % rawset
)^-1
)
function converters.totime(s)
if not s then
return
elseif type(s) == "table" then
return s
elseif type(s) == "string" then
local t = lpegmatch(p,s)
if not t then
logs.report("system","invalid time specification %a",s)
elseif t.tzh then
local localtzh, localtzm = ostimezone(true)
t.hour = t.hour + localtzh - t.tzs * t.tzh
t.min = t.min + localtzm - t.tzs * t.tzm
end
return t
end
local n = tonumber(s)
if n and n >= 0 then
return osdate("*t",n)
end
end
function converters.settime(t)
if type(t) ~= "table" then
t = converters.totime(t)
end
if t then
texset("year", t.year or 1000)
texset("month", t.month or 1)
texset("day", t.day or 1)
texset("time", (t.hour or 0) * 60 + (t.min or 0))
end
end
-- taken from x-asciimath (where we needed it for a project)
local d_one = lpegpatterns.digit
local d_two = d_one * d_one
local d_three = d_two * d_one
local d_four = d_three * d_one
local d_split = P(-1) + Carg(2) * (lpegpatterns.period /"")
local d_spaced = (Carg(1) * d_three)^1
local digitized_1 = Cs ( (
d_three * d_spaced * d_split +
d_two * d_spaced * d_split +
d_one * d_spaced * d_split +
P(1)
)^1 )
local p_fourbefore = d_four * d_split
local p_fourafter = d_four * P(-1)
local p_beforesplit = d_three * d_spaced^0 * d_split
+ d_two * d_spaced^0 * d_split
+ d_one * d_spaced^0 * d_split
+ d_one * d_split
local p_aftersplit = p_fourafter
+ d_three * d_spaced
+ d_two * d_spaced
+ d_one * d_spaced
local digitized_2 = Cs (
p_fourbefore * (p_aftersplit^0) +
p_beforesplit * ((p_aftersplit + d_one^1)^0)
)
local p_fourbefore = d_four * d_split
local p_fourafter = d_four
local d_spaced = (Carg(1) * (d_three + d_two + d_one))^1
local p_aftersplit = p_fourafter * P(-1)
+ d_three * d_spaced * P(1)^0
+ d_one^1
local digitized_3 = Cs((p_fourbefore + p_beforesplit) * p_aftersplit^0)
local digits_space = utfchar(0x2008)
local splitmethods = {
digitized_1,
digitized_2,
digitized_3,
}
local replacers = table.setmetatableindex(function(t,k)
local v = lpeg.replacer(".",k)
t[k] = v
return v
end)
function converters.spaceddigits(settings,data)
local data = tostring(data or settings.data or "")
if data ~= "" then
local method = settings.method
local split = splitmethods[tonumber(method) or 1]
if split then
local symbol = settings.symbol
local separator = settings.separator
if not symbol or symbol == "" then
symbol = "."
end
if type(separator) ~= "string" or separator == "" then
separator = digits_space
end
local result = lpegmatch(split,data,1,separator,symbol)
if not result and symbol ~= "." then
result = lpegmatch(replacers[symbol],data)
end
if result then
-- print(method,symbol,separator,data,result)
return result
end
end
end
return str
end
-- method 2 : split 3 before and 3 after
-- method 3 : split 3 before and 3 after with > 4 before
-- symbols is extra split (in addition to period)
-- local setup = { splitmethod = 3, symbol = "," }
-- local setup = { splitmethod = 2, symbol = "," }
-- local setup = { splitmethod = 1, symbol = "," }
--
-- local t = {
-- "0.00002",
-- "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678", "123456789",
-- "1.1",
-- "12.12",
-- "123.123",
-- "1234.123",
-- "1234.1234",
-- "12345.1234",
-- "1234.12345",
-- "12345.12345",
-- "123456.123456",
-- "1234567.1234567",
-- "12345678.12345678",
-- "123456789.123456789",
-- "0.1234",
-- "1234.0",
-- "1234.00",
-- "0.123456789",
-- "100.00005",
-- "0.80018",
-- "10.80018",
-- "100.80018",
-- "1000.80018",
-- "10000.80018",
-- }
--
-- for i=1,#t do
-- print(formatters["%-20s : [%s]"](t[i],converters.spaceddigits(setup,t[i])))
-- end
implement {
name = "spaceddigits",
actions = { converters.spaceddigits, context },
arguments = {
{
{ "symbol" },
{ "separator" },
{ "data" },
{ "method" },
}
}
}
local function field(n) return context(osdate("*t")[n]) end
implement { name = "actualday", public = true, actions = function() field("day") end }
implement { name = "actualmonth", public = true, actions = function() field("month") end }
implement { name = "actualyear", public = true, actions = function() field("year") end }
implement {
name = "uuid",
public = true,
actions = { os.uuid, context },
}
[-- Attachment #3: Type: text/plain, Size: 511 bytes --]
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-13 19:09 ` Wolfgang Schuster
@ 2025-01-13 20:33 ` Hans Hagen
2025-01-14 12:08 ` autumnus
0 siblings, 1 reply; 11+ messages in thread
From: Hans Hagen @ 2025-01-13 20:33 UTC (permalink / raw)
To: Wolfgang Schuster, mailing list for ConTeXt users
On 1/13/2025 8:09 PM, Wolfgang Schuster wrote:
>
>
> Am 13.01.2025 um 19:02 schrieb Hans Hagen:
>> On 1/13/2025 5:43 PM, Wolfgang Schuster wrote:
>>> Am 12.01.2025 um 06:16 schrieb autumnus:
>>>> Thank you for your explanation.
>>>> Regarding the space after the month,
>>>> will it be added to the ConTeXt in the future?
>>>> I'm worried that after I patch it,
>>>> it will be overwritten when I update it later.
>>>
>>> It depends whether Hans includes the fix or not.
>>
>> You mean this?
>>
>> \c!date={\v!year,年,\space,\v!month,\v!day,日}
>>
>> It also depends on Tomas who deals with languages,
>
> No, I sent a patched core-con.lmt in a previous mail where I added
>
> local packed = { ["cn"] = true }
>
> on line 1881 and changed line 1916 from
>
> if not auto and spaced[tag] then
>
> to
>
> if not auto and not packed[currentlanguage] and spaced[tag] then
ah, ok, missed that one ... sure i'll patch
Hans
-----------------------------------------------------------------
Hans Hagen | PRAGMA ADE
Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
* [NTG-context] Re: Weird date output
2025-01-13 20:33 ` Hans Hagen
@ 2025-01-14 12:08 ` autumnus
0 siblings, 0 replies; 11+ messages in thread
From: autumnus @ 2025-01-14 12:08 UTC (permalink / raw)
To: ntg-context
There should be two changes to be made here:
One is a patch added by Wolfgang, which fixes the extra space for dates in the current Chinese environment.
One is that in the current environment, the format of the Chinese date should be modified to:
\currentdate[year,年,M,月,day,日] (output: 2025年1月14日)
( Because the current date format is a mix of Chinese characters and numbers. : 2025年 一月 14日)
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://mailman.ntg.nl/mailman3/lists/ntg-context.ntg.nl
webpage : https://www.pragma-ade.nl / https://context.aanhet.net (mirror)
archive : https://github.com/contextgarden/context
wiki : https://wiki.contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-01-14 12:10 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-11 5:08 [NTG-context] Weird date output autumnus
2025-01-11 17:17 ` [NTG-context] " Wolfgang Schuster
2025-01-12 5:16 ` autumnus
2025-01-12 11:11 ` Tomáš Hála
2025-01-12 13:27 ` autumnus
2025-01-12 13:31 ` autumnus
2025-01-13 16:43 ` Wolfgang Schuster
2025-01-13 18:02 ` Hans Hagen
2025-01-13 19:09 ` Wolfgang Schuster
2025-01-13 20:33 ` Hans Hagen
2025-01-14 12:08 ` autumnus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).