2

What already works

I am using \immediate\write18 to let the GNU date command do some date/time arithmetic. The resulting timestamp in ISO format (e.g., 2011-09-09T09:59:59Z) is written to a temporary file /tmp/date.txt, whose content is then read into the macro \ScriptResult, which I can happily print. So far so good.

What doesn't work yet

I am then trying to use \DTMsavetimestamp from the datetime2 package to save \ScriptResult to a timestamp that I can print via \DTMusedate and \DTMusetime (both also part of datetime2). However, this breaks compilation.

I have absolutely zero doubts that this is due to some expansion-related problem. :)

Minimal (non-)working example

Save the following file to test.tex and try to compile via pdflatex -shell-escape test.tex (-shell-escape crucial due to \write18). Compilation will fail. You can then try to comment the line \DTMsavetimestamp{mytimestamp}{\ScriptResult} and uncomment the line \DTMsavetimestamp{mytimestamp}{2011-09-09T09:59:59Z}, after which the MWE compiles fine. This is what makes me think that this issue relates to expansion.

% NOTE: Compile via: pdflatex -shell-escape

\documentclass{article}

\usepackage{datetime2}

\begin{document}

\def\mydate{2015-01-01}%
\def\mytime{12:23}%
\def\offset{-7}

% Black magic that works just fine and we should not have to worry about
\immediate\write18{echo '\mydate\space\mytime\space\offset hours' | sed -e 's/://' | xargs -0 date +\%Y-\%m-\%dT\%H:\%M:\%SZ -d > /tmp/date.txt}% 

% Write temporary file content to \ScriptResult. NOTE: Works
% Inspired from: http://tex.stackexchange.com/a/251574/38212
\newread\myscriptresult
\immediate\openin\myscriptresult=/tmp/date.txt
\read\myscriptresult to \ScriptResult
\immediate\closein\myscriptresult

% Print \ScriptResult. NOTE: Works
\noindent Return value read from \verb|/tmp/date.txt|: \ScriptResult\\

\DTMsavetimestamp{mytimestamp}{\ScriptResult}% TODO: This breaks compilation...
%\DTMsavetimestamp{mytimestamp}{2011-09-09T09:59:59Z}% ... whereas this works.

\noindent Date: \DTMusedate{mytimestamp}\\
\noindent Time: \DTMusetime{mytimestamp}

\end{document}

Restrictions

I am looking for a solution that continues to use the datetime2 package. If there is a solution that does not require writing to a temporary file /tmp/date.txt, that would actually be welcome (but it's not a priority).

  • 1
    Your time is short a second as it's not in the form HH:MM:SS. – Werner Jul 20 '16 at 16:47
  • I don't understand what offset does in the above... Can you explain? – Werner Jul 20 '16 at 16:48
  • I don't think it's an expansion problem. I think it may be a category code problem. – Nicola Talbot Jul 20 '16 at 16:56
  • @Werner: The \write18 command takes care of the "missing second" and outputs an ISO-formatted timestamp, based on the given date, time, and \offset, which is interpreted as an offset in hours (that's the date/time arithmetic bit). However, this part works like a charm and should not even have to be understood in detail to solve this problem. – Florian H. Jul 20 '16 at 17:03
  • @FlorianH.: Then try with \begingroup\edef\x{\endgroup\noexpand\DTMsavetimestamp{\ScriptResult}}\x. – Werner Jul 20 '16 at 17:04
2

It works fine using piped input instead:

\documentclass{article}

\usepackage{datetime2}

\begin{document}

\def\mydate{2015-01-01}%
\def\mytime{12:23}%
\def\offset{-7}

\makeatletter
\begingroup\endlinechar=-1\relax
\edef\pc{\expandafter\@gobble\string\%}
\everyeof{\noexpand}%
\edef\x{\endgroup\def\noexpand\ScriptResult{%
 \@@input|"echo '\mydate\space\mytime\space\offset hours'
   | sed -e 's/://'
   | xargs -0 date +\pc Y-\pc m-\pc dT\pc H:\pc M:\pc SZ -d" }}\x

\makeatother

Result: \ScriptResult

\DTMsavetimestamp{mytimestamp}{\ScriptResult}

\noindent Date: \DTMusedate{mytimestamp}\\
\noindent Time: \DTMusetime{mytimestamp}

\end{document}

Produces:

image of result

I'm guessing that the writing to file and reading back is introducing a category code change for one or more of the characters that are part of the syntax. The same error occurs if I try:

\documentclass{article}

\usepackage{datetime2}

\begin{document}
\edef\ScriptResult{\detokenize{2015-01-01T05:23:00Z}}

Result: \ScriptResult

\DTMsavetimestamp{mytimestamp}{\ScriptResult}

\noindent Date: \DTMusedate{mytimestamp}\\
\noindent Time: \DTMusetime{mytimestamp}

\end{document}

Alternatively, there's something subtly different in the result when reading in date.txt that I haven't noticed.

Edit: It's occurred to me that the original problem might have been due to a spurious space added to the end of \ScriptResult when reading from date.txt, which would probably have caused the same error message.

  • This works beautifully, and I'd like to accept it as an answer. However, when I try to move from my MWE to the real-world example, compilation fails for some reason with a Improper \spacefactor message. I am guessing this is triggered by \space, but I have no idea why the error appears not in my MWE, but only in my larger project. Any ideas? Or if not, perhaps workarounds that do not require \space altogether? I should mention that I am actually reading \mydate and \mytime from a .csv file via \usepackage{datatool} (but that does not seem to cause this particular issue). – Florian H. Jul 20 '16 at 18:14
  • Possible pointer to the cause of the Improper \spacefactor error: tex.ac.uk/FAQ-atvert.html – Florian H. Jul 20 '16 at 18:22
  • @FlorianH. Yes, improper space factor often indicates that you're using internal commands (ones with @ in the name) when @ is not considered a letter. (That's why my MWE has \makeatletter ... \makeatother) – Nicola Talbot Jul 20 '16 at 18:23
  • Mmh, but I am using \makeatletter ... \makeatother in my real-world project, and still I get that error. Need to investigate further, I guess. – Florian H. Jul 20 '16 at 18:29
  • It turns out that if the Improper \spacefactor error is thrown in my real-world project only in presence of \DTMsavetimestamp{mytimestamp}{\ScriptResult}. If I comment that command, plus the \DTMusedate and \DTMusetime commands, the project compiles fine as well. Any ideas? – Florian H. Jul 20 '16 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.