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 want to determine how many days there are in a particular month.

Using the datenumber package, I thought I could simply set the date to the 1st of the next month and then back up one day would be the end of the month and extract the date. Well that sure seemed simple when I came up with it, but then got stuck at actually extracting the day of the month.

So, what do I need to replace

\xdef\LastDayOfMonth{\value{dateday}}

with the get the number of days in the month.

Notes:

  • I am not opposed to additional packages, so any package solution is fine.

Code:

\documentclass{article}
\usepackage{datenumber}
\usepackage{pgffor}

\newcounter{GivenDateCounter}
\newcommand{\LastDayOfMonth}{XX}%
\newcommand{\NumberOfDaysInMonth}[2]{%
    % #1 = YYYY
    % #2 = MM
    \ifnum#2<12\relax
        % Since this is NOT Dec we can just go to the 1st of the next
        % month and back up one day.
        \setmydatenumber{GivenDateCounter}%
                {#1}%
                {\numexpr#2+1\relax}% Next month
                {01}% First of the month
    \else
        % Since this IS Dec we can just go to Jan 1st of the next
        % year and back up one day.
        \setmydatenumber{GivenDateCounter}%
                {\numexpr#1+1\relax}% Next Year
                {01}% Next day is Jan next year since current month is 12
                {01}% First of the month
    \fi
    \addtocounter{GivenDateCounter}{-1}% Now we are the end of the required month
    \xdef\LastDayOfMonth{\value{dateday}}%  <---- Stuck here.
    \typeout{**** \string\LastDayOfMonth for #1-#2=\LastDayOfMonth}%
}%

\begin{document}

\foreach \YearNumber in {2013, 2014} {%
    \foreach \MonthNumber in {01, 02, ..., 12} {%
        \par
        Number of Days in \YearNumber-\MonthNumber{} is 
        \NumberOfDaysInMonth{\YearNumber}{\MonthNumber}.%
    }%
}%


\end{document}
share|improve this question
2  
The number of days in each month is independent of the year except for February which depends on the year being a leap year or not. Wouldn't it be easier to just encode the leap year algorithm and use an if-cascade? if year is not divisible by 4 then common year else if year is not divisible by 100 then leap year else if year is divisible by 400 then leap year else common year –  Christian Lindig May 1 at 17:14
    
@ChristianLindig: Good suggestion, but I'd prefer not to code it if possible. Although the two solutions below that compute it makes it look a lot simpler than I had thought it would be. –  Peter Grill May 1 at 20:05

3 Answers 3

up vote 8 down vote accepted

I'd say to use \arabic{dateday}, since \value{dateday} is not expandable (it expands to the registers name, not to the value). However it doesn't work, because dateday is not set.

Since you're not bound to datetime, here's a version with xparse.

\documentclass{article}
\usepackage{xparse,pgffor,multicol}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand\NumberOfDaysInMonth { m m }
 {
  \grill_numb_days_month:nn { #1 } { #2 }
 }

\cs_new:Npn \grill_numb_days_month:nn #1 #2
 {
  \int_case:nn { #2 }
   {
    {1}{31}
    {2}{ \grill_if_leap_year:nTF { #1 } { 29 } { 28 } }
    {3}{31}
    {4}{30}
    {5}{31}
    {6}{30}
    {7}{31}
    {8}{31}
    {9}{30}
    {10}{31}
    {11}{30}
    {12}{31}
   }
 }

\prg_new_conditional:Npnn \grill_if_leap_year:n #1 { p,T,F,TF }
 {
  \bool_if:nTF
   {
    \int_compare_p:n { \int_mod:nn { #1 } { 4 } != 0 }
    ||
    (
     \int_compare_p:n { \int_mod:nn { #1 } { 4 } == 0 }
     &&
     \int_compare_p:n { \int_mod:nn { \int_div_truncate:nn { #1 } { 100 } } { 4 } != 0 }
    ) 
   }
   { \prg_return_false: }
   { \prg_return_true: }
 }

\ExplSyntaxOff

\begin{document}
\begin{multicols}{2}

\foreach \YearNumber in {1900, 2000, 2012, 2013} {%
    \foreach \MonthNumber in {1, 2, ..., 12} {%
        \par
        Number of Days in \YearNumber-\MonthNumber{} is 
        \NumberOfDaysInMonth{\YearNumber}{\MonthNumber}.%
    }
}

\end{multicols}

\end{document}

Note that \NumberOfDaysInMonth is fully expandable, so

\edef\MDCCFebruary{\NumberOfDaysInMonth{1700}{2}}

would define the macro to expand to 28.

enter image description here

The conditional command \grill_if_leap_year:nTF can also be used in other situations. It has the four forms: predicate, true, false and true/false.

share|improve this answer

An old-school way using \ifnum and mod calculations from intcalc:

enter image description here

\documentclass{article}
\usepackage{multicol,pgffor,intcalc}
\newcommand{\NumberOfDaysInMonth}[2]{% \NumberOfDaysInMonth{<year>}{<month>}
  \ifcase#2
  \or 31% January
  \or% February
    \ifnum\intcalcMod{#1}{4}=0
      \ifnum\intcalcMod{#1}{100}=0
        \ifnum\intcalcMod{#1}{400}=0
          29% Year divisible by 4 and 100 and 400
        \else
          28% Year divisible by 4 and 100 (not 400)
        \fi
      \else
        29% Year divisible by 4 (not 100 nor 400)
      \fi
    \else
      28% Year not divisible by 4
    \fi
  \or 31% March
  \or 30% April
  \or 31% May
  \or 30% June
  \or 31% July
  \or 31% August
  \or 30% September
  \or 31% October
  \or 30% November
  \or 31% December
  \else
    999% Invalid month...
  \fi
}

\begin{document}

\begin{multicols}{2}

\foreach \YearNumber in {1900, 2000, 2012, 2013} {%
    \foreach \MonthNumber in {1, 2, ..., 12} {%
        \par
        Number of Days in \YearNumber-\MonthNumber{} is 
        \NumberOfDaysInMonth{\YearNumber}{\MonthNumber}.%
    }
}

\end{multicols}

\end{document}
share|improve this answer

You can use package pgfcalendar from the pgf bundle. The utility macros accept date input as <year>-<month>-last for the last day in <month> of <year>.

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

\begin{document} 

\newcount\datecount
\newcommand\daysinmonth[2]{%
  \pgfcalendardatetojulian{#1-#2-last}{\datecount}%
  \pgfcalendarjuliantodate{\the\datecount}{\dyear}{\dmonth}{\dday}%
  \dday
}%

\daysinmonth{2012}{2}\par
\daysinmonth{2014}{2}\par
\daysinmonth{2014}{5}

\end{document}
share|improve this answer

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.