Improving on your code:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\int_new:N \mytest_date_day_int
\int_new:N \mytest_date_month_int
\int_new:N \mytest_date_year_int
\cs_new_protected:Npn \mytest_date_parse:n #1
{
\__mytest_date_parse:www #1 \q_stop
}
\cs_new_protected:Npn \__mytest_date_parse:www #1-#2-#3 \q_stop
{
\int_set:Nn \mytest_date_year_int {#1}
\int_set:Nn \mytest_date_month_int {#2}
\int_set:Nn \mytest_date_day_int {#3}
}
\keys_define:nn { my-test } {
date .code:n = { \mytest_date_parse:n { #1 } },
}
\NewDocumentCommand \Information { m } {
\keys_set:nn { my-test } { #1 }
}
\NewDocumentCommand \PrintDate { } {
Date:\nobreakspace
\int_use:N \mytest_date_day_int
\slash
\int_use:N \mytest_date_month_int
\slash
\int_use:N \mytest_date_year_int
}
\ExplSyntaxOff
\Information{
date = 2015-02-10,
}
\begin{document}
\PrintDate
\end{document}
It's better to split off the .code:n
bit with the actual implementation. There's no need to define the parser macro with six arguments, as three are predetermined.
Don't forget that functions performing assignments should be protected
.
Here's a check that the date is in ISO format: YYYY-MM-DD (but it allows month and year to be one digit); l3regex
is the easiest tool. In case the date is invalid, 0/0/0
is printed, but it is easy to add a suitable error message.
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\int_new:N \mytest_date_day_int
\int_new:N \mytest_date_month_int
\int_new:N \mytest_date_year_int
\cs_new_protected:Npn \mytest_date_parse:n #1
{
\regex_match:nnTF { \A \d{4}-\d{1,2}-\d{1,2} \Z } { #1 }
{
\__mytest_date_parse:www #1 \q_stop
}
{
\__mytest_date_parse:www 0000-00-00 \q_stop
}
}
\cs_new:Npn \__mytest_date_parse:www #1-#2-#3 \q_stop
{
\int_set:Nn \mytest_date_year_int {#1}
\int_set:Nn \mytest_date_month_int {#2}
\int_set:Nn \mytest_date_day_int {#3}
}
\keys_define:nn { my-test } {
date .code:n = { \mytest_date_parse:n {#1} },
}
\NewDocumentCommand \Information { m } {
\keys_set:nn { my-test } { #1 }
}
\NewDocumentCommand \PrintDate { } {
Date:\nobreakspace
\int_use:N \mytest_date_day_int
\slash
\int_use:N \mytest_date_month_int
\slash
\int_use:N \mytest_date_year_int
}
\ExplSyntaxOff
\Information{
date = 2015-02-10,
}
\begin{document}
\PrintDate
\Information{date=201-1-1}
\PrintDate
\Information{date=2015-1}
\PrintDate
\Information{date=2015/1/1}
\PrintDate
\end{document}
The regex means: the entire string (\A
and \Z
represent start and end) should consist of four digits (\d{4}
), a hyphen, one to two digits \d{1,2}
, a hyphen and again one to two digits. Any other format will return false.
A further version that accepts also date=20150101
, that is a string of eight digits and splits the parsing into the two cases.
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\int_new:N \mytest_date_day_int
\int_new:N \mytest_date_month_int
\int_new:N \mytest_date_year_int
\cs_new_protected:Npn \mytest_date_validate_parse:n #1
{
\regex_match:nnTF { \A \d{4}-\d{1,2}-\d{1,2} \Z } { #1 }
{
\__mytest_date_parse:www #1 \q_stop
}
{
\regex_match:nnTF { \A \d{8} \Z } { #1 }
{
\__mytest_date_parse:nnnnnnnn #1
}
{
\__mytest_date_parse:nnnnnnnn 00000000
}
}
}
\cs_new:Npn \__mytest_date_parse:www #1-#2-#3 \q_stop
{
\int_set:Nn \mytest_date_year_int {#1}
\int_set:Nn \mytest_date_month_int {#2}
\int_set:Nn \mytest_date_day_int {#3}
}
\cs_new:Nn \__mytest_date_parse:nnnnnnnn
{
\int_set:Nn \mytest_date_year_int {#1#2#3#4}
\int_set:Nn \mytest_date_month_int {#5#6}
\int_set:Nn \mytest_date_day_int {#7#8}
}
\keys_define:nn { my-test } {
date .code:n = { \mytest_date_validate_parse:n {#1} },
}
\NewDocumentCommand \Information { m } {
\keys_set:nn { my-test } { #1 }
}
\NewDocumentCommand \PrintDate { } {
Date:\nobreakspace
\int_use:N \mytest_date_day_int
\slash
\int_use:N \mytest_date_month_int
\slash
\int_use:N \mytest_date_year_int
}
\ExplSyntaxOff
\Information{
date = 2015-02-10,
}
\begin{document}
Good: \PrintDate
\Information{date=201-1-1}%bad
Bad: \PrintDate
\Information{date=2015-1}%bad
Bad: \PrintDate
\Information{date=2015/1/1}%bad
Bad: \PrintDate
\Information{date=20150101}%good
Good: \PrintDate
\Information{date=201511}%bad
Bad: \PrintDate
\Information{date=201501012}%bad
Bad: \PrintDate
\end{document}

expl3 iso date
yields nil.expl3
.