43

I was asked how to implement a \tomorrow macro in TeX/LaTeX. While I could come up with a reasonably good solution, working for one document class, I don't see how that could be achieved in a document class agnostic way.

I found advdate, but even though the date arithmetic may be of use, it assumes a specific format for the date (which also is wrong for the locale I reside in).

Does anyone have a reasonably portable solution? Is this even possible?

Max
  • 5,702
  • If your class already defines \today then the only difficult part of \tomorrow is the date arithemtic, all \tommorrow can just locally add 1 day to \year\month\day taking care of date arithemetic, and then just do \today – David Carlisle Dec 18 '12 at 01:14
  • No unfortunately this is not possible as far as i see, since \today is edef'd in latex.ltx for example. otherwise i would have done \def\tomorrow{\advance\day 1\relax\today\advance -1\relax} – Max Dec 18 '12 at 01:24
  • Yes latex.ltx edefs a uS english version but any language package will change that, babel's german fir example has \def\dategerman{\def\today{\number\day.~\month@german \space\number\year}} \def\dateaustrian{\def\today{\number\day.~\ifnum1=\month J\"anner\else \month@german\fi \space\number\year}} so if your preamble has \dateaustian \today will give a localised today and {add a day to \day\month\year \today} will give a localised tomorrow, you can't simply \advance\day 1 as you need to take account of month arithmetic, but perhaps that's what you meant? – David Carlisle Dec 18 '12 at 01:55
  • Well yes, of course that would exclude all the date arithmetic that was fabulously solved by the other two answers (and advdate). I should have used pseudocode. I'd say adding the requirement of having to use babel is ok. – Max Dec 18 '12 at 02:15
  • 2
    put your system clock forward by 1 day prior to compiling, then put it back... ;-( Up-vote me if you think this is the worst hack of all time. – Nicholas Hamilton Dec 18 '12 at 09:07
  • Sorry, but this is neither a hack nor an answer. – egreg Dec 18 '12 at 09:32
  • OMG how funny... – Nicholas Hamilton Dec 18 '12 at 11:36

4 Answers4

33

Just a quick cook-up

\documentclass{article}
\usepackage{pgfkeys,pgfcalendar}

\newcount\pgfdatecount
\newcommand{\tomorrow}{%
\pgfcalendardatetojulian{\year-\month-\day+1}{\pgfdatecount}
\pgfcalendarjuliantodate{\the\pgfdatecount}{\myyear}{\mymonth}{\myday}
\pgfcalendarmonthname{\mymonth}\space\myday,\space\myyear%
}

\begin{document}

\today~ is the day before tomorrow.\par
\tomorrow~ is the day after today.

\end{document}

enter image description here

Adding weekday names etc. is also possible. You can check the manual. This is, as far as I can paranoi(?!), independent from the class but the month names are fixed. If you like you can introduce them too but ISO dates rulaz just because of this.

percusse
  • 157,807
26

Here is a prototype in LaTeX3; the data about tomorrow is available in the integer variables

\l_tomorrow_day_int
\l_tomorrow_month_int
\l_tomorrow_year_int

The code follows; the final macro is just an example of how the data can be used, possibly in connection with datetime.

\documentclass{article}

\ExplSyntaxOn \prop_new:N \g_tomorrow_months_prop \bool_new:N \l_tomorrow_leap_bool \tl_new:N \l_tomorrow_daysinmonth_tl \int_new:N \l_tomorrow_day_int \int_new:N \l_tomorrow_month_int \int_new:N \l_tomorrow_year_int

\prop_gput:Nnn \g_tomorrow_months_prop { 1 } { 31 } \prop_gput:Nnn \g_tomorrow_months_prop { 2 } { \bool_if:NTF \l_tomorrow_leap_bool { 29 } { 28 } } \prop_gput:Nnn \g_tomorrow_months_prop { 3 } { 31 } \prop_gput:Nnn \g_tomorrow_months_prop { 4 } { 30 } \prop_gput:Nnn \g_tomorrow_months_prop { 5 } { 31 } \prop_gput:Nnn \g_tomorrow_months_prop { 6 } { 30 } \prop_gput:Nnn \g_tomorrow_months_prop { 7 } { 31 } \prop_gput:Nnn \g_tomorrow_months_prop { 8 } { 31 } \prop_gput:Nnn \g_tomorrow_months_prop { 9 } { 30 } \prop_gput:Nnn \g_tomorrow_months_prop { 10 } { 31 } \prop_gput:Nnn \g_tomorrow_months_prop { 11 } { 30 } \prop_gput:Nnn \g_tomorrow_months_prop { 12 } { 31 }

\cs_new_protected:Npn \tomorrow_check_leap:n #1 { \int_compare:nTF { 0 = \int_mod:nn { #1 } { 4 } } {% possibly a leap year \int_compare:nTF { 0 = \int_mod:nn { #1 } { 100 } } {% possibly not a leap year \int_compare:nTF { 0 = \int_mod:nn { #1/100 } { 4 } } {% leap year \bool_set_true:N \l_tomorrow_leap_bool } {% not leap year \bool_set_false:N \l_tomorrow_leap_bool } } {% leap year \bool_set_true:N \l_tomorrow_leap_bool } } {% not leap year \bool_set_false:N \l_tomorrow_leap_bool } }

\cs_new_protected:Npn \tomorrow_set_tomorrow:nnn #1 #2 #3 { \int_compare:nT { #2 = 2 } { \tomorrow_check_leap:n { #3 } } \int_set:Nn \l_tomorrow_day_int { #1 } \int_set:Nn \l_tomorrow_month_int { #2 } \int_set:Nn \l_tomorrow_year_int { #3 } __tomorrow_incr_day: } \cs_new_protected:Npn __tomorrow_incr_day: { \int_incr:N \l_tomorrow_day_int \prop_get:NVN \g_tomorrow_months_prop \l_tomorrow_month_int \l_tomorrow_daysinmonth_tl \int_compare:nT { \l_tomorrow_day_int > \tl_use:N \l_tomorrow_daysinmonth_tl } { \int_set:Nn \l_tomorrow_day_int { 1 } __tomorrow_incr_month: } } \cs_new_protected:Npn __tomorrow_incr_month: { \int_incr:N \l_tomorrow_month_int \int_compare:nT { \l_tomorrow_month_int > 12 } { \int_set:Nn \l_tomorrow_month_int { 1 } \int_incr:N \l_tomorrow_year_int } } \cs_generate_variant:Nn \prop_get:Nn { NV,Ne }

\NewDocumentCommand{\printtomorrowof}{mmm} { \tomorrow_set_tomorrow:nnn { #1 } { #2 } { #3 } Today~it~is~ \int_to_arabic:n { #3 }/ \int_to_arabic:n { #2 }/ \int_to_arabic:n { #1 },~ tomorrow~it~is~ \int_to_arabic:n { \l_tomorrow_year_int }/ \int_to_arabic:n { \l_tomorrow_month_int }/ \int_to_arabic:n { \l_tomorrow_day_int } \par } \ExplSyntaxOff

\begin{document}

\printtomorrowof{\day}{\month}{\year} \printtomorrowof{30}{10}{2012} \printtomorrowof{31}{10}{2012} \printtomorrowof{31}{12}{2012} \printtomorrowof{28}{2}{2012} \printtomorrowof{28}{2}{2013} \printtomorrowof{28}{2}{1900} \printtomorrowof{28}{2}{2000}

\end{document}

As you see, leap years are correctly recognized. Only Gregorian calendar, of course.

In order to define a suitable \tomorrow command, you can add (before \ExplSyntaxOn) a babel version

\NewDocumentCommand{\tomorrow}{}
 {
  \tomorrow_set_tomorrow:nnn { \day } { \month } { \year }
  \group_begin:
  \day = \l_tomorrow_day_int
  \month = \l_tomorrow_month_int
  \year = \l_tomorrow_year_int
  \today
  \group_end:
 }

or a datetime version (requires package datetime, of course)

\NewDocumentCommand{\tomorrow}{}
 {
  \tomorrow_set_tomorrow:nnn { \day } { \month } { \year }
  \formatdate { \l_tomorrow_day_int }
              { \l_tomorrow_month_int }
              { \l_tomorrow_year_int }
 }

enter image description here


This is, of course, overkill if one wants only tomorrow's date. The macros actually allow to compute any date from a given one, given the interval (positive or negative). One might make expandable also the "reverse" from a Julian date to the form "Day/Month/Year", but it would be very slow.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\juliandate}{ m m m }
 {
  \juliandate_calc:nnnn { #1 } { #2 } { #3 } { \use:n }
 }
\NewDocumentCommand{\storejuliandate}{ s m m m m }
 {
  \IfBooleanTF{#1}
   {
    \juliandate_calc:nnnn { #3 } { #4 } { #5 } { \cs_set:Npx #2 }
   }
   {
    \juliandate_calc:nnnn { #3 } { #4 } { #5 } { \cs_new:Npx #2 }
   }
 }
\cs_new:Npn \juliandate_calc:nnnn #1 #2 #3 #4 % #1 = day, #2 = month, #3 = year, #4 = what to do
 {
  #4 
   {
    \int_eval:n
     {
      #1 +
      \int_div_truncate:nn { 153 * (#2 + 12 * \int_div_truncate:nn { 14 - #2 } { 12 } - 3) + 2 } { 5 } +
      365 * (#3 + 4800 - \int_div_truncate:nn { 14 - #2 } { 12 } ) +
      \int_div_truncate:nn { #3 + 4800 - \int_div_truncate:nn { 14 - #2 } { 12 } } { 4 } -
      \int_div_truncate:nn { #3 + 4800 - \int_div_truncate:nn { 14 - #2 } { 12 } } { 100 } + 
      \int_div_truncate:nn { #3 + 4800 - \int_div_truncate:nn { 14 - #2 } { 12 } } { 400 } -
      32045
     }
   }
 }

\tl_new:N \l__juliandate_g_tl \tl_new:N \l__juliandate_dg_tl \tl_new:N \l__juliandate_c_tl \tl_new:N \l__juliandate_dc_tl \tl_new:N \l__juliandate_b_tl \tl_new:N \l__juliandate_db_tl \tl_new:N \l__juliandate_a_tl \tl_new:N \l__juliandate_da_tl \tl_new:N \l__juliandate_y_tl \tl_new:N \l__juliandate_m_tl \tl_new:N \l__juliandate_d_tl \int_new:N \l_juliandate_day_int \int_new:N \l_juliandate_month_int \int_new:N \l_juliandate_year_int

\cs_new:Npn __juliandate_set:nn #1 #2 { \tl_set:cx { l__juliandate_#1_tl } { \int_eval:n { #2 } } } \cs_new:Npn __juliandate_use:n #1 { \tl_use:c { l__juliandate_#1_tl } } \cs_new_protected:Npn \juliandate_reverse:n #1 { __juliandate_set:nn { g } { \int_div_truncate:nn { #1 + 32044 } { 146097 } } __juliandate_set:nn { dg } { \int_mod:nn { #1 + 32044 } { 146097 } } __juliandate_set:nn { c } { \int_div_truncate:nn { ( \int_div_truncate:nn { __juliandate_use:n { dg } } { 36524 } + 1) * 3 } { 4 } } __juliandate_set:nn { dc } { __juliandate_use:n { dg } - __juliandate_use:n { c } * 36524 } __juliandate_set:nn { b } { \int_div_truncate:nn { __juliandate_use:n { dc } } { 1461 } } __juliandate_set:nn { db } { \int_mod:nn { __juliandate_use:n { dc } } { 1461 } } __juliandate_set:nn { a } { \int_div_truncate:nn { ( \int_div_truncate:nn { __juliandate_use:n { db } } { 365 } + 1) * 3 } { 4 } } __juliandate_set:nn { da } { __juliandate_use:n { db } - __juliandate_use:n { a } * 365 } __juliandate_set:nn { y } { __juliandate_use:n { g } * 400 + __juliandate_use:n { c } * 100 + __juliandate_use:n { b } * 4 + __juliandate_use:n { a } } __juliandate_set:nn { m } { \int_div_truncate:nn { __juliandate_use:n { da } * 5 + 308 } { 153 } - 2 } __juliandate_set:nn { d } { __juliandate_use:n { da } - \int_div_truncate:nn { (__juliandate_use:n { m } + 4) * 153 } { 5 } + 122 } \int_set:Nn \l_juliandate_year_int { __juliandate_use:n { y } - 4800 + \int_div_truncate:nn { __juliandate_use:n { m } + 2 } { 12 } } \int_set:Nn \l_juliandate_month_int { \int_mod:nn { __juliandate_use:n { m } + 2 } { 12 } + 1 } \int_set:Nn \l_juliandate_day_int { __juliandate_use:n { d } + 1 } } \cs_generate_variant:Nn \juliandate_reverse:n { x }

\NewDocumentCommand{\showday}{ m } { \juliandate_reverse:n { #1 } \int_to_arabic:n { \l_juliandate_day_int }- \int_to_arabic:n { \l_juliandate_month_int }- \int_to_arabic:n { \l_juliandate_year_int } }

\NewDocumentCommand{\tomorrow}{ } { \group_begin: \juliandate_reverse:x { \juliandate_calc:nnnn { \day + 1 } { \month } { \year } { \use:n } } \day = \l_juliandate_day_int \month = \l_juliandate_month_int \year = \l_juliandate_year_int \today \group_end: } \NewDocumentCommand{\tomorrowof}{ m m m } { \group_begin: \juliandate_reverse:x { \juliandate_calc:nnnn { #1 + 1 } { #2 } { #3 } { \use:n } } \day = \l_juliandate_day_int \month = \l_juliandate_month_int \year = \l_juliandate_year_int \today \group_end: } \ExplSyntaxOff \begin{document} \juliandate{18}{12}{2012}

\storejuliandate*{\x}{18}{12}{2012}\x

\storejuliandate*{\x}{1}{1}{1900}\x

\showday{2456280}

\showday{2415021}

\tomorrow

\tomorrowof{31}{12}{2012}

\tomorrowof{28}{2}{2012}

\tomorrowof{29}{2}{2012}

\tomorrowof{28}{2}{2013}

\tomorrowof{28}{2}{1900}

\end{document}

egreg
  • 1,121,712
  • That is great work on the arithmetic. The problem, as I stated above, is to make it look like what would have been produced by today, which is affected by the documentclass, babel and a few other packages. – Max Dec 18 '12 at 00:36
  • @Max so the \tomorrow should not take any arguments. You want a command which uses \today and adds a day, without having to specify which day it is now, is that right? – Vivi Dec 18 '12 at 00:45
  • Yes, ideally. This would be accomplished by \def\newtomorrow{\tomorrow{\day}{\month}{\year} already, but it would be wrong for a german, french or american document. While it's trivial to adjust the tomorrow macro on a per user/country/document basis, the solution i am looking for would work with every documentclass and combination of packages. This may not be possible though. – Max Dec 18 '12 at 00:55
  • @Max I've shown how you can integrate the macros with babel or datetime – egreg Dec 18 '12 at 07:49
  • yes thank you very much. I am having trouble compiling it though. I get

    ! Command\prop_get:Nn' not yet defined!`

    on line

    l.72 \cs_generate_variant:Nn \prop_get:Nn

    I haven't really done much with latex3/expl3 yet and started reading the code for a couple of hours. I only seem to have \prop_get:NnN which isn't consistent with your line i think. This is under texlive 2012, do i need an updated package?

    – Max Dec 18 '12 at 14:31
  • @Max Yes, you need to update to the latest l3kernel version. – egreg Dec 18 '12 at 17:13
  • Note that as of September 2014, \prop_get:Nn has been renamed to \prop_item:Nn – egreg Sep 17 '14 at 18:01
  • 1
    @egreg The code seems to be broken... Use of \??? doesn't match its definition. <argument> \??? ! LaTeX Error: A property list was misused. l.95 \printtomorrowof{30}{10}{2012} – projetmbc Apr 20 '23 at 19:34
  • @egreg I am talking about the 1st code. – projetmbc Apr 20 '23 at 19:40
  • 1
    @projetmbc Thanks for noting, fixed. – egreg Apr 20 '23 at 21:36
3

I suggest to use datenumber package.

On preamble

\usepackage{datenumber}
\setdatetoday
\addtocounter{datenumber}{1}%
\setdatebynumber{\thedatenumber}%

In the document

today is \today
tomorrow is \datedate

Stefan Pinnow
  • 29,535
2

This question has been answered a while ago, but I didn't see a plain TeX solution here yet. Hopefully it will be useful to somebody.

\let\mydatesep=-
\newcount\advancedday
\newcount\daysinthismonth
\newcount\tempyear
\newcount\ttempyear
\def\advancedatebydays#1{%
\advancedday=\number\day%
\advance\advancedday by #1%
\tempyear=\number\year%
\ttempyear=\tempyear%
\loop%
\loop%
\ifnum\ttempyear>4 %
  \advance\ttempyear by-4 %
\repeat%
\ifnum\month=2 %
  \ifnum\ttempyear=4 %
    \daysinthismonth=29 %
  \else%
    \daysinthismonth=28 %
  \fi%
\else%
  \ifodd\month%
    \ifnum\month<8 %
      \daysinthismonth=30 %
    \else%
      \daysinthismonth=31 %
    \fi%
  \else%
    \ifnum\number\month>7 %
      \daysinthismonth=31 %
    \else%
      \daysinthismonth=30 %
    \fi%
  \fi%
\fi%
\ifnum\advancedday>\daysinthismonth%
  \ifnum\month=12 %
    \advance \tempyear by 1 %
    \advance \ttempyear by 1 %
    \advance \advancedday by -\daysinthismonth%
    \advance \month by -11 %
  \else%
    \advance \advancedday by -\daysinthismonth%
    \advance \month by 1 %
  \fi%
\repeat%
\number\advancedday\mydatesep\number\month\mydatesep\number\tempyear%
}%

\advancedatebydays{302}
\bye
1010011010
  • 6,357