How to compare a date with a set of dates











up vote
3
down vote

favorite












I am creating a schedule for weekly lectures using the following code



documentclass{article}
usepackage{advdate}

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newififfirst
firsttrue
newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
section*{today}
}

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

end{document}


The code works fine. Now, let's suppose there are holidays on March 08, March 29, April 18, May 17, and June 18.



My question is: how to redefine the nextlec to skip a holiday and return the next non-holiday date?



Note: this is not a duplicate from here, since I want to compare a calculated date to a set of several dates that I want to define.



EDITS:



After Jeffrey J Weimer suggestion (see comments), I tried to implemente the following piece code in my original one, but got a lot of error.



defholidays#1{def@holidays{#1}}
newcommand{theholidays}{ {@holidays} }

newififfirst
firsttrue

newcommand{jumpweek}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
}

newcommandnextlecbool{true}

newcommand{nextlec}{%
jumpweek
foeach holiday in theholidays
while{nextlecbool}
ifnum (10000*theyear + 100*themonth + theday) = holiday
section*{today}
Feriado.
jumpweek
else
renewcommand{nextlecbool}{false}
fi
EndWhile
;
renewcommand{nextlecbool}{true}
}









share|improve this question
























  • Where are you defining the dates? In an external file that is loaded? If so, I almost have to think the datatool package will provide a viable approach.
    – Jeffrey J Weimer
    yesterday










  • @JeffreyJWeimer I would like to define the date at the same tex file, but I don't know how to do this.
    – Brasil
    yesterday






  • 1




    OK.I think a clever trick may be to concatenate the holiday numbers for the month + day and make a comparison to the resulting number. For example, May 17 becomes 517 and June 18 becomes 618. Concatenation is a string operation. An alternative for numerics would use calc with for example 100*month + day.
    – Jeffrey J Weimer
    yesterday










  • Great @JeffreyJWeimer. It's really good idea. I will try it. You could make your comment an anwer. Then, I will accept it after getting positive reault... thank you!
    – Brasil
    yesterday










  • The calendars package may do what you want.
    – Jeffrey J Weimer
    14 hours ago















up vote
3
down vote

favorite












I am creating a schedule for weekly lectures using the following code



documentclass{article}
usepackage{advdate}

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newififfirst
firsttrue
newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
section*{today}
}

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

end{document}


The code works fine. Now, let's suppose there are holidays on March 08, March 29, April 18, May 17, and June 18.



My question is: how to redefine the nextlec to skip a holiday and return the next non-holiday date?



Note: this is not a duplicate from here, since I want to compare a calculated date to a set of several dates that I want to define.



EDITS:



After Jeffrey J Weimer suggestion (see comments), I tried to implemente the following piece code in my original one, but got a lot of error.



defholidays#1{def@holidays{#1}}
newcommand{theholidays}{ {@holidays} }

newififfirst
firsttrue

newcommand{jumpweek}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
}

newcommandnextlecbool{true}

newcommand{nextlec}{%
jumpweek
foeach holiday in theholidays
while{nextlecbool}
ifnum (10000*theyear + 100*themonth + theday) = holiday
section*{today}
Feriado.
jumpweek
else
renewcommand{nextlecbool}{false}
fi
EndWhile
;
renewcommand{nextlecbool}{true}
}









share|improve this question
























  • Where are you defining the dates? In an external file that is loaded? If so, I almost have to think the datatool package will provide a viable approach.
    – Jeffrey J Weimer
    yesterday










  • @JeffreyJWeimer I would like to define the date at the same tex file, but I don't know how to do this.
    – Brasil
    yesterday






  • 1




    OK.I think a clever trick may be to concatenate the holiday numbers for the month + day and make a comparison to the resulting number. For example, May 17 becomes 517 and June 18 becomes 618. Concatenation is a string operation. An alternative for numerics would use calc with for example 100*month + day.
    – Jeffrey J Weimer
    yesterday










  • Great @JeffreyJWeimer. It's really good idea. I will try it. You could make your comment an anwer. Then, I will accept it after getting positive reault... thank you!
    – Brasil
    yesterday










  • The calendars package may do what you want.
    – Jeffrey J Weimer
    14 hours ago













up vote
3
down vote

favorite









up vote
3
down vote

favorite











I am creating a schedule for weekly lectures using the following code



documentclass{article}
usepackage{advdate}

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newififfirst
firsttrue
newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
section*{today}
}

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

end{document}


The code works fine. Now, let's suppose there are holidays on March 08, March 29, April 18, May 17, and June 18.



My question is: how to redefine the nextlec to skip a holiday and return the next non-holiday date?



Note: this is not a duplicate from here, since I want to compare a calculated date to a set of several dates that I want to define.



EDITS:



After Jeffrey J Weimer suggestion (see comments), I tried to implemente the following piece code in my original one, but got a lot of error.



defholidays#1{def@holidays{#1}}
newcommand{theholidays}{ {@holidays} }

newififfirst
firsttrue

newcommand{jumpweek}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
}

newcommandnextlecbool{true}

newcommand{nextlec}{%
jumpweek
foeach holiday in theholidays
while{nextlecbool}
ifnum (10000*theyear + 100*themonth + theday) = holiday
section*{today}
Feriado.
jumpweek
else
renewcommand{nextlecbool}{false}
fi
EndWhile
;
renewcommand{nextlecbool}{true}
}









share|improve this question















I am creating a schedule for weekly lectures using the following code



documentclass{article}
usepackage{advdate}

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newififfirst
firsttrue
newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
section*{today}
}

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

end{document}


The code works fine. Now, let's suppose there are holidays on March 08, March 29, April 18, May 17, and June 18.



My question is: how to redefine the nextlec to skip a holiday and return the next non-holiday date?



Note: this is not a duplicate from here, since I want to compare a calculated date to a set of several dates that I want to define.



EDITS:



After Jeffrey J Weimer suggestion (see comments), I tried to implemente the following piece code in my original one, but got a lot of error.



defholidays#1{def@holidays{#1}}
newcommand{theholidays}{ {@holidays} }

newififfirst
firsttrue

newcommand{jumpweek}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
}

newcommandnextlecbool{true}

newcommand{nextlec}{%
jumpweek
foeach holiday in theholidays
while{nextlecbool}
ifnum (10000*theyear + 100*themonth + theday) = holiday
section*{today}
Feriado.
jumpweek
else
renewcommand{nextlecbool}{false}
fi
EndWhile
;
renewcommand{nextlecbool}{true}
}






date advdate






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 17 hours ago

























asked yesterday









Brasil

362312




362312












  • Where are you defining the dates? In an external file that is loaded? If so, I almost have to think the datatool package will provide a viable approach.
    – Jeffrey J Weimer
    yesterday










  • @JeffreyJWeimer I would like to define the date at the same tex file, but I don't know how to do this.
    – Brasil
    yesterday






  • 1




    OK.I think a clever trick may be to concatenate the holiday numbers for the month + day and make a comparison to the resulting number. For example, May 17 becomes 517 and June 18 becomes 618. Concatenation is a string operation. An alternative for numerics would use calc with for example 100*month + day.
    – Jeffrey J Weimer
    yesterday










  • Great @JeffreyJWeimer. It's really good idea. I will try it. You could make your comment an anwer. Then, I will accept it after getting positive reault... thank you!
    – Brasil
    yesterday










  • The calendars package may do what you want.
    – Jeffrey J Weimer
    14 hours ago


















  • Where are you defining the dates? In an external file that is loaded? If so, I almost have to think the datatool package will provide a viable approach.
    – Jeffrey J Weimer
    yesterday










  • @JeffreyJWeimer I would like to define the date at the same tex file, but I don't know how to do this.
    – Brasil
    yesterday






  • 1




    OK.I think a clever trick may be to concatenate the holiday numbers for the month + day and make a comparison to the resulting number. For example, May 17 becomes 517 and June 18 becomes 618. Concatenation is a string operation. An alternative for numerics would use calc with for example 100*month + day.
    – Jeffrey J Weimer
    yesterday










  • Great @JeffreyJWeimer. It's really good idea. I will try it. You could make your comment an anwer. Then, I will accept it after getting positive reault... thank you!
    – Brasil
    yesterday










  • The calendars package may do what you want.
    – Jeffrey J Weimer
    14 hours ago
















Where are you defining the dates? In an external file that is loaded? If so, I almost have to think the datatool package will provide a viable approach.
– Jeffrey J Weimer
yesterday




Where are you defining the dates? In an external file that is loaded? If so, I almost have to think the datatool package will provide a viable approach.
– Jeffrey J Weimer
yesterday












@JeffreyJWeimer I would like to define the date at the same tex file, but I don't know how to do this.
– Brasil
yesterday




@JeffreyJWeimer I would like to define the date at the same tex file, but I don't know how to do this.
– Brasil
yesterday




1




1




OK.I think a clever trick may be to concatenate the holiday numbers for the month + day and make a comparison to the resulting number. For example, May 17 becomes 517 and June 18 becomes 618. Concatenation is a string operation. An alternative for numerics would use calc with for example 100*month + day.
– Jeffrey J Weimer
yesterday




OK.I think a clever trick may be to concatenate the holiday numbers for the month + day and make a comparison to the resulting number. For example, May 17 becomes 517 and June 18 becomes 618. Concatenation is a string operation. An alternative for numerics would use calc with for example 100*month + day.
– Jeffrey J Weimer
yesterday












Great @JeffreyJWeimer. It's really good idea. I will try it. You could make your comment an anwer. Then, I will accept it after getting positive reault... thank you!
– Brasil
yesterday




