7

I think this is my first post here, and I'll try to make it right.

As a scholar of antiquity, I would like to be able to construct nice timelines of events and periods for papers and presentations. There are several available packages for this, but they all appear to have the same flaw – they treat and display years BCE as "-[year]". To me, there is no such thing as a "minus year".

Adding to this, all of them appear to put the "year 0" as the turning point between "minus" and "plus" years. Contrary to common practice, there is no such thing as the "year zero", there is 1 BCE and 1 CE with no year inbetween.

My question is, are there any neat ways of writing a timeline with years displayed as BCE and CE with "year 1" as turning point between the two?

A minumum example:

\documentclass{article}
\usepackage{chronology}
\begin{document}
\begin{chronology}*[5]{-25}{20}{10cm}[10cm]
\event[-20]{-20}{\color{gray}Random event}
\event[-5]{10}{Random war}
\end{chronology}
\end{document}

enter image description here

  • 1
    You mean something like this? – Alenanno Jun 20 '16 at 11:05
  • Isn't this just a mapping of the Interval [a,b] to [c,d]? – user31729 Jun 20 '16 at 11:12
  • I do timelines which run from BCE to CE. I realise that there is no year 0. Nonetheless, 0 is the turning point, I think and that's what I take my 0 on the axis to represent. It is not supposed to mean that there was every a point at which it makes sense to say 0BCE or 0CE. Rather, 0 is the instant between 1BCE and 1CE. At least, that's how I think of it. – cfr Jun 20 '16 at 12:22
  • Here's an example. – cfr Jun 20 '16 at 12:25
  • cfr: I understand your point, the problem is that all the other numbers refer to years, not to turning points. All numbers should thus refer to years for consistency. I don't think an editor of a journal would accept "year zero". – komponisto Jun 21 '16 at 8:13
4

Current version of chronos is available at:
https://tex.stackexchange.com/a/342699/ (2016-12-06)

chronos now automatically eliminate year zero by default. (It can be reinstated if required.) It also omits minus signs for years by default and can be customised to include labels for the era (BCE/CE or whatever).

Here's a default timeline showing the last day of BCE and the first of CE.

