Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
    
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 1: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 1: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 1: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 2:15
    
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 9:07
show 2 more comments

2 Answers 2

up vote 17 down vote accepted

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}
\usepackage{xparse}
\ExplSyntaxOn
\prop_new:N \g_tomorrow_months_prop
\bool_new:N \l_tomorrow_leap_bool
\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
  \int_compare:nT
   { \l_tomorrow_day_int > \prop_get:NV \g_tomorrow_months_prop \l_tomorrow_month_int }
   {
    \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 }

\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}
share|improve this answer
    
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 0: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 0: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 0:55
    
@Max I've shown how you can integrate the macros with babel or datetime –  egreg Dec 18 '12 at 7: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
show 1 more comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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