4

I have written a Lua function to position dates in a timeline that I am drawing with TikZ.

The function seems to work, but when I use it in a \foreach loop I get the following error:

! LuaTeX error ./stardate.lua:52: attempt to compare number with nil
stack traceback:
    ./stardate.lua:52: in function 'StarDate'
    [string "\directlua "]:1: in main chunk.
\StarDate ...directlua {tex.write(StarDate("#1"))}

while if used outside the loop it works.

Here is my MWE (I compile my source file with LuaLaTeX):

\documentclass[a4paper]{article}

\usepackage{tikz}

\directlua{require("stardate.lua")}
\newcommand*{\StarDate}[1]{%
% * <- the argument is a number and should not contain paragraphs
  \directlua{tex.write(StarDate("#1"))}%
}

\begin{document}
\def\StartingDate{\StarDate{16-11-1965}}
\begin{tikzpicture}% [scale=.9]
  \draw [->] (-.5,0) -- ++(\linewidth,0);
  \draw (0,0) node [below] {\StartingDate} -- ++(0,1ex) node [above] {Venera 3};% works
  % \foreach [evaluate={\Distance=(\StarDate{\LaunchDate}-\StartingDate);}] \Name/\LaunchDate in % code NOT working
  % {%
  % Galileo/18-10-1989,
  % }{%
  %   %   \pgfmathsetmacro{\Distance}{\StarDate{LaunchDate}-\StartingDate}
  %   \draw (\Distance ex,0) node [below] {\LaunchDate} -- ++(1ex,0) node [above,align=center] {\Name};%
  % }
\end{tikzpicture}
\end{document}

and the Lua function (stardate.lua):

-- Converts date given in format DD-MM-YYYY to format YYYY.xxxx
-- ==============================================================
-- Determines if a year is a leap year or not.
-- Leap years are those divisible by 4, but not also divisible
-- by 100 if not divisible by 400.
local function FebDays(Year)
   if Year % 4 ~= 0 then
      return 28
   else
      if Year % 100 ~= 0 then
     return 29
      else
     if Year % 400 ~= 0 then
        return 28
     else
        return 29
     end
      end
   end
end
--
-- Returns the number of days for the given Year taking into
-- account if it is a leap year or not.
local function YearDays(Year)
   if FebDays(Year) == 28 then
      return
     365
   else
      return
     366
   end
end
--
-- Prints the number of the days of a Month for a certain Year.
local function NumberOfDays(Month, Year)
   local DaysMonth = {31, FebDays(Year), 31, 30, 31, 30, 
              31, 31, 30, 31, 30, 31,}
   return
      DaysMonth[Month]
end
--
function StarDate(DateStr)
   -- Accepts other separators.
   local NormalizedDateStr = string.gsub(DateStr, "[ /,.%-]", "-")
   local Day, Month, Year = string.match(
      NormalizedDateStr, "^(%d%d)%-(%d%d)%-(%d%d%d%d)$"
   )
   Month = tonumber(Month)
   -- IF January THEN the number of days is Day, ELSE sum number of days
   -- of months before Month and then add Day.
   local MonthDays = 0 
   if Month > 1 then
      for I = 1, Month - 1 do
     MonthDays = MonthDays + NumberOfDays(Month, Year)
      end
   end
   local TotDays = MonthDays + Day
   local PercentDays = tostring(TotDays / YearDays(Year))
   -- Trunc at fourth decimal.
   PercentDays = string.match(PercentDays, ".%d%d%d%d")
   return
      tonumber(Year .. PercentDays)
end

Any insight on what is going on?

3

You had a couple of syntax issues with \foreach: the major was the syntax for evaluate key. It is /pgf/foreach/evaluate=<\variable> as <\macro> using <formula>.

This should work.

\documentclass{standalone}

\usepackage{tikz}

\directlua{require("stardate.lua")}
\def\StarDate#1{%
  \directlua{tex.sprint(StarDate("#1"))}%
}

\begin{document}
\edef\StartingDate{\StarDate{16-11-1965}}
\begin{tikzpicture}
  \draw [->] (-.5,0) -- ++(\linewidth,0);
  \draw (0,0) 
        node [below] {\StartingDate} 
        -- 
        ++(0,1ex) 
        node [above] {Venera 3};

  \foreach \Name/\LaunchDate [%
    evaluate =  \LaunchDate as \Distance using (\StarDate{\LaunchDate}-\StartingDate)] in {%
      Galileo/18-10-1989}{%
    \draw (\Distance ex,0) 
          node [below] {\LaunchDate} 
          -- 
          ++(1ex,0) 
          node [above,align=center] {\Name};
    }
\end{tikzpicture}
\end{document}
  • Thanks for your answer. However, the problem is not solved yet because the nodes with name and date are placed, but the tick is not drawn. Moreover, I have to pay close attention to white spaces, i.e. Galileo/18-10-1989% ,Galileo/18-10-1992% ,Galileo/18-10-1998% ,Galileo/18-10-2010% (if I want to write it as a "list".) Why is that? – Pier Paolo Oct 20 '14 at 16:52

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.