Great @JeffreyJWeimer. It's really good idea. I will try it. You could make your comment an anwer. Then, I will accept it after getting positive reault... thank you!
– Brasil
yesterday












The calendars package may do what you want.
– Jeffrey J Weimer
14 hours ago




The calendars package may do what you want.
– Jeffrey J Weimer
14 hours ago










2 Answers
2






active

oldest

votes

















up vote
1
down vote













Perhaps this exhibits some tricks about recursive iteration and about using delimited arguments for taking apart strings of pattern



<word for month><space><number of day>,<space><year>



documentclass{article}
usepackage{datenumber}
usepackage{advdate}

makeatletter
%-----------------------------------------------------------------
% Section: Code for comparing dates.
%-----------------------------------------------------------------
% monthtonumber{<name of a month>} yields the number of that
% month (range 1..12; January -> 1, February -> 2 ,...,
% December -> 12)
% monthfork just selects/"spits out" an undelimited argument that
% comes behind a delimited argument's delimiter which is formed by
% a list of all months.
% In any case there will be only one place where the list
% is correct and where the delimiter will match...
% ! is used both for making visibly distinguishing month-phrases
% from each other more easy and for denoting where the
% remainder which is to be removed by the !!!!-delimited argument
% ends.
%-----------------------------------------------------------------
newcommand*monthtonumber[1]{%
monthfork
!#1!February!March!April!May!June!July!August!September!October!November!December!{1}%
!January!#1!March!April!May!June!July!August!September!October!November!December!{2}%
!January!February!#1!April!May!June!July!August!September!October!November!December!{3}%
!January!February!March!#1!May!June!July!August!September!October!November!December!{4}%
!January!February!March!April!#1!June!July!August!September!October!November!December!{5}%
!January!February!March!April!May!#1!July!August!September!October!November!December!{6}%
!January!February!March!April!May!June!#1!August!September!October!November!December!{7}%
!January!February!March!April!May!June!July!#1!September!October!November!December!{8}%
!January!February!March!April!May!June!July!August!#1!October!November!December!{9}%
!January!February!March!April!May!June!July!August!September!#1!November!December!{10}%
!January!February!March!April!May!June!July!August!September!October!#1!December!{11}%
!January!February!March!April!May!June!July!August!September!October!November!#1!{12}%
!!!!%
}%
%-----------------------------------------------------------------
% monthfork grabs the undelimited argument behind that
% list of months that is correct/in correct order due to insertion
% of the name of the month by monthtonumber.
% As monthfork needs to be an argument that processes
% delimited arguments, it needs to be defined in terms of
% def. Nonetheless provide a dummy-definition in terms
% of newcommand before for triggering an error-message
% in case one is about to override a macro that already
% is defined, e.g., by some package.
%-----------------------------------------------------------------
newcommandmonthfork{}%
defmonthfork#1!January!February!March!April!May!June!%
July!August!September!October!November!%
December!#2#3!!!!{#2}%
%
%-----------------------------------------------------------------
% comparedatetotoday{<month as word><space><day as number>,<space><year as number>}%
% {<tokens in case dates do not differ>}%
% {<tokens in case dates differ>}%
% converts <month as word> to a number and compares that to the value of month,
% compares <day as number> to the value of day,
% compares <year as number> to the value of year
% In case a difference is detected delivers <tokens in case dates differ>
% In case no difference is detected delivers <tokens in case dates do not differ>
% The macro splitdateandcomparecomponents is used for obtaining
% the components of the date.
% As the date is provided in the pattern
% <month as word><space><day as number>,<space><year as number>
% a space is attached at the end which yields the pattern
% <month as word><space><day as number>,<space><year as number><space>
% and then the components of that pattern are obtained by the macro
% splitdateandcomparecomponents where the three arguments are delimited
% accordingly. Again first a newcommand-dummy-definition for
% triggering error-message in case of overriding an already existing
% command.
%-----------------------------------------------------------------
newcommandcomparedatetotoday[1]{splitdateandcomparecomponents#1 }%
newcommandsplitdateandcomparecomponents{}%
defsplitdateandcomparecomponents#1 #2, #3 {%
ifnumthemonth=monthtonumber{#1} %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheday=#2 %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheyear=#3 %
expandafter@firstoftwoelseexpandafter@secondoftwofi
{@firstoftwo}%
}%
}%
@secondoftwo
}%
%-----------------------------------------------------------------
% comparedatestotoday{%
% {{<month 1 as word><space><day 1 as number>,<space><year 1 as number>}}%<-date1
% {{<month 2 as word><space><day 2 as number>,<space><year 2 as number>}}%<-date2
% ...
% {{<month k as word><space><day k as number>,<space><year k as number>}}%<-datek
% }%
% {<tokens in case at least one date does not differ from the date formed by
% year, month and day>}%
% {<tokens in case all dates do differ from the date formed by
% year, month and day>}%
%
% comparedatestotoday attaches the token relax to the list of
% holiday-dates and prepends an argument holding the token
% @secondoftwo and calls comparedatestotodayloop.
%
% comparedatestotodayloop in a recursive loop compares with all
% elements of the list of holiday-dates compares the date-components to
% month, day, year for finding out if month, day and year
% denote one of these holiday-dates.
%
% comparedatestotodayloop's recursive loop works as follows:
%
% comparedatestotodayloop processes two arguments.
% The first argument denotes the action in case the end of the list is reached.
% The second argument either is an element of the list of dates or is the
% attached token relax.
% Thus for finding out whether the end of the list is reached, one can
% check whether the second argument equals relax.
% If so, just spit out the first argument which denotes the action in
% case the end of the list is reached.
% If not so, compare the date held in the second argument to
% month, day, year (which are components of today) for finding out
% if today is a holiday and therefore the first argument needs to be
% replaced by @firstoftwo before doing the next iteration by
% calling comparedatestotodayloop again...
%-----------------------------------------------------------------
newcommandcomparedatestotoday[1]{%
comparedatestotodayloop{@secondoftwo}#1relax
}%
% comparedatestotodayloop{<token in case end of list is reached>}%
% {<either element of list of holiday-dates
% or relax which was attached for marking
% the end of the list of holiday-dates>}%
newcommandcomparedatestotodayloop[2]{%
ifxrelax#2expandafter@firstoftwoelseexpandafter@secondoftwofi
{#1}{%
comparedatetotoday{#2}%
{comparedatestotodayloop{@firstoftwo}}%
{comparedatestotodayloop{#1}}%
}%
}%
%-----------------------------------------------------------------
% Section: Code for printing lists of dates.
%-----------------------------------------------------------------
% PrintListOfHolidays[<macro for formatting a date>]%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<macro holding the list of dates>}
newcommandexchange[2]{#2#1}
newcommandPrintListOfHolidays[4][RemoveDaysLeadZero]{%
expandafterexchangeexpandafter{#4}{Holidayloop{#1}{}{}{#2}{#3}}relaxrelax
}%
%-----------------------------------------------------------------
% Holidayloop{<macro for formatting a date>}%
% {<separator for this date in case it is not the last date of the list>}%
% {<separator for this date in case it is the last date of the list>}%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<month as word><space><day as number>,>space><year as number>}
% At first glimpse the arguments <separator for this date in case it is not the last date of the list>
% and <separator between dates> respective
% <separator for this date in case it is the last date of the list> and
% <separator for the last date> seem to be the same.
% But we must consider the case of the list being empty or holding
% only one element: In these cases we don't want any separator, thus
% we need a possibility to pass empty arguments for the first
% iteration...
%
newcommandHolidayloop[7]{%
ifxrelax#6expandafter@gobbleelseexpandafter@firstofonefi
{%
ifxrelax#7expandafter@firstoftwoelseexpandafter@secondoftwofi
{#3#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: last date of the list
{#2#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: not the last date of the list
}%
}%
% macros for formatting the date.
% They all take the date and use "inner" macros that by means of
% delimited arguments split it into components and do the desired
% things to the components.
newcommandRemoveDaysLeadZero[1]{innerRemoveDaysLeadZero#1relax}
newcommandinnerRemoveDaysLeadZero{}%
definnerRemoveDaysLeadZero#1 #2,#3relax{mbox{#1 number#2,#3}}%
%
newcommandRemoveYear[1]{innerRemoveyear#1relax}
newcommandinnerRemoveyear{}%
definnerRemoveyear#1 #2,#3relax{mbox{#1 number#2}}%
%
newcommandAddDayOfWeek[1]{innerAddDayOfweek#1relax}
newcommandinnerAddDayOfweek{}%
definnerAddDayOfweek#1 #2, #3relax{%
setdatenumber{#3}{monthtonumber{#1}}{#2}%
mbox{datedayname, #1 #2, #3}%
}%
%
% As we need to compare each today/each combination of
% year, month and day to the list of holidays for
% for finding out whether a today is on a holiday, we can
% maintain a list of such todays that are on holidays.
% Whenever such a today is found, it will added to the macro
% @DaysAffectedByHolidays. That macro in turn is used at the
% end of the document for writing to .aux-file a directive
% for defining a macro DaysAffectedByHolidays that holds the
% list of only those holidays that "collide" with lecture-days.
%
newcommandDaysAffectedByHolidays{}%
newcommand@DaysAffectedByHolidays{}%
AtEndDocument{%
immediatewrite@auxout{%
stringgdefstringDaysAffectedByHolidays{@DaysAffectedByHolidays}%
}%
}%

newififfirst
firsttrue

newcounter{lecture}

newlengthscratchlength

newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
% Compare the advanced today to each element of the list of holidays:
expandaftercomparedatestotoday
expandafter{Holidaylist}{%
%
% Tokens in case the advanced today denotes one of the holidays:
%
%setdatenumber{year}{month}{day}%
%section*{Holiday: datedayname, today} Holiday.%
xdef@DaysAffectedByHolidays{@DaysAffectedByHolidays{today}}%
% calculate another lecture-day...
nextlec
}{%
%
% Tokens in case the advanced today does not denote one of the holidays:
%
stepcounter{lecture}%
setdatenumber{year}{month}{day}%
section*{Lecture~arabic{lecture}: datedayname, today}%
}%
}%

makeatother

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newcommand*Holidaylist{%
{March 08, 2019}%
{March 29, 2019}%
{April 18, 2019}%
{May 17, 2019}%
{June 18, 2019}%
}%

begin{document}

settowidthscratchlength{hbox{textbf{All holidays: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

% The macros holding the lists of dates of holidays do not
% contain the token relax. Therefore if they are not empty
% as there is at least one holiday, things will end up in
% the else-branch of the if-comparison.
%
ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

% These occur after the 2nd LaTeX-run:

settowidthscratchlength{hbox{textbf{Holidays that affect our lecture-plan: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

newpage

nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

end{document}


enter image description hereenter image description here






share|improve this answer



















  • 1




    Thank you @UlrichDiez. Your suggestion seems to work (I didn't try yet). However, it is to big and complex for me (I am just a junior in LaTeX). Could you, please, document or explain the role of pieces of this code? (For instance, whats the meaning of !? Or, why defmonthfork#1 after newcommand{monthfork}{}?) Sorry for my inconvenience and thank you again.
    – Brasil
    18 hours ago










  • @Brasil I tried to add some commenting. ;-)
    – Ulrich Diez
    11 hours ago


















up vote
0
down vote













You can make a list of the holidays and check whether the current date as set by AdvDate appears in the list:



documentclass[twocolumn]{article}
usepackage{advdate}
usepackage{xparse}

ExplSyntaxOn
clist_new:N g_brasil_holiday_clist

NewDocumentCommand{holidays}{m}
{
clist_gset:Nn g_brasil_holiday_clist { #1 }
}
NewDocumentCommand{nextlec}{}
{
brasil_check_holiday:
section*{today}
}

cs_new_protected:Nn brasil_check_holiday:
{
AdvanceDate[7]
clist_if_in:NxT g_brasil_holiday_clist
{ int_eval:n {day} / int_eval:n {month} }
{ brasil_check_holiday: } % redo the test
}
cs_generate_variant:Nn clist_if_in:NnT { Nx }
ExplSyntaxOff

holidays{8/3,29/3,18/4,17/5,18/6}

%... Set the first lecture date

ThisYear{2019}
ThisMonth{3}
ThisDay{1}
AdvanceDate[-7]

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

nextlec
Lecture 11.

nextlec
Lecture 12.

nextlec
Lecture 13.

nextlec
Lecture 14.

nextlec
Lecture 15.

nextlec
Lecture 16.

nextlec
Lecture 17.

nextlec
Lecture 18.

end{document}


Here I use twocolumn just for reducing the output to a single page.



enter image description here






share|improve this answer





















  • Hi @egreg. This code seems very cool! I just read about the xparse package and as far as I could understand, it is like a programming language with features that apply for LaTeX. So, let's go with my questions: (a) would it be possible to do the same task without xparse? (b) about the commands ExplSyntaxOn, ´clist, NewDocumentCommand, and cs, are they LaTeX native, or definitions inside the xparse`? Thank you very much!
    – Brasil
    13 hours ago











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f461120%2fhow-to-compare-a-date-with-a-set-of-dates%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote













Perhaps this exhibits some tricks about recursive iteration and about using delimited arguments for taking apart strings of pattern



<word for month><space><number of day>,<space><year>



documentclass{article}
usepackage{datenumber}
usepackage{advdate}

makeatletter
%-----------------------------------------------------------------
% Section: Code for comparing dates.
%-----------------------------------------------------------------
% monthtonumber{<name of a month>} yields the number of that
% month (range 1..12; January -> 1, February -> 2 ,...,
% December -> 12)
% monthfork just selects/"spits out" an undelimited argument that
% comes behind a delimited argument's delimiter which is formed by
% a list of all months.
% In any case there will be only one place where the list
% is correct and where the delimiter will match...
% ! is used both for making visibly distinguishing month-phrases
% from each other more easy and for denoting where the
% remainder which is to be removed by the !!!!-delimited argument
% ends.
%-----------------------------------------------------------------
newcommand*monthtonumber[1]{%
monthfork
!#1!February!March!April!May!June!July!August!September!October!November!December!{1}%
!January!#1!March!April!May!June!July!August!September!October!November!December!{2}%
!January!February!#1!April!May!June!July!August!September!October!November!December!{3}%
!January!February!March!#1!May!June!July!August!September!October!November!December!{4}%
!January!February!March!April!#1!June!July!August!September!October!November!December!{5}%
!January!February!March!April!May!#1!July!August!September!October!November!December!{6}%
!January!February!March!April!May!June!#1!August!September!October!November!December!{7}%
!January!February!March!April!May!June!July!#1!September!October!November!December!{8}%
!January!February!March!April!May!June!July!August!#1!October!November!December!{9}%
!January!February!March!April!May!June!July!August!September!#1!November!December!{10}%
!January!February!March!April!May!June!July!August!September!October!#1!December!{11}%
!January!February!March!April!May!June!July!August!September!October!November!#1!{12}%
!!!!%
}%
%-----------------------------------------------------------------
% monthfork grabs the undelimited argument behind that
% list of months that is correct/in correct order due to insertion
% of the name of the month by monthtonumber.
% As monthfork needs to be an argument that processes
% delimited arguments, it needs to be defined in terms of
% def. Nonetheless provide a dummy-definition in terms
% of newcommand before for triggering an error-message
% in case one is about to override a macro that already
% is defined, e.g., by some package.
%-----------------------------------------------------------------
newcommandmonthfork{}%
defmonthfork#1!January!February!March!April!May!June!%
July!August!September!October!November!%
December!#2#3!!!!{#2}%
%
%-----------------------------------------------------------------
% comparedatetotoday{<month as word><space><day as number>,<space><year as number>}%
% {<tokens in case dates do not differ>}%
% {<tokens in case dates differ>}%
% converts <month as word> to a number and compares that to the value of month,
% compares <day as number> to the value of day,
% compares <year as number> to the value of year
% In case a difference is detected delivers <tokens in case dates differ>
% In case no difference is detected delivers <tokens in case dates do not differ>
% The macro splitdateandcomparecomponents is used for obtaining
% the components of the date.
% As the date is provided in the pattern
% <month as word><space><day as number>,<space><year as number>
% a space is attached at the end which yields the pattern
% <month as word><space><day as number>,<space><year as number><space>
% and then the components of that pattern are obtained by the macro
% splitdateandcomparecomponents where the three arguments are delimited
% accordingly. Again first a newcommand-dummy-definition for
% triggering error-message in case of overriding an already existing
% command.
%-----------------------------------------------------------------
newcommandcomparedatetotoday[1]{splitdateandcomparecomponents#1 }%
newcommandsplitdateandcomparecomponents{}%
defsplitdateandcomparecomponents#1 #2, #3 {%
ifnumthemonth=monthtonumber{#1} %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheday=#2 %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheyear=#3 %
expandafter@firstoftwoelseexpandafter@secondoftwofi
{@firstoftwo}%
}%
}%
@secondoftwo
}%
%-----------------------------------------------------------------
% comparedatestotoday{%
% {{<month 1 as word><space><day 1 as number>,<space><year 1 as number>}}%<-date1
% {{<month 2 as word><space><day 2 as number>,<space><year 2 as number>}}%<-date2
% ...
% {{<month k as word><space><day k as number>,<space><year k as number>}}%<-datek
% }%
% {<tokens in case at least one date does not differ from the date formed by
% year, month and day>}%
% {<tokens in case all dates do differ from the date formed by
% year, month and day>}%
%
% comparedatestotoday attaches the token relax to the list of
% holiday-dates and prepends an argument holding the token
% @secondoftwo and calls comparedatestotodayloop.
%
% comparedatestotodayloop in a recursive loop compares with all
% elements of the list of holiday-dates compares the date-components to
% month, day, year for finding out if month, day and year
% denote one of these holiday-dates.
%
% comparedatestotodayloop's recursive loop works as follows:
%
% comparedatestotodayloop processes two arguments.
% The first argument denotes the action in case the end of the list is reached.
% The second argument either is an element of the list of dates or is the
% attached token relax.
% Thus for finding out whether the end of the list is reached, one can
% check whether the second argument equals relax.
% If so, just spit out the first argument which denotes the action in
% case the end of the list is reached.
% If not so, compare the date held in the second argument to
% month, day, year (which are components of today) for finding out
% if today is a holiday and therefore the first argument needs to be
% replaced by @firstoftwo before doing the next iteration by
% calling comparedatestotodayloop again...
%-----------------------------------------------------------------
newcommandcomparedatestotoday[1]{%
comparedatestotodayloop{@secondoftwo}#1relax
}%
% comparedatestotodayloop{<token in case end of list is reached>}%
% {<either element of list of holiday-dates
% or relax which was attached for marking
% the end of the list of holiday-dates>}%
newcommandcomparedatestotodayloop[2]{%
ifxrelax#2expandafter@firstoftwoelseexpandafter@secondoftwofi
{#1}{%
comparedatetotoday{#2}%
{comparedatestotodayloop{@firstoftwo}}%
{comparedatestotodayloop{#1}}%
}%
}%
%-----------------------------------------------------------------
% Section: Code for printing lists of dates.
%-----------------------------------------------------------------
% PrintListOfHolidays[<macro for formatting a date>]%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<macro holding the list of dates>}
newcommandexchange[2]{#2#1}
newcommandPrintListOfHolidays[4][RemoveDaysLeadZero]{%
expandafterexchangeexpandafter{#4}{Holidayloop{#1}{}{}{#2}{#3}}relaxrelax
}%
%-----------------------------------------------------------------
% Holidayloop{<macro for formatting a date>}%
% {<separator for this date in case it is not the last date of the list>}%
% {<separator for this date in case it is the last date of the list>}%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<month as word><space><day as number>,>space><year as number>}
% At first glimpse the arguments <separator for this date in case it is not the last date of the list>
% and <separator between dates> respective
% <separator for this date in case it is the last date of the list> and
% <separator for the last date> seem to be the same.
% But we must consider the case of the list being empty or holding
% only one element: In these cases we don't want any separator, thus
% we need a possibility to pass empty arguments for the first
% iteration...
%
newcommandHolidayloop[7]{%
ifxrelax#6expandafter@gobbleelseexpandafter@firstofonefi
{%
ifxrelax#7expandafter@firstoftwoelseexpandafter@secondoftwofi
{#3#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: last date of the list
{#2#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: not the last date of the list
}%
}%
% macros for formatting the date.
% They all take the date and use "inner" macros that by means of
% delimited arguments split it into components and do the desired
% things to the components.
newcommandRemoveDaysLeadZero[1]{innerRemoveDaysLeadZero#1relax}
newcommandinnerRemoveDaysLeadZero{}%
definnerRemoveDaysLeadZero#1 #2,#3relax{mbox{#1 number#2,#3}}%
%
newcommandRemoveYear[1]{innerRemoveyear#1relax}
newcommandinnerRemoveyear{}%
definnerRemoveyear#1 #2,#3relax{mbox{#1 number#2}}%
%
newcommandAddDayOfWeek[1]{innerAddDayOfweek#1relax}
newcommandinnerAddDayOfweek{}%
definnerAddDayOfweek#1 #2, #3relax{%
setdatenumber{#3}{monthtonumber{#1}}{#2}%
mbox{datedayname, #1 #2, #3}%
}%
%
% As we need to compare each today/each combination of
% year, month and day to the list of holidays for
% for finding out whether a today is on a holiday, we can
% maintain a list of such todays that are on holidays.
% Whenever such a today is found, it will added to the macro
% @DaysAffectedByHolidays. That macro in turn is used at the
% end of the document for writing to .aux-file a directive
% for defining a macro DaysAffectedByHolidays that holds the
% list of only those holidays that "collide" with lecture-days.
%
newcommandDaysAffectedByHolidays{}%
newcommand@DaysAffectedByHolidays{}%
AtEndDocument{%
immediatewrite@auxout{%
stringgdefstringDaysAffectedByHolidays{@DaysAffectedByHolidays}%
}%
}%

newififfirst
firsttrue

newcounter{lecture}

newlengthscratchlength

newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
% Compare the advanced today to each element of the list of holidays:
expandaftercomparedatestotoday
expandafter{Holidaylist}{%
%
% Tokens in case the advanced today denotes one of the holidays:
%
%setdatenumber{year}{month}{day}%
%section*{Holiday: datedayname, today} Holiday.%
xdef@DaysAffectedByHolidays{@DaysAffectedByHolidays{today}}%
% calculate another lecture-day...
nextlec
}{%
%
% Tokens in case the advanced today does not denote one of the holidays:
%
stepcounter{lecture}%
setdatenumber{year}{month}{day}%
section*{Lecture~arabic{lecture}: datedayname, today}%
}%
}%

makeatother

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newcommand*Holidaylist{%
{March 08, 2019}%
{March 29, 2019}%
{April 18, 2019}%
{May 17, 2019}%
{June 18, 2019}%
}%

begin{document}

settowidthscratchlength{hbox{textbf{All holidays: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

% The macros holding the lists of dates of holidays do not
% contain the token relax. Therefore if they are not empty
% as there is at least one holiday, things will end up in
% the else-branch of the if-comparison.
%
ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

% These occur after the 2nd LaTeX-run:

settowidthscratchlength{hbox{textbf{Holidays that affect our lecture-plan: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

newpage

nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

end{document}


enter image description hereenter image description here






share|improve this answer



















  • 1




    Thank you @UlrichDiez. Your suggestion seems to work (I didn't try yet). However, it is to big and complex for me (I am just a junior in LaTeX). Could you, please, document or explain the role of pieces of this code? (For instance, whats the meaning of !? Or, why defmonthfork#1 after newcommand{monthfork}{}?) Sorry for my inconvenience and thank you again.
    – Brasil
    18 hours ago










  • @Brasil I tried to add some commenting. ;-)
    – Ulrich Diez
    11 hours ago















up vote
1
down vote













Perhaps this exhibits some tricks about recursive iteration and about using delimited arguments for taking apart strings of pattern



<word for month><space><number of day>,<space><year>



documentclass{article}
usepackage{datenumber}
usepackage{advdate}

makeatletter
%-----------------------------------------------------------------
% Section: Code for comparing dates.
%-----------------------------------------------------------------
% monthtonumber{<name of a month>} yields the number of that
% month (range 1..12; January -> 1, February -> 2 ,...,
% December -> 12)
% monthfork just selects/"spits out" an undelimited argument that
% comes behind a delimited argument's delimiter which is formed by
% a list of all months.
% In any case there will be only one place where the list
% is correct and where the delimiter will match...
% ! is used both for making visibly distinguishing month-phrases
% from each other more easy and for denoting where the
% remainder which is to be removed by the !!!!-delimited argument
% ends.
%-----------------------------------------------------------------
newcommand*monthtonumber[1]{%
monthfork
!#1!February!March!April!May!June!July!August!September!October!November!December!{1}%
!January!#1!March!April!May!June!July!August!September!October!November!December!{2}%
!January!February!#1!April!May!June!July!August!September!October!November!December!{3}%
!January!February!March!#1!May!June!July!August!September!October!November!December!{4}%
!January!February!March!April!#1!June!July!August!September!October!November!December!{5}%
!January!February!March!April!May!#1!July!August!September!October!November!December!{6}%
!January!February!March!April!May!June!#1!August!September!October!November!December!{7}%
!January!February!March!April!May!June!July!#1!September!October!November!December!{8}%
!January!February!March!April!May!June!July!August!#1!October!November!December!{9}%
!January!February!March!April!May!June!July!August!September!#1!November!December!{10}%
!January!February!March!April!May!June!July!August!September!October!#1!December!{11}%
!January!February!March!April!May!June!July!August!September!October!November!#1!{12}%
!!!!%
}%
%-----------------------------------------------------------------
% monthfork grabs the undelimited argument behind that
% list of months that is correct/in correct order due to insertion
% of the name of the month by monthtonumber.
% As monthfork needs to be an argument that processes
% delimited arguments, it needs to be defined in terms of
% def. Nonetheless provide a dummy-definition in terms
% of newcommand before for triggering an error-message
% in case one is about to override a macro that already
% is defined, e.g., by some package.
%-----------------------------------------------------------------
newcommandmonthfork{}%
defmonthfork#1!January!February!March!April!May!June!%
July!August!September!October!November!%
December!#2#3!!!!{#2}%
%
%-----------------------------------------------------------------
% comparedatetotoday{<month as word><space><day as number>,<space><year as number>}%
% {<tokens in case dates do not differ>}%
% {<tokens in case dates differ>}%
% converts <month as word> to a number and compares that to the value of month,
% compares <day as number> to the value of day,
% compares <year as number> to the value of year
% In case a difference is detected delivers <tokens in case dates differ>
% In case no difference is detected delivers <tokens in case dates do not differ>
% The macro splitdateandcomparecomponents is used for obtaining
% the components of the date.
% As the date is provided in the pattern
% <month as word><space><day as number>,<space><year as number>
% a space is attached at the end which yields the pattern
% <month as word><space><day as number>,<space><year as number><space>
% and then the components of that pattern are obtained by the macro
% splitdateandcomparecomponents where the three arguments are delimited
% accordingly. Again first a newcommand-dummy-definition for
% triggering error-message in case of overriding an already existing
% command.
%-----------------------------------------------------------------
newcommandcomparedatetotoday[1]{splitdateandcomparecomponents#1 }%
newcommandsplitdateandcomparecomponents{}%
defsplitdateandcomparecomponents#1 #2, #3 {%
ifnumthemonth=monthtonumber{#1} %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheday=#2 %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheyear=#3 %
expandafter@firstoftwoelseexpandafter@secondoftwofi
{@firstoftwo}%
}%
}%
@secondoftwo
}%
%-----------------------------------------------------------------
% comparedatestotoday{%
% {{<month 1 as word><space><day 1 as number>,<space><year 1 as number>}}%<-date1
% {{<month 2 as word><space><day 2 as number>,<space><year 2 as number>}}%<-date2
% ...
% {{<month k as word><space><day k as number>,<space><year k as number>}}%<-datek
% }%
% {<tokens in case at least one date does not differ from the date formed by
% year, month and day>}%
% {<tokens in case all dates do differ from the date formed by
% year, month and day>}%
%
% comparedatestotoday attaches the token relax to the list of
% holiday-dates and prepends an argument holding the token
% @secondoftwo and calls comparedatestotodayloop.
%
% comparedatestotodayloop in a recursive loop compares with all
% elements of the list of holiday-dates compares the date-components to
% month, day, year for finding out if month, day and year
% denote one of these holiday-dates.
%
% comparedatestotodayloop's recursive loop works as follows:
%
% comparedatestotodayloop processes two arguments.
% The first argument denotes the action in case the end of the list is reached.
% The second argument either is an element of the list of dates or is the
% attached token relax.
% Thus for finding out whether the end of the list is reached, one can
% check whether the second argument equals relax.
% If so, just spit out the first argument which denotes the action in
% case the end of the list is reached.
% If not so, compare the date held in the second argument to
% month, day, year (which are components of today) for finding out
% if today is a holiday and therefore the first argument needs to be
% replaced by @firstoftwo before doing the next iteration by
% calling comparedatestotodayloop again...
%-----------------------------------------------------------------
newcommandcomparedatestotoday[1]{%
comparedatestotodayloop{@secondoftwo}#1relax
}%
% comparedatestotodayloop{<token in case end of list is reached>}%
% {<either element of list of holiday-dates
% or relax which was attached for marking
% the end of the list of holiday-dates>}%
newcommandcomparedatestotodayloop[2]{%
ifxrelax#2expandafter@firstoftwoelseexpandafter@secondoftwofi
{#1}{%
comparedatetotoday{#2}%
{comparedatestotodayloop{@firstoftwo}}%
{comparedatestotodayloop{#1}}%
}%
}%
%-----------------------------------------------------------------
% Section: Code for printing lists of dates.
%-----------------------------------------------------------------
% PrintListOfHolidays[<macro for formatting a date>]%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<macro holding the list of dates>}
newcommandexchange[2]{#2#1}
newcommandPrintListOfHolidays[4][RemoveDaysLeadZero]{%
expandafterexchangeexpandafter{#4}{Holidayloop{#1}{}{}{#2}{#3}}relaxrelax
}%
%-----------------------------------------------------------------
% Holidayloop{<macro for formatting a date>}%
% {<separator for this date in case it is not the last date of the list>}%
% {<separator for this date in case it is the last date of the list>}%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<month as word><space><day as number>,>space><year as number>}
% At first glimpse the arguments <separator for this date in case it is not the last date of the list>
% and <separator between dates> respective
% <separator for this date in case it is the last date of the list> and
% <separator for the last date> seem to be the same.
% But we must consider the case of the list being empty or holding
% only one element: In these cases we don't want any separator, thus
% we need a possibility to pass empty arguments for the first
% iteration...
%
newcommandHolidayloop[7]{%
ifxrelax#6expandafter@gobbleelseexpandafter@firstofonefi
{%
ifxrelax#7expandafter@firstoftwoelseexpandafter@secondoftwofi
{#3#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: last date of the list
{#2#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: not the last date of the list
}%
}%
% macros for formatting the date.
% They all take the date and use "inner" macros that by means of
% delimited arguments split it into components and do the desired
% things to the components.
newcommandRemoveDaysLeadZero[1]{innerRemoveDaysLeadZero#1relax}
newcommandinnerRemoveDaysLeadZero{}%
definnerRemoveDaysLeadZero#1 #2,#3relax{mbox{#1 number#2,#3}}%
%
newcommandRemoveYear[1]{innerRemoveyear#1relax}
newcommandinnerRemoveyear{}%
definnerRemoveyear#1 #2,#3relax{mbox{#1 number#2}}%
%
newcommandAddDayOfWeek[1]{innerAddDayOfweek#1relax}
newcommandinnerAddDayOfweek{}%
definnerAddDayOfweek#1 #2, #3relax{%
setdatenumber{#3}{monthtonumber{#1}}{#2}%
mbox{datedayname, #1 #2, #3}%
}%
%
% As we need to compare each today/each combination of
% year, month and day to the list of holidays for
% for finding out whether a today is on a holiday, we can
% maintain a list of such todays that are on holidays.
% Whenever such a today is found, it will added to the macro
% @DaysAffectedByHolidays. That macro in turn is used at the
% end of the document for writing to .aux-file a directive
% for defining a macro DaysAffectedByHolidays that holds the
% list of only those holidays that "collide" with lecture-days.
%
newcommandDaysAffectedByHolidays{}%
newcommand@DaysAffectedByHolidays{}%
AtEndDocument{%
immediatewrite@auxout{%
stringgdefstringDaysAffectedByHolidays{@DaysAffectedByHolidays}%
}%
}%

newififfirst
firsttrue

newcounter{lecture}

newlengthscratchlength

newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
% Compare the advanced today to each element of the list of holidays:
expandaftercomparedatestotoday
expandafter{Holidaylist}{%
%
% Tokens in case the advanced today denotes one of the holidays:
%
%setdatenumber{year}{month}{day}%
%section*{Holiday: datedayname, today} Holiday.%
xdef@DaysAffectedByHolidays{@DaysAffectedByHolidays{today}}%
% calculate another lecture-day...
nextlec
}{%
%
% Tokens in case the advanced today does not denote one of the holidays:
%
stepcounter{lecture}%
setdatenumber{year}{month}{day}%
section*{Lecture~arabic{lecture}: datedayname, today}%
}%
}%

makeatother

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newcommand*Holidaylist{%
{March 08, 2019}%
{March 29, 2019}%
{April 18, 2019}%
{May 17, 2019}%
{June 18, 2019}%
}%

begin{document}

settowidthscratchlength{hbox{textbf{All holidays: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

% The macros holding the lists of dates of holidays do not
% contain the token relax. Therefore if they are not empty
% as there is at least one holiday, things will end up in
% the else-branch of the if-comparison.
%
ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

% These occur after the 2nd LaTeX-run:

settowidthscratchlength{hbox{textbf{Holidays that affect our lecture-plan: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

newpage

nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

end{document}


enter image description hereenter image description here






share|improve this answer



















  • 1




    Thank you @UlrichDiez. Your suggestion seems to work (I didn't try yet). However, it is to big and complex for me (I am just a junior in LaTeX). Could you, please, document or explain the role of pieces of this code? (For instance, whats the meaning of !? Or, why defmonthfork#1 after newcommand{monthfork}{}?) Sorry for my inconvenience and thank you again.
    – Brasil
    18 hours ago










  • @Brasil I tried to add some commenting. ;-)
    – Ulrich Diez
    11 hours ago













up vote
1
down vote










up vote
1
down vote









Perhaps this exhibits some tricks about recursive iteration and about using delimited arguments for taking apart strings of pattern



<word for month><space><number of day>,<space><year>



documentclass{article}
usepackage{datenumber}
usepackage{advdate}

makeatletter
%-----------------------------------------------------------------
% Section: Code for comparing dates.
%-----------------------------------------------------------------
% monthtonumber{<name of a month>} yields the number of that
% month (range 1..12; January -> 1, February -> 2 ,...,
% December -> 12)
% monthfork just selects/"spits out" an undelimited argument that
% comes behind a delimited argument's delimiter which is formed by
% a list of all months.
% In any case there will be only one place where the list
% is correct and where the delimiter will match...
% ! is used both for making visibly distinguishing month-phrases
% from each other more easy and for denoting where the
% remainder which is to be removed by the !!!!-delimited argument
% ends.
%-----------------------------------------------------------------
newcommand*monthtonumber[1]{%
monthfork
!#1!February!March!April!May!June!July!August!September!October!November!December!{1}%
!January!#1!March!April!May!June!July!August!September!October!November!December!{2}%
!January!February!#1!April!May!June!July!August!September!October!November!December!{3}%
!January!February!March!#1!May!June!July!August!September!October!November!December!{4}%
!January!February!March!April!#1!June!July!August!September!October!November!December!{5}%
!January!February!March!April!May!#1!July!August!September!October!November!December!{6}%
!January!February!March!April!May!June!#1!August!September!October!November!December!{7}%
!January!February!March!April!May!June!July!#1!September!October!November!December!{8}%
!January!February!March!April!May!June!July!August!#1!October!November!December!{9}%
!January!February!March!April!May!June!July!August!September!#1!November!December!{10}%
!January!February!March!April!May!June!July!August!September!October!#1!December!{11}%
!January!February!March!April!May!June!July!August!September!October!November!#1!{12}%
!!!!%
}%
%-----------------------------------------------------------------
% monthfork grabs the undelimited argument behind that
% list of months that is correct/in correct order due to insertion
% of the name of the month by monthtonumber.
% As monthfork needs to be an argument that processes
% delimited arguments, it needs to be defined in terms of
% def. Nonetheless provide a dummy-definition in terms
% of newcommand before for triggering an error-message
% in case one is about to override a macro that already
% is defined, e.g., by some package.
%-----------------------------------------------------------------
newcommandmonthfork{}%
defmonthfork#1!January!February!March!April!May!June!%
July!August!September!October!November!%
December!#2#3!!!!{#2}%
%
%-----------------------------------------------------------------
% comparedatetotoday{<month as word><space><day as number>,<space><year as number>}%
% {<tokens in case dates do not differ>}%
% {<tokens in case dates differ>}%
% converts <month as word> to a number and compares that to the value of month,
% compares <day as number> to the value of day,
% compares <year as number> to the value of year
% In case a difference is detected delivers <tokens in case dates differ>
% In case no difference is detected delivers <tokens in case dates do not differ>
% The macro splitdateandcomparecomponents is used for obtaining
% the components of the date.
% As the date is provided in the pattern
% <month as word><space><day as number>,<space><year as number>
% a space is attached at the end which yields the pattern
% <month as word><space><day as number>,<space><year as number><space>
% and then the components of that pattern are obtained by the macro
% splitdateandcomparecomponents where the three arguments are delimited
% accordingly. Again first a newcommand-dummy-definition for
% triggering error-message in case of overriding an already existing
% command.
%-----------------------------------------------------------------
newcommandcomparedatetotoday[1]{splitdateandcomparecomponents#1 }%
newcommandsplitdateandcomparecomponents{}%
defsplitdateandcomparecomponents#1 #2, #3 {%
ifnumthemonth=monthtonumber{#1} %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheday=#2 %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheyear=#3 %
expandafter@firstoftwoelseexpandafter@secondoftwofi
{@firstoftwo}%
}%
}%
@secondoftwo
}%
%-----------------------------------------------------------------
% comparedatestotoday{%
% {{<month 1 as word><space><day 1 as number>,<space><year 1 as number>}}%<-date1
% {{<month 2 as word><space><day 2 as number>,<space><year 2 as number>}}%<-date2
% ...
% {{<month k as word><space><day k as number>,<space><year k as number>}}%<-datek
% }%
% {<tokens in case at least one date does not differ from the date formed by
% year, month and day>}%
% {<tokens in case all dates do differ from the date formed by
% year, month and day>}%
%
% comparedatestotoday attaches the token relax to the list of
% holiday-dates and prepends an argument holding the token
% @secondoftwo and calls comparedatestotodayloop.
%
% comparedatestotodayloop in a recursive loop compares with all
% elements of the list of holiday-dates compares the date-components to
% month, day, year for finding out if month, day and year
% denote one of these holiday-dates.
%
% comparedatestotodayloop's recursive loop works as follows:
%
% comparedatestotodayloop processes two arguments.
% The first argument denotes the action in case the end of the list is reached.
% The second argument either is an element of the list of dates or is the
% attached token relax.
% Thus for finding out whether the end of the list is reached, one can
% check whether the second argument equals relax.
% If so, just spit out the first argument which denotes the action in
% case the end of the list is reached.
% If not so, compare the date held in the second argument to
% month, day, year (which are components of today) for finding out
% if today is a holiday and therefore the first argument needs to be
% replaced by @firstoftwo before doing the next iteration by
% calling comparedatestotodayloop again...
%-----------------------------------------------------------------
newcommandcomparedatestotoday[1]{%
comparedatestotodayloop{@secondoftwo}#1relax
}%
% comparedatestotodayloop{<token in case end of list is reached>}%
% {<either element of list of holiday-dates
% or relax which was attached for marking
% the end of the list of holiday-dates>}%
newcommandcomparedatestotodayloop[2]{%
ifxrelax#2expandafter@firstoftwoelseexpandafter@secondoftwofi
{#1}{%
comparedatetotoday{#2}%
{comparedatestotodayloop{@firstoftwo}}%
{comparedatestotodayloop{#1}}%
}%
}%
%-----------------------------------------------------------------
% Section: Code for printing lists of dates.
%-----------------------------------------------------------------
% PrintListOfHolidays[<macro for formatting a date>]%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<macro holding the list of dates>}
newcommandexchange[2]{#2#1}
newcommandPrintListOfHolidays[4][RemoveDaysLeadZero]{%
expandafterexchangeexpandafter{#4}{Holidayloop{#1}{}{}{#2}{#3}}relaxrelax
}%
%-----------------------------------------------------------------
% Holidayloop{<macro for formatting a date>}%
% {<separator for this date in case it is not the last date of the list>}%
% {<separator for this date in case it is the last date of the list>}%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<month as word><space><day as number>,>space><year as number>}
% At first glimpse the arguments <separator for this date in case it is not the last date of the list>
% and <separator between dates> respective
% <separator for this date in case it is the last date of the list> and
% <separator for the last date> seem to be the same.
% But we must consider the case of the list being empty or holding
% only one element: In these cases we don't want any separator, thus
% we need a possibility to pass empty arguments for the first
% iteration...
%
newcommandHolidayloop[7]{%
ifxrelax#6expandafter@gobbleelseexpandafter@firstofonefi
{%
ifxrelax#7expandafter@firstoftwoelseexpandafter@secondoftwofi
{#3#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: last date of the list
{#2#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: not the last date of the list
}%
}%
% macros for formatting the date.
% They all take the date and use "inner" macros that by means of
% delimited arguments split it into components and do the desired
% things to the components.
newcommandRemoveDaysLeadZero[1]{innerRemoveDaysLeadZero#1relax}
newcommandinnerRemoveDaysLeadZero{}%
definnerRemoveDaysLeadZero#1 #2,#3relax{mbox{#1 number#2,#3}}%
%
newcommandRemoveYear[1]{innerRemoveyear#1relax}
newcommandinnerRemoveyear{}%
definnerRemoveyear#1 #2,#3relax{mbox{#1 number#2}}%
%
newcommandAddDayOfWeek[1]{innerAddDayOfweek#1relax}
newcommandinnerAddDayOfweek{}%
definnerAddDayOfweek#1 #2, #3relax{%
setdatenumber{#3}{monthtonumber{#1}}{#2}%
mbox{datedayname, #1 #2, #3}%
}%
%
% As we need to compare each today/each combination of
% year, month and day to the list of holidays for
% for finding out whether a today is on a holiday, we can
% maintain a list of such todays that are on holidays.
% Whenever such a today is found, it will added to the macro
% @DaysAffectedByHolidays. That macro in turn is used at the
% end of the document for writing to .aux-file a directive
% for defining a macro DaysAffectedByHolidays that holds the
% list of only those holidays that "collide" with lecture-days.
%
newcommandDaysAffectedByHolidays{}%
newcommand@DaysAffectedByHolidays{}%
AtEndDocument{%
immediatewrite@auxout{%
stringgdefstringDaysAffectedByHolidays{@DaysAffectedByHolidays}%
}%
}%

newififfirst
firsttrue

newcounter{lecture}

newlengthscratchlength

newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
% Compare the advanced today to each element of the list of holidays:
expandaftercomparedatestotoday
expandafter{Holidaylist}{%
%
% Tokens in case the advanced today denotes one of the holidays:
%
%setdatenumber{year}{month}{day}%
%section*{Holiday: datedayname, today} Holiday.%
xdef@DaysAffectedByHolidays{@DaysAffectedByHolidays{today}}%
% calculate another lecture-day...
nextlec
}{%
%
% Tokens in case the advanced today does not denote one of the holidays:
%
stepcounter{lecture}%
setdatenumber{year}{month}{day}%
section*{Lecture~arabic{lecture}: datedayname, today}%
}%
}%

makeatother

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newcommand*Holidaylist{%
{March 08, 2019}%
{March 29, 2019}%
{April 18, 2019}%
{May 17, 2019}%
{June 18, 2019}%
}%

begin{document}

settowidthscratchlength{hbox{textbf{All holidays: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

% The macros holding the lists of dates of holidays do not
% contain the token relax. Therefore if they are not empty
% as there is at least one holiday, things will end up in
% the else-branch of the if-comparison.
%
ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

% These occur after the 2nd LaTeX-run:

settowidthscratchlength{hbox{textbf{Holidays that affect our lecture-plan: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

newpage

nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

end{document}


enter image description hereenter image description here






share|improve this answer














Perhaps this exhibits some tricks about recursive iteration and about using delimited arguments for taking apart strings of pattern



<word for month><space><number of day>,<space><year>



documentclass{article}
usepackage{datenumber}
usepackage{advdate}

makeatletter
%-----------------------------------------------------------------
% Section: Code for comparing dates.
%-----------------------------------------------------------------
% monthtonumber{<name of a month>} yields the number of that
% month (range 1..12; January -> 1, February -> 2 ,...,
% December -> 12)
% monthfork just selects/"spits out" an undelimited argument that
% comes behind a delimited argument's delimiter which is formed by
% a list of all months.
% In any case there will be only one place where the list
% is correct and where the delimiter will match...
% ! is used both for making visibly distinguishing month-phrases
% from each other more easy and for denoting where the
% remainder which is to be removed by the !!!!-delimited argument
% ends.
%-----------------------------------------------------------------
newcommand*monthtonumber[1]{%
monthfork
!#1!February!March!April!May!June!July!August!September!October!November!December!{1}%
!January!#1!March!April!May!June!July!August!September!October!November!December!{2}%
!January!February!#1!April!May!June!July!August!September!October!November!December!{3}%
!January!February!March!#1!May!June!July!August!September!October!November!December!{4}%
!January!February!March!April!#1!June!July!August!September!October!November!December!{5}%
!January!February!March!April!May!#1!July!August!September!October!November!December!{6}%
!January!February!March!April!May!June!#1!August!September!October!November!December!{7}%
!January!February!March!April!May!June!July!#1!September!October!November!December!{8}%
!January!February!March!April!May!June!July!August!#1!October!November!December!{9}%
!January!February!March!April!May!June!July!August!September!#1!November!December!{10}%
!January!February!March!April!May!June!July!August!September!October!#1!December!{11}%
!January!February!March!April!May!June!July!August!September!October!November!#1!{12}%
!!!!%
}%
%-----------------------------------------------------------------
% monthfork grabs the undelimited argument behind that
% list of months that is correct/in correct order due to insertion
% of the name of the month by monthtonumber.
% As monthfork needs to be an argument that processes
% delimited arguments, it needs to be defined in terms of
% def. Nonetheless provide a dummy-definition in terms
% of newcommand before for triggering an error-message
% in case one is about to override a macro that already
% is defined, e.g., by some package.
%-----------------------------------------------------------------
newcommandmonthfork{}%
defmonthfork#1!January!February!March!April!May!June!%
July!August!September!October!November!%
December!#2#3!!!!{#2}%
%
%-----------------------------------------------------------------
% comparedatetotoday{<month as word><space><day as number>,<space><year as number>}%
% {<tokens in case dates do not differ>}%
% {<tokens in case dates differ>}%
% converts <month as word> to a number and compares that to the value of month,
% compares <day as number> to the value of day,
% compares <year as number> to the value of year
% In case a difference is detected delivers <tokens in case dates differ>
% In case no difference is detected delivers <tokens in case dates do not differ>
% The macro splitdateandcomparecomponents is used for obtaining
% the components of the date.
% As the date is provided in the pattern
% <month as word><space><day as number>,<space><year as number>
% a space is attached at the end which yields the pattern
% <month as word><space><day as number>,<space><year as number><space>
% and then the components of that pattern are obtained by the macro
% splitdateandcomparecomponents where the three arguments are delimited
% accordingly. Again first a newcommand-dummy-definition for
% triggering error-message in case of overriding an already existing
% command.
%-----------------------------------------------------------------
newcommandcomparedatetotoday[1]{splitdateandcomparecomponents#1 }%
newcommandsplitdateandcomparecomponents{}%
defsplitdateandcomparecomponents#1 #2, #3 {%
ifnumthemonth=monthtonumber{#1} %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheday=#2 %
expandafter@firstofoneelseexpandafter@secondoftwofi
{%
ifnumtheyear=#3 %
expandafter@firstoftwoelseexpandafter@secondoftwofi
{@firstoftwo}%
}%
}%
@secondoftwo
}%
%-----------------------------------------------------------------
% comparedatestotoday{%
% {{<month 1 as word><space><day 1 as number>,<space><year 1 as number>}}%<-date1
% {{<month 2 as word><space><day 2 as number>,<space><year 2 as number>}}%<-date2
% ...
% {{<month k as word><space><day k as number>,<space><year k as number>}}%<-datek
% }%
% {<tokens in case at least one date does not differ from the date formed by
% year, month and day>}%
% {<tokens in case all dates do differ from the date formed by
% year, month and day>}%
%
% comparedatestotoday attaches the token relax to the list of
% holiday-dates and prepends an argument holding the token
% @secondoftwo and calls comparedatestotodayloop.
%
% comparedatestotodayloop in a recursive loop compares with all
% elements of the list of holiday-dates compares the date-components to
% month, day, year for finding out if month, day and year
% denote one of these holiday-dates.
%
% comparedatestotodayloop's recursive loop works as follows:
%
% comparedatestotodayloop processes two arguments.
% The first argument denotes the action in case the end of the list is reached.
% The second argument either is an element of the list of dates or is the
% attached token relax.
% Thus for finding out whether the end of the list is reached, one can
% check whether the second argument equals relax.
% If so, just spit out the first argument which denotes the action in
% case the end of the list is reached.
% If not so, compare the date held in the second argument to
% month, day, year (which are components of today) for finding out
% if today is a holiday and therefore the first argument needs to be
% replaced by @firstoftwo before doing the next iteration by
% calling comparedatestotodayloop again...
%-----------------------------------------------------------------
newcommandcomparedatestotoday[1]{%
comparedatestotodayloop{@secondoftwo}#1relax
}%
% comparedatestotodayloop{<token in case end of list is reached>}%
% {<either element of list of holiday-dates
% or relax which was attached for marking
% the end of the list of holiday-dates>}%
newcommandcomparedatestotodayloop[2]{%
ifxrelax#2expandafter@firstoftwoelseexpandafter@secondoftwofi
{#1}{%
comparedatetotoday{#2}%
{comparedatestotodayloop{@firstoftwo}}%
{comparedatestotodayloop{#1}}%
}%
}%
%-----------------------------------------------------------------
% Section: Code for printing lists of dates.
%-----------------------------------------------------------------
% PrintListOfHolidays[<macro for formatting a date>]%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<macro holding the list of dates>}
newcommandexchange[2]{#2#1}
newcommandPrintListOfHolidays[4][RemoveDaysLeadZero]{%
expandafterexchangeexpandafter{#4}{Holidayloop{#1}{}{}{#2}{#3}}relaxrelax
}%
%-----------------------------------------------------------------
% Holidayloop{<macro for formatting a date>}%
% {<separator for this date in case it is not the last date of the list>}%
% {<separator for this date in case it is the last date of the list>}%
% {<separator between dates>}%
% {<separator for the last date>}%
% {<month as word><space><day as number>,>space><year as number>}
% At first glimpse the arguments <separator for this date in case it is not the last date of the list>
% and <separator between dates> respective
% <separator for this date in case it is the last date of the list> and
% <separator for the last date> seem to be the same.
% But we must consider the case of the list being empty or holding
% only one element: In these cases we don't want any separator, thus
% we need a possibility to pass empty arguments for the first
% iteration...
%
newcommandHolidayloop[7]{%
ifxrelax#6expandafter@gobbleelseexpandafter@firstofonefi
{%
ifxrelax#7expandafter@firstoftwoelseexpandafter@secondoftwofi
{#3#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: last date of the list
{#2#1{#6}Holidayloop{#1}{#4}{#5}{#4}{#5}{#7}}%<-case: not the last date of the list
}%
}%
% macros for formatting the date.
% They all take the date and use "inner" macros that by means of
% delimited arguments split it into components and do the desired
% things to the components.
newcommandRemoveDaysLeadZero[1]{innerRemoveDaysLeadZero#1relax}
newcommandinnerRemoveDaysLeadZero{}%
definnerRemoveDaysLeadZero#1 #2,#3relax{mbox{#1 number#2,#3}}%
%
newcommandRemoveYear[1]{innerRemoveyear#1relax}
newcommandinnerRemoveyear{}%
definnerRemoveyear#1 #2,#3relax{mbox{#1 number#2}}%
%
newcommandAddDayOfWeek[1]{innerAddDayOfweek#1relax}
newcommandinnerAddDayOfweek{}%
definnerAddDayOfweek#1 #2, #3relax{%
setdatenumber{#3}{monthtonumber{#1}}{#2}%
mbox{datedayname, #1 #2, #3}%
}%
%
% As we need to compare each today/each combination of
% year, month and day to the list of holidays for
% for finding out whether a today is on a holiday, we can
% maintain a list of such todays that are on holidays.
% Whenever such a today is found, it will added to the macro
% @DaysAffectedByHolidays. That macro in turn is used at the
% end of the document for writing to .aux-file a directive
% for defining a macro DaysAffectedByHolidays that holds the
% list of only those holidays that "collide" with lecture-days.
%
newcommandDaysAffectedByHolidays{}%
newcommand@DaysAffectedByHolidays{}%
AtEndDocument{%
immediatewrite@auxout{%
stringgdefstringDaysAffectedByHolidays{@DaysAffectedByHolidays}%
}%
}%

newififfirst
firsttrue

newcounter{lecture}

newlengthscratchlength

newcommand{nextlec}{%
iffirst
firstfalse
else
AdvanceDate[7]%
fi
% Compare the advanced today to each element of the list of holidays:
expandaftercomparedatestotoday
expandafter{Holidaylist}{%
%
% Tokens in case the advanced today denotes one of the holidays:
%
%setdatenumber{year}{month}{day}%
%section*{Holiday: datedayname, today} Holiday.%
xdef@DaysAffectedByHolidays{@DaysAffectedByHolidays{today}}%
% calculate another lecture-day...
nextlec
}{%
%
% Tokens in case the advanced today does not denote one of the holidays:
%
stepcounter{lecture}%
setdatenumber{year}{month}{day}%
section*{Lecture~arabic{lecture}: datedayname, today}%
}%
}%

makeatother

%... Set the first lecture date
ThisYear{2019}
ThisMonth{3}
ThisDay{1}

newcommand*Holidaylist{%
{March 08, 2019}%
{March 29, 2019}%
{April 18, 2019}%
{May 17, 2019}%
{June 18, 2019}%
}%

begin{document}

settowidthscratchlength{hbox{textbf{All holidays: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

% The macros holding the lists of dates of holidays do not
% contain the token relax. Therefore if they are not empty
% as there is at least one holiday, things will end up in
% the else-branch of the if-comparison.
%
ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

ifrelaxHolidaylistrelaxelse
hbox{%
hbox{textbf{All holidays: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{Holidaylist}.strut%
}}%
}%
fi

% These occur after the 2nd LaTeX-run:

settowidthscratchlength{hbox{textbf{Holidays that affect our lecture-plan: }}}
setlengthscratchlength{-scratchlength}
addtolengthscratchlength{textwidth}

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays{; }{; }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[RemoveYear]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

ifrelaxDaysAffectedByHolidaysrelaxelse
hbox{%
hbox{textbf{Holidays that affect our lecture-plan: }}%
hbox toscratchlength{vtop{%
hsize=scratchlengthnoindent
PrintListOfHolidays[AddDayOfWeek]{, }{ and }{DaysAffectedByHolidays}.strut%
}}%
}%
fi

newpage

nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

end{document}


enter image description hereenter image description here







share|improve this answer














share|improve this answer



share|improve this answer








edited 11 hours ago

























answered yesterday









Ulrich Diez

3,755515




3,755515








  • 1




    Thank you @UlrichDiez. Your suggestion seems to work (I didn't try yet). However, it is to big and complex for me (I am just a junior in LaTeX). Could you, please, document or explain the role of pieces of this code? (For instance, whats the meaning of !? Or, why defmonthfork#1 after newcommand{monthfork}{}?) Sorry for my inconvenience and thank you again.
    – Brasil
    18 hours ago










  • @Brasil I tried to add some commenting. ;-)
    – Ulrich Diez
    11 hours ago














  • 1




    Thank you @UlrichDiez. Your suggestion seems to work (I didn't try yet). However, it is to big and complex for me (I am just a junior in LaTeX). Could you, please, document or explain the role of pieces of this code? (For instance, whats the meaning of !? Or, why defmonthfork#1 after newcommand{monthfork}{}?) Sorry for my inconvenience and thank you again.
    – Brasil
    18 hours ago










  • @Brasil I tried to add some commenting. ;-)
    – Ulrich Diez
    11 hours ago








1




1




Thank you @UlrichDiez. Your suggestion seems to work (I didn't try yet). However, it is to big and complex for me (I am just a junior in LaTeX). Could you, please, document or explain the role of pieces of this code? (For instance, whats the meaning of !? Or, why defmonthfork#1 after newcommand{monthfork}{}?) Sorry for my inconvenience and thank you again.
– Brasil
18 hours ago




Thank you @UlrichDiez. Your suggestion seems to work (I didn't try yet). However, it is to big and complex for me (I am just a junior in LaTeX). Could you, please, document or explain the role of pieces of this code? (For instance, whats the meaning of !? Or, why defmonthfork#1 after newcommand{monthfork}{}?) Sorry for my inconvenience and thank you again.
– Brasil
18 hours ago












@Brasil I tried to add some commenting. ;-)
– Ulrich Diez
11 hours ago




@Brasil I tried to add some commenting. ;-)
– Ulrich Diez
11 hours ago










up vote
0
down vote













You can make a list of the holidays and check whether the current date as set by AdvDate appears in the list:



documentclass[twocolumn]{article}
usepackage{advdate}
usepackage{xparse}

ExplSyntaxOn
clist_new:N g_brasil_holiday_clist

NewDocumentCommand{holidays}{m}
{
clist_gset:Nn g_brasil_holiday_clist { #1 }
}
NewDocumentCommand{nextlec}{}
{
brasil_check_holiday:
section*{today}
}

cs_new_protected:Nn brasil_check_holiday:
{
AdvanceDate[7]
clist_if_in:NxT g_brasil_holiday_clist
{ int_eval:n {day} / int_eval:n {month} }
{ brasil_check_holiday: } % redo the test
}
cs_generate_variant:Nn clist_if_in:NnT { Nx }
ExplSyntaxOff

holidays{8/3,29/3,18/4,17/5,18/6}

%... Set the first lecture date

ThisYear{2019}
ThisMonth{3}
ThisDay{1}
AdvanceDate[-7]

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

nextlec
Lecture 11.

nextlec
Lecture 12.

nextlec
Lecture 13.

nextlec
Lecture 14.

nextlec
Lecture 15.

nextlec
Lecture 16.

nextlec
Lecture 17.

nextlec
Lecture 18.

end{document}


Here I use twocolumn just for reducing the output to a single page.



enter image description here






share|improve this answer





















  • Hi @egreg. This code seems very cool! I just read about the xparse package and as far as I could understand, it is like a programming language with features that apply for LaTeX. So, let's go with my questions: (a) would it be possible to do the same task without xparse? (b) about the commands ExplSyntaxOn, ´clist, NewDocumentCommand, and cs, are they LaTeX native, or definitions inside the xparse`? Thank you very much!
    – Brasil
    13 hours ago















up vote
0
down vote













You can make a list of the holidays and check whether the current date as set by AdvDate appears in the list:



documentclass[twocolumn]{article}
usepackage{advdate}
usepackage{xparse}

ExplSyntaxOn
clist_new:N g_brasil_holiday_clist

NewDocumentCommand{holidays}{m}
{
clist_gset:Nn g_brasil_holiday_clist { #1 }
}
NewDocumentCommand{nextlec}{}
{
brasil_check_holiday:
section*{today}
}

cs_new_protected:Nn brasil_check_holiday:
{
AdvanceDate[7]
clist_if_in:NxT g_brasil_holiday_clist
{ int_eval:n {day} / int_eval:n {month} }
{ brasil_check_holiday: } % redo the test
}
cs_generate_variant:Nn clist_if_in:NnT { Nx }
ExplSyntaxOff

holidays{8/3,29/3,18/4,17/5,18/6}

%... Set the first lecture date

ThisYear{2019}
ThisMonth{3}
ThisDay{1}
AdvanceDate[-7]

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

nextlec
Lecture 11.

nextlec
Lecture 12.

nextlec
Lecture 13.

nextlec
Lecture 14.

nextlec
Lecture 15.

nextlec
Lecture 16.

nextlec
Lecture 17.

nextlec
Lecture 18.

end{document}


Here I use twocolumn just for reducing the output to a single page.



enter image description here






share|improve this answer





















  • Hi @egreg. This code seems very cool! I just read about the xparse package and as far as I could understand, it is like a programming language with features that apply for LaTeX. So, let's go with my questions: (a) would it be possible to do the same task without xparse? (b) about the commands ExplSyntaxOn, ´clist, NewDocumentCommand, and cs, are they LaTeX native, or definitions inside the xparse`? Thank you very much!
    – Brasil
    13 hours ago













up vote
0
down vote










up vote
0
down vote









You can make a list of the holidays and check whether the current date as set by AdvDate appears in the list:



documentclass[twocolumn]{article}
usepackage{advdate}
usepackage{xparse}

ExplSyntaxOn
clist_new:N g_brasil_holiday_clist

NewDocumentCommand{holidays}{m}
{
clist_gset:Nn g_brasil_holiday_clist { #1 }
}
NewDocumentCommand{nextlec}{}
{
brasil_check_holiday:
section*{today}
}

cs_new_protected:Nn brasil_check_holiday:
{
AdvanceDate[7]
clist_if_in:NxT g_brasil_holiday_clist
{ int_eval:n {day} / int_eval:n {month} }
{ brasil_check_holiday: } % redo the test
}
cs_generate_variant:Nn clist_if_in:NnT { Nx }
ExplSyntaxOff

holidays{8/3,29/3,18/4,17/5,18/6}

%... Set the first lecture date

ThisYear{2019}
ThisMonth{3}
ThisDay{1}
AdvanceDate[-7]

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

nextlec
Lecture 11.

nextlec
Lecture 12.

nextlec
Lecture 13.

nextlec
Lecture 14.

nextlec
Lecture 15.

nextlec
Lecture 16.

nextlec
Lecture 17.

nextlec
Lecture 18.

end{document}


Here I use twocolumn just for reducing the output to a single page.



enter image description here






share|improve this answer












You can make a list of the holidays and check whether the current date as set by AdvDate appears in the list:



documentclass[twocolumn]{article}
usepackage{advdate}
usepackage{xparse}

ExplSyntaxOn
clist_new:N g_brasil_holiday_clist

NewDocumentCommand{holidays}{m}
{
clist_gset:Nn g_brasil_holiday_clist { #1 }
}
NewDocumentCommand{nextlec}{}
{
brasil_check_holiday:
section*{today}
}

cs_new_protected:Nn brasil_check_holiday:
{
AdvanceDate[7]
clist_if_in:NxT g_brasil_holiday_clist
{ int_eval:n {day} / int_eval:n {month} }
{ brasil_check_holiday: } % redo the test
}
cs_generate_variant:Nn clist_if_in:NnT { Nx }
ExplSyntaxOff

holidays{8/3,29/3,18/4,17/5,18/6}

%... Set the first lecture date

ThisYear{2019}
ThisMonth{3}
ThisDay{1}
AdvanceDate[-7]

begin{document}
nextlec
Lecture 01.

nextlec
Lecture 02.

nextlec
Lecture 03.

nextlec
Lecture 04.

nextlec
Lecture 05.

nextlec
Lecture 06.

nextlec
Lecture 07.

nextlec
Lecture 08.

nextlec
Lecture 09.

nextlec
Lecture 10.

nextlec
Lecture 11.

nextlec
Lecture 12.

nextlec
Lecture 13.

nextlec
Lecture 14.

nextlec
Lecture 15.

nextlec
Lecture 16.

nextlec
Lecture 17.

nextlec
Lecture 18.

end{document}


Here I use twocolumn just for reducing the output to a single page.



enter image description here







share|improve this answer












share|improve this answer



share|improve this answer










answered 16 hours ago









egreg

699k8518583127




699k8518583127












  • Hi @egreg. This code seems very cool! I just read about the xparse package and as far as I could understand, it is like a programming language with features that apply for LaTeX. So, let's go with my questions: (a) would it be possible to do the same task without xparse? (b) about the commands ExplSyntaxOn, ´clist, NewDocumentCommand, and cs, are they LaTeX native, or definitions inside the xparse`? Thank you very much!
    – Brasil
    13 hours ago


















  • Hi @egreg. This code seems very cool! I just read about the xparse package and as far as I could understand, it is like a programming language with features that apply for LaTeX. So, let's go with my questions: (a) would it be possible to do the same task without xparse? (b) about the commands ExplSyntaxOn, ´clist, NewDocumentCommand, and cs, are they LaTeX native, or definitions inside the xparse`? Thank you very much!
    – Brasil
    13 hours ago
















Hi @egreg. This code seems very cool! I just read about the xparse package and as far as I could understand, it is like a programming language with features that apply for LaTeX. So, let's go with my questions: (a) would it be possible to do the same task without xparse? (b) about the commands ExplSyntaxOn, ´clist, NewDocumentCommand, and cs, are they LaTeX native, or definitions inside the xparse`? Thank you very much!
– Brasil
13 hours ago




Hi @egreg. This code seems very cool! I just read about the xparse package and as far as I could understand, it is like a programming language with features that apply for LaTeX. So, let's go with my questions: (a) would it be possible to do the same task without xparse? (b) about the commands ExplSyntaxOn, ´clist, NewDocumentCommand, and cs, are they LaTeX native, or definitions inside the xparse`? Thank you very much!
– Brasil
13 hours ago


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f461120%2fhow-to-compare-a-date-with-a-set-of-dates%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

サソリ

広島県道265号伴広島線

Accessing regular linux commands in Huawei's Dopra Linux