\begin{tikzpicture}
  [
    chronos={%
      start date={-1}-12-01,
      end date=1-01-31,
    }
  ]
  \chronosevent {{-1}-12-31}{New Year's Eve}(20pt)
  \chronosevent {1-01-01}{New Year's Day}(-20pt)
\end{tikzpicture}

default turning from BCE to CE

Note that I'm fully aware of the inappropriateness of calling 1st January New Year's Day etc. at this point, and that current calendars are not really appropriate here. These examples are intended for demonstration purposes only because I take it that, in most cases, timelines running partly or wholly in BCE will include only years rather than full dates anyway. If there are exceptions, chronos allows the date markers for events to be specified as arbitrary text on a per event basis.

The year zero can be reinstated if required. The underlying code is using pgfcalendar which assumes a year zero (and uses minuses).

\begin{tikzpicture}
  [
    chronos={%
      start date={-1}-12-01,
      end date=1-01-31,
      year zero,
    }
  ]
  \chronosevent {{-1}-12-31}{New Year's Eve}(20pt)
  \chronosevent {1-01-01}{New Year's Day}(-20pt)
\end{tikzpicture}

with year zero

Here are three possibilities for your timeline with chronos. Further customisation should be straightforward as the original idea was to provide a more flexible and transparent alternative to chronosys.

\begin{tikzpicture}
  [
    chronos={%
      start date={{-25}-01-01},
      end date={20-01-01},
      step years=5,
      only text,
      year format={Y E},
      timeline width=100mm,
      timeline marks,
      timeline year={font=\scriptsize},
      lines/.style={draw=none},
      events/.append style={rotate=-45, anchor=west},
      event distance=-2.5pt,
    }
  ]
  \chronosevent[gray]{{-20}}[text=gray]{Random event}
  \chronosperiod[ultra thick, gray, opacity=.75]{{-5}}{10}{Random war}
\end{tikzpicture}

version 1

Note that the marks are not equidistant, because the time between 1 CE and 5 CE is obviously less than in the other cases. Obviously, you could also mark 1 BCE, but that would put the marker very close to 1 CE. The issue here is that although 1 BCE ends as 1 CE starts (i.e. there is no year 0), the years are marked at YYYY-01-01, as you'd expect. So the 'turning point' marks 31 December 1 BCE and 1 January 1 CE, but 1 BCE's marker would be at 1 January 1 BCE.

I'm not sure whether I should be marking the years at the mid-year point. But then an event on 1st April will be placed prior to the year marker (reading left to right). I'm not sure if that would be better or not and would welcome input on this as I'm really not clear what the correct answer is.

\begin{tikzpicture}
  [
    chronos={%
      start date={{-25}-01-01},
      end date={20-01-01},
      step years=5,
      only text,
      timeline width=100mm,
      timeline marks,
      timeline mark eras,
      timeline year={font=\scriptsize},
      lines/.style={draw=none},
      events/.append style={rotate=-45, anchor=west},
      event distance=-2.5pt,
    }
  ]
  \chronosevent[gray]{{-20}}[text=gray]{Random event}
  \chronosperiod[ultra thick, gray, opacity=.75]{{-5}}{10}{Random war}
\end{tikzpicture}

version 2

\begin{tikzpicture}
  [
    chronos={%
      start date={{-25}-01-01},
      end date={20-01-01},
      step years=5,
      timeline height=5mm,
      only text,
      timeline width=100mm,
      timeline marks,
      timeline mark eras,
      timeline font=\scriptsize,
      timeline years=on line,
      timeline marks,
      timeline border height=5pt,
    }
  ]
  \chronosevent[gray]{{-20}}{Random event}
  \chronosperiod[blue!50!gray]{{-5}}{10}{Random war}
\end{tikzpicture}

version 3

I may adapt this to produce timelines which have higher information density (of the kind I posted a while ago, though mine had a year zero). If you allow the lines to events to turn, I think the effect is neater and clearer. However, that's not how the existing packages seem to do it and I'm not really sure anybody but me is much interested!

Complete code (chronos 2016-08-15):

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{pgfcalendar}
\usepackage{datenumber,xparse,fp}
\usetikzlibrary{arrows.meta,backgrounds,fixedpointarithmetic}
\makeatletter
\ExplSyntaxOn
\tl_new:N \l_chronos_dateformat_tl
\tl_new:N \l_chronos_yearformat_tl
\tl_set:Nn \l_chronos_dateformat_tl { d/m/Y }
\tl_set:Nn \l_chronos_yearformat_tl { Y }
% YY yn lle YYYY
\cs_new_protected_nopar:Npn \chronos_year_shorten:n #1
{
  \chronos_year_shorten_aux:w #1 \q_stop % expl3 manuaal, 46
}
\cs_new_protected_nopar:Npn \chronos_year_shorten_aux:w #1 #2 #3 #4 \q_stop
{
  #3 #4
}
\cs_generate_variant:Nn \chronos_year_shorten:n { V , c }
\cs_generate_variant:Nn \int_abs:n { c }
% dangos dyddiadau
\cs_new_protected_nopar:Npn \chronos_show_date:n #1
{
  \tl_map_inline:Nn \l_chronos_dateformat_tl
  {
    \str_case:nnF { ##1 }
    {
      { a } { \pgfcalendarweekdayshortname{\thechronos@weekday} }
      { A } { \pgfcalendarweekdayname{\thechronos@weekday} }
      { b } { \pgfcalendarmonthshortname{\csname chronos@#1month\endcsname} }
      { B } { \pgfcalendarmonthname{\csname chronos@#1month\endcsname} }
      { d } { \csname chronos@#1day\endcsname }
      { E } { \chronos_dateformat_era:c { chronos@#1year } }
      { m } { \csname chronos@#1month\endcsname }
      { q } { \chronos_dateformat_sign:c { chronos@#1year } }
      { Q } { \chronos_dateformat_signs:c { chronos@#1year } }
      { y } { \chronos_year_shorten:c { chronos@#1year } }
      { Y } { \int_abs:c { chronos@#1year } }
      { @ } { ~ }
    }
    {
      ##1
    }
  }
}
\cs_new_protected_nopar:Npn \chronos_show_year:n #1
{
  \tl_map_inline:Nn \l_chronos_yearformat_tl
  {
    \str_case:nnF { ##1 }
    {
      { E } { \chronos_dateformat_era:n { #1 } }
      { q } { \chronos_dateformat_sign:n { #1 } }
      { Q } { \chronos_dateformat_signs:n { #1 } }
      { y } { \chronos_year_shorten:n { #1 } }
      { Y } { \int_abs:n { #1 } }
      { @ } { ~ }
    }
    {
      ##1
    }
  }
}
\cs_new_protected_nopar:Npn \chronos_dateformat_sign:n #1
{
  \int_compare:nT { #1 < 0 } { - }
}
\cs_generate_variant:Nn \chronos_dateformat_sign:n { c }
\cs_new_protected_nopar:Npn \chronos_dateformat_signs:n #1
{
  \int_compare:nTF
  { #1 < 0 } { - }
  {
    \int_compare:nT { #1 > 0 }
    {
      \ifchronos@yearzero\relax
      \else
        \int_compare:nT { #1 > 1} { +  }
      \fi
    }
  }
}
\cs_generate_variant:Nn \chronos_dateformat_signs:n { c }
\cs_new_protected_nopar:Npn \chronos_dateformat_era:n #1
{
  \int_compare:nTF
  { #1 < 0 } { \chronos@yearbce }
  {
    \int_compare:nT { #1 > 0 }
    {
      \ifchronos@yearzero\relax
      \else
        \int_compare:nT { #1 > 1} { \chronos@yearce }
      \fi
    }
  }
}
\cs_generate_variant:Nn \chronos_dateformat_era:n { c }
\cs_new_protected_nopar:Npn \chronos_set_dateformat:n #1
{
  \tl_set:Nn \l_chronos_dateformat_tl { #1 }
  \tl_replace_all:Nnn \l_chronos_dateformat_tl { ~ } { @ }
}
\cs_new_protected_nopar:Npn \chronos_set_yearformat:n #1
{
  \tl_set:Nn \l_chronos_yearformat_tl { #1 }
  \tl_replace_all:Nnn \l_chronos_yearformat_tl { ~ } { @ }
}
% user interface
\NewDocumentCommand \chronos@setdateformat { m }
{
  \chronos_set_dateformat:n { #1 }
}
\NewDocumentCommand \chronos@setyearformat { m }
{
  \chronos_set_yearformat:n { #1 }
}
% for pgf/tikz convenience
\NewDocumentCommand \chronos@showdate { o m }
{
  \group_begin:
    \IfValueT { #1 }
    {
      \chronos_set_dateformat:n { #1 }
    }
    \pgfcalendarjuliantoweekday{\csname thechronos@#2date\endcsname}{\c@chronos@weekday}%
    \chronos_show_date:n { #2 }
  \group_end:
}
\NewDocumentCommand \chronos@showyear { o m }
{
  \group_begin:
    \IfValueT { #1 }
    {
      \chronos_set_yearformat:n { #1 }
    }
    \chronos_show_year:n { #2 }
  \group_end:
}
\ExplSyntaxOff
\newlength\chronos@tempdima
\newcounter{chronos@date}
\newcounter{chronos@startdate}
\newcounter{chronos@enddate}
\newcounter{chronos@startyear}
\newcounter{chronos@endyear}
\newcounter{chronos@yeardate}
\newcounter{chronos@thingdate}
\newcounter{chronos@otherthingdate}
\newcounter{chronos@weekday}
\newcounter{chronos@tempcnta}
\newif\ifchronos@marks
\chronos@marksfalse
\newif\ifchronos@timeline@showyears
\chronos@timeline@showyearstrue
\newif\ifchronos@eventyearsonline
\chronos@eventyearsonlinefalse
\newif\ifchronos@yearzero
\chronos@yearzerofalse
\newif\ifchronos@onlytext
\chronos@onlytextfalse
\newif\ifchronos@markeras
\chronos@markerasfalse
\newif\ifchronos@yearsonline
\chronos@yearsonlinefalse
\pgfkeys{/pgf/number format,
  int detect,
  set thousands separator={},
}
\tikzset{%
  /handlers/.chronos too/.code={%
    \edef\chronos@tempc{\pgfkeyscurrentpath}%
    \edef\chronos@tempd{#1}%
    \tikzset{%
      \pgfkeyscurrentpath @too/.code={%
        \tikzset{%
          /chronos/\chronos@tempd/.append style={##1},
        }%
      },
      \chronos@tempc/.forward to=\chronos@tempc @too,
    }%
  },
  chronos/.code={% https://tex.stackexchange.com/a/159856/ - Claudio Fiandrino
    \tikzset{%
      align=center,
      anchor=mid,
      fixed point arithmetic,
      /chronos/.cd,
      #1,
      timeline config,
      timeline config/.code={},
    }%
    \ifnum\chronos@startyear=\chronos@endyear
      \tikzset{%
        /chronos/timeline no years,
      }%
    \fi
    \setlength\chronos@tempdima{\chronos@timelinemargin}%
    \ifchronos@markeras
      {%
        \chronos@timelinefont
        \pgfmathsetmacro\chronos@tempe{((width("\chronos@bce"))>(width("\chronos@ce"))) ? (width("\chronos@bce")) : (width("\chronos@ce"))}%
        \xdef\chronos@tempf{\chronos@tempe}%
      }%
      \addtolength\chronos@tempdima{\chronos@tempf pt}%
    \fi
    \pgfmathsetmacro\chronos@unit{(\chronos@width-2*\chronos@tempdima)/(\thechronos@enddate-\thechronos@startdate)}%
    \draw [/chronos/timeline@line, line width=\chronos@height] (-\chronos@tempdima,0) coordinate (chronos pre) -- +(\chronos@width,0) coordinate (chronos post);
    \coordinate (chronos base) at (0,-.5*\chronos@height);
    \coordinate (chronos top) at (0,.5*\chronos@height);
    \coordinate (chronos foot) at (0,{-.5*\chronos@height-\chronos@borderheight});
    \coordinate (chronos head) at (0,{.5*\chronos@height+\chronos@borderheight});
    \coordinate (chronos start) at (0,0);
    \coordinate (chronos end) at ([xshift=-\chronos@tempdima]chronos post);
    \ifdim\chronos@borderheight>0pt
      \fill [bottom color=chronos@borderinner, top color=chronos@borderouter] (chronos pre |- chronos head) rectangle (chronos post |- chronos top);
      \fill [top color=chronos@borderinner, bottom color=chronos@borderouter] (chronos pre |- chronos base) rectangle (chronos post |- chronos foot);
    \fi
    \ifchronos@timeline@showyears
      \pgfmathsetcounter{chronos@startyear}{\chronos@startyear}%
      \pgfmathsetcounter{chronos@endyear}{\chronos@endyear}%
      \def\tempa{none}%
      \ifx\chronos@stepfrom\tempa
        \def\tempa{01}%
        \ifx\chronos@startmonth\tempa
          \ifx\chronos@startday\tempa
            \else\stepcounter{chronos@startyear}%
          \fi
          \else\stepcounter{chronos@startyear}%
        \fi
      \else
        \pgfmathsetcounter{chronos@startyear}{\chronos@stepfrom}%
      \fi
      \def\tempa{12}%
      \def\tempb{31}%
      \ifx\chronos@endmonth\tempa
        \ifx\chronos@endday\tempb
          \stepcounter{chronos@endyear}%
        \fi
      \fi
      \ifnum\value{chronos@endyear}<\value{chronos@startyear}\setcounter{chronos@endyear}{\thechronos@startyear}\fi
      \pgfmathsetmacro\chronos@nextstep{int(((\thechronos@startyear+\chronos@stepyears)>\thechronos@endyear) ? \thechronos@endyear : (\thechronos@startyear+\chronos@stepyears))}%
      \ifchronos@yearzero\setcounter{chronos@tempcnta}{1}\else\setcounter{chronos@tempcnta}{0}\fi
      \foreach \b [evaluate=\b as \i using {((\b==0)&&(\thechronos@tempcnta==0)) ? 1 : int(\b)}, remember=\i as \ilast (initially \pi)] in {\thechronos@startyear,\chronos@nextstep,...,\thechronos@endyear} {%
        \ifnum\i=\ilast\relax
        \else
          \pgfcalendardatetojulian{{\i}-01-01}{\c@chronos@yeardate}%
          \ifchronos@yearzero\relax\else\ifnum0<\i\addtocounter{chronos@yeardate}{-366}\fi\fi
          \pgfmathsetmacro\chronos@tempa{(\thechronos@yeardate-\thechronos@startdate)*\chronos@unit}%
          \ifchronos@yearsonline
            \node (chronos@year@\i) [/chronos/.cd, timeline@years, timeline year on line] at (\chronos@tempa pt,0) {\chronos@timelinefont\chronos@showyear{\i}};
            \ifchronos@marks
               \path [/chronos/timeline mark on line] (chronos@year@\i.south) -- (chronos@year@\i |- chronos base);
               \path [/chronos/timeline mark on line] (chronos@year@\i.north) --  (chronos@year@\i |- chronos top);
            \fi
            \ifchronos@markeras
              \path (chronos pre) +(\chronos@timelinemargin,0) node (chronos@bce) [/chronos/.cd, timeline@years, timeline year on line] {\chronos@timelinefont\chronos@bce};
              \path (chronos post) +(-\chronos@timelinemargin,0) node (chronos@ce) [/chronos/.cd, timeline@years, timeline year on line] {\chronos@timelinefont\chronos@ce};
            \fi
          \else
            \node (chronos@year@\i) [/chronos/.cd, timeline@years, timeline year off line] at (\chronos@tempa pt,0) {\chronos@timelinefont\chronos@showyear{\i}};
            \ifchronos@marks
              \path [shorten <=.5*\chronos@height, /chronos/timeline mark off line] (\chronos@tempa pt, 0) -- (chronos@year@\i);
            \fi
            \ifchronos@markeras
              \path (chronos pre) +(\chronos@timelinemargin,0) node (chronos@bce) [/chronos/.cd, timeline@years, timeline year off line] {\chronos@timelinefont\chronos@bce};
              \path (chronos post) +(-\chronos@timelinemargin,0) node (chronos@ce) [/chronos/.cd, timeline@years, timeline year off line] {\chronos@timelinefont\chronos@ce};
            \fi
          \fi
        \fi
      }%
    \else
      \ifchronos@markeras
        \path (chronos pre) +(\chronos@timelinemargin,0) node (chronos@bce) [/chronos/.cd, timeline@years, timeline year off line] {\chronos@timelinefont\chronos@bce};
        \path (chronos post) +(-\chronos@timelinemargin,0) node (chronos@ce) [/chronos/.cd, timeline@years, timeline year off line] {\chronos@timelinefont\chronos@ce};
      \fi
    \fi
    \ifchronos@eventyearsonline
      \tikzset{%
        /chronos/timeline years=on line,
      }%
    \fi
  },
  chronos set date/.code args={#1:#2:#3:#4}{%
    \pgfcalendardatetojulian{{#1}-#2-#3}{\c@chronos@date}%
    \setcounter{chronos@#4date}{\thechronos@date}%
    \ifchronos@yearzero\relax
    \else
      \setcounter{chronos@tempcnta}{#1}%
      \ifnum0<\value{chronos@tempcnta}%
        \addtocounter{chronos@#4date}{-366}%
      \fi
    \fi
    \expandafter\def\csname chronos@#4year\endcsname{#1}%
    \expandafter\def\csname chronos@#4month\endcsname{#2}%
    \expandafter\def\csname chronos@#4day\endcsname{#3}%
  },
  chronos date/.style args={#1-#2-#3}{%
    /tikz/chronos set date/.expanded={#1:#2:#3:thing}%
  },
  chronos period date/.style args={#1-#2-#3}{%
    /tikz/chronos set date/.expanded={#1:#2:#3:otherthing}%
  },
  /chronos/.search also={/tikz},
  /chronos/.cd,
  timeline config/.code={},
  date format/.code={%
    \chronos@setdateformat{#1}%
  },
  year format/.code={%
    \chronos@setyearformat{#1}%
  },
  step years/.store in=\chronos@stepyears,
  step from year/.store in=\chronos@stepfrom,
  start date/.style args={#1-#2-#3}{%
    /chronos/timeline config/.append code={%
      \tikzset{/tikz/chronos set date/.expanded={#1:#2:#3:start}}%
    },
  },
  end date/.style args={#1-#2-#3}{%
    /chronos/timeline config/.append code={%
      \tikzset{/tikz/chronos set date/.expanded={#1:#2:#3:end}}%
    },
  },
  ce year label/.store in=\chronos@yearce,
  bce year label/.store in=\chronos@yearbce,
  timeline ce label/.store in=\chronos@ce,
  timeline bce label/.store in=\chronos@bce,
  timeline width/.store in=\chronos@width,
  timeline height/.store in=\chronos@height,
  width/.forward to=/chronos/timeline width,
  height/.forward to=/chronos/timeline height,
  timeline border height/.store in=\chronos@borderheight,
  timeline border inner colour/.code={\colorlet{chronos@borderinner}{#1}},
  timeline border outer colour/.code={\colorlet{chronos@borderouter}{#1}},
  timeline mark eras/.is if=chronos@markeras,
  timeline margin/.store in=\chronos@timelinemargin,
  timeline font/.store in=\chronos@timelinefont,
  timeline years set/.store in=\chronos@timelineyears,
  timeline years/.is choice,
  timeline years/.forward to=/chronos/timeline years set,
  timeline years/above/.code={%
    \tikzset{%
      /chronos/timeline@years/.style={above, anchor=south, yshift=.5*\chronos@height},
    }%
  },
  timeline years/below/.code={%
    \tikzset{%
      /chronos/timeline@years/.style={below, anchor=north, yshift=-.5*\chronos@height},
    }%
  },
  timeline years/on line/.code={%
    \chronos@yearsonlinetrue
    \tikzset{%
      /chronos/timeline@years/.style={anchor=center},
    }%
  },
  only years/.code={%
    \edef\tempa{}%
    \edef\tempb{#1}%
    \ifx\tempa\tempb\chronos@setdateformat{Y}\else\chronos@setdateformat{#1}\fi
    \tikzset{%
      /tikz/chronos date/.style={%
        /tikz/chronos set date/.expanded={##1:01:01:thing}%
      },
      /tikz/chronos period date/.style={%
        /tikz/chronos set date/.expanded={##1:01:01:otherthing}%
      },
    }%
  },
  only text/.code={%
    \tikzset{/chronos/only years}%
    \chronos@setdateformat{}%
    \chronos@onlytexttrue
  },
  year zero/.is if=chronos@yearzero,
  background/.code={%
    \colorlet{chronos@background}{#1}%
  },
  timeline marks/.is if=chronos@marks,
  timeline show years/.is if=chronos@timeline@showyears,
  timeline no years/.code={%
    \tikzset{%
      /chronos/timeline show years=false,
    }%
  },
  lines/.style={draw, {Triangle[width=0pt 3,reversed,length=0pt 1.5]}-{Triangle[width=0pt 3,reversed,length=0pt 1.5]}, shorten <={.5*\chronos@height}},
  events/.style={fill=chronos@background, fill opacity=.75, text opacity=1, draw opacity=1, rounded corners, align=center, font=\footnotesize},
  period/.style={draw},
  period event line/.style={/chronos/lines},
  period event/.style={/chronos/events},
  event line/.style={/chronos/lines},
  event/.style={/chronos/events},
  event years on line/.is if=chronos@eventyearsonline,
  event year on line/.style={/chronos/timeline@years, /chronos/timeline year on line},
  event distance/.store in=\chronos@eventdistance,
  special date/.store in=\chronos@specialdate,
  timeline@line/.style={draw},
  timeline line/.chronos too=timeline@line,
  timeline year off line/.style={fill=chronos@background, text opacity=1, align=center, fill opacity=.75},
  timeline mark off line/.style={draw, {Triangle[width=0pt 3,reversed,length=0pt 1.5]}-, thin, shorten >=-2pt},
  timeline year on line/.style={text=chronos@background, inner sep=1pt, align=center},
  timeline mark on line/.style={draw=chronos@background, shorten >=1.5pt},
  timeline mark too/.code={%
    \tikzset{%
      /chronos/.cd,
      timeline mark on line/.append style={#1},
      timeline mark off line/.append style={#1},
    }%
  },
  timeline year too/.code={%
    \tikzset{%
      /chronos/.cd,
      timeline year on line/.append style={#1},
      timeline year off line/.append style={#1},
    }%
  },
  timeline mark/.forward to=/chronos/timeline mark too,
  timeline year/.forward to=/chronos/timeline year too,
  start date=1001-10-01,
  end date=1003-06-14,
  timeline width=100mm,
  timeline height=1pt,
  timeline border height=0pt,
  chronos date=1850-01-01,
  chronos period date=1851-01-01,
  step years=1,
  timeline years=above,
  background=white,
  timeline border inner colour=black,
  timeline border outer colour=chronos@background,
  step from year=none,
  special date=none,
  ce year label={\textsc{ce}},
  bce year label={\textsc{bce}},
  event distance=-10pt,
  timeline ce label={CE},
  timeline bce label={BCE},
  timeline margin=10pt,
  timeline font=\sffamily,
}
\NewDocumentCommand \chronosevent { O {} m O {} +m D () { \chronos@eventdistance } }
{%
  \tikzset{%
    chronos date/.expanded={#2},
  }%
  \pgfmathsetmacro\chronos@offset{(#5 < 0pt) ? (#5-.5*\chronos@height-.5*\chronos@borderheight) : (#5+.5*\chronos@height+.5*\chronos@borderheight)}%
  \pgfmathsetmacro\chronos@anchor{(#5 < 0pt) ? "north" : "south"}%
  \scoped[on background layer]{\path [postaction={/chronos/event line, #1}] ({(\thechronos@thingdate-\thechronos@startdate)*\chronos@unit pt},0) -- +(0,\chronos@offset pt) node [anchor=\chronos@anchor, /chronos/event, #3] {\ifchronos@onlytext\relax\else\chronos@showdate{thing}\\\fi#4};}
  \ifchronos@eventyearsonline
    \edef\tempa{none}%
    \edef\tempb{\chronos@specialdate}%
    \ifx\tempa\tempb\else\let\chronos@thingyear\chronos@specialdate\tikzset{/chronos/special date=none}\fi
    \node [/chronos/.cd, event year on line] at ({(\thechronos@thingdate-\thechronos@startdate)*\chronos@unit pt},0) {\chronos@thingyear};
  \fi
}
\NewDocumentCommand \chronosspecialdate { m }
{%
  \tikzset{%
    /chronos/special date=#1,
  }%
}
\NewDocumentCommand \chronosperiod { O {} m O {} m O {} +m D () { \chronos@eventdistance } }
{%
  \tikzset{%
    chronos date/.expanded={#2}, chronos period date/.expanded={#4}
  }%
  \pgfmathsetmacro\chronos@offset{(#7 < 0pt) ? (#7-.5*\chronos@height-.5*\chronos@borderheight) : (#7+.5*\chronos@height+.5*\chronos@borderheight)}%
  \pgfmathsetmacro\chronos@anchor{(#7 < 0pt) ? "north" : "south"}%
  \ifchronos@yearsonline
    \pgfmathsetmacro\chronos@borderoffset{(#7 < 0pt) ? (-.5*\chronos@height-.5*\chronos@borderheight) : (.5*\chronos@height+.5*\chronos@borderheight)}%
    \path [postaction={line width=\chronos@borderheight, /chronos/period, blend mode=overlay, #1}] ({(\thechronos@thingdate-\thechronos@startdate)*\chronos@unit pt},\chronos@borderoffset pt) -- ({(\thechronos@otherthingdate-\thechronos@startdate)*\chronos@unit pt},\chronos@borderoffset pt);
  \else
    \path [postaction={line width=\chronos@height, /chronos/period, #1}] ({(\thechronos@thingdate-\thechronos@startdate)*\chronos@unit pt},0) -- ({(\thechronos@otherthingdate-\thechronos@startdate)*\chronos@unit pt},0);
  \fi
  \scoped[on background layer]{\path [postaction={/chronos/period event line, #3}] ({(.5*\thechronos@otherthingdate+.5*\thechronos@thingdate-\thechronos@startdate)*\chronos@unit pt},0) -- +(0,\chronos@offset pt) node [anchor=\chronos@anchor, /chronos/period event, #5] {\ifchronos@onlytext\relax\else\chronos@showdate{thing}--\chronos@showdate{otherthing}\\\fi#6};}
}
\makeatother
\begin{document}
\begin{tikzpicture}
  [
    chronos={%
      start date={{-25}-01-01},
      end date={20-01-01},
      step years=5,
      only text,
      year format={Y E},
      timeline width=100mm,
      timeline marks,
      timeline year={font=\scriptsize},
      lines/.style={draw=none},
      events/.append style={rotate=-45, anchor=west},
      event distance=-2.5pt,
    }
  ]
  \chronosevent[gray]{{-20}}[text=gray]{Random event}
  \chronosperiod[ultra thick, gray, opacity=.75]{{-5}}{10}{Random war}
\end{tikzpicture}
\begin{tikzpicture}
  [
    chronos={%
      start date={{-25}-01-01},
      end date={20-01-01},
      step years=5,
      only text,
      timeline width=100mm,
      timeline marks,
      timeline mark eras,
      timeline year={font=\scriptsize},
      lines/.style={draw=none},
      events/.append style={rotate=-45, anchor=west},
      event distance=-2.5pt,
    }
  ]
  \chronosevent[gray]{{-20}}[text=gray]{Random event}
  \chronosperiod[ultra thick, gray, opacity=.75]{{-5}}{10}{Random war}
\end{tikzpicture}
\begin{tikzpicture}
  [
    chronos={%
      start date={{-25}-01-01},
      end date={20-01-01},
      step years=5,
      timeline height=5mm,
      only text,
      timeline width=100mm,
      timeline marks,
      timeline mark eras,
      timeline font=\scriptsize,
      timeline years=on line,
      timeline marks,
      timeline border height=5pt,
    }
  ]
  \chronosevent[gray]{{-20}}{Random event}
  \chronosperiod[blue!50!gray]{{-5}}{10}{Random war}
\end{tikzpicture}
\end{document}
3

A temporary solution for the timeline (without events for now). The line for the years can be created with the command \chronoline and it works like this

\chronoline[ <step> ]{ <starting year> }{ <ending year> }

The first argument in square brackets is optional. If not given, the step will be every 10 years. If you want to change the step, add a number like 20 to print every 20 years. The other parameters are pretty self-explanatory. So to have a timeline that goes every 20 years from 100 BCE to 120 CE, you can write

\chronoline[20]{100}{120}

The line will appear at the bottom of the page.

Possible improvements:

  • For now the distance between the years is fixed, but I guess it could be changed to "fit" the page. It depends on how much you need to use this timeline.
  • The line is not visually centered.

Output

enter image description here

Code

\documentclass{article}
\usepackage[landscape]{geometry}
\usepackage{tikz}

\usetikzlibrary{calc, arrows.meta}
\pagestyle{empty}

\tikzset{
    date/.style={below=7pt, text width=1cm, align=center}
}

\newcommand\chronoline[3][10]{%
\tikz[shift={($(current page.south)+(0cm,2cm)$)}, remember picture, overlay]{%
\pgfmathtruncatemacro\startdate{#2/10}
\pgfmathtruncatemacro\enddate{#3/10}
\pgfmathtruncatemacro\stepdate{-\startdate+(#1/10)}
    \draw[{Latex}-{Latex}, line width=.3mm] ($(-\startdate,0)+(-1,0)$) -- ($(\enddate,0)+(1,0)$);
%
\foreach \x [evaluate=\x as \year using int(abs(\x*10)), remember=\x as \lastx] in 
    {-\startdate,\stepdate,...,0,...,\enddate}{%
    \ifnum\x=0
    \node[date] (n\x) at (\x,0) {$1$\\\scriptsize CE}; 
    \else
    \ifnum\x<0
    \node[date] (n\x) at (\x,0) {$\year$\\\scriptsize BCE};
    \else
    \node[date] (n\x) at (\x,0) {$\year$\\\scriptsize CE};
    \fi
    \fi 
    \draw (\x,-0.2) -- (\x,0.2);
}}
}

\begin{document}
\chronoline{100}{120}
\end{document}
  • Thank you! This looks very nifty, but at the same time a bit difficult to handle compared to the chronology package, for instance. – komponisto Jun 21 '16 at 8:15
  • @komponisto What is difficult about it? The definition of the command is done, I mean, you don't need to maintain it. I will add the code for the events soon. – Alenanno Jun 21 '16 at 20:29

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.