2

How do I create a bibcheck that would only print publications between two dates, let's say between May 1st, 2017 and April 30th, 2018? Using biblatex 3.9, biber 2.10 on Mac OS X 10.13.4, compiling with XeLatex in TexShop.

The Biblatex manual provides \defbibcheck. In the example below, \defbibcheck is used to print publications since the year 2000. But I don't know how to modify it to print only publications between two dates.

\defbibcheck{recent}{%
\iffieldint{year}
{\ifnumless{\thefield{year}}{2000}
{\skipentry}
{}}
{\skipentry}}

MWE Below

\documentclass{article}
\usepackage{biblatex}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
    @article{greenwade93,
        author  = "A Guy",
        title   = "A document",
        date    = "2016-01-05",
        journal = "Journal of Post-Modern Mysticisms",
        volume  = "14",
        number  = "3",
        pages   = "342--351"
    }

    @book{abook,
        author    = "An Other Auther",
        title     = "Something Really Important",
        date      = "2017-06-01",
        publisher = "Addison-Wesley",
        address   = "Somewhere Town"
    }
    \end{filecontents}



\addbibresource{\jobname.bib}
\begin{document}
Test
\nocite{*}
\printbibliography
\end{document}
  • \defbibcheck{recent}{% \iffieldint{year} {\ifnumless{\thefield{year}}{2000} {\skipentry} {\ifnumgreater{\thefield{year}}{2012} {\skipentry} {}}} {\skipentry}} prints all entries with 2000 <= year <= 2012. – moewe Apr 12 '18 at 20:37
  • 1
    Ha! I knew there was something similar: https://tex.stackexchange.com/q/346270/35864 – moewe Apr 12 '18 at 20:39
  • 1
    I understand you want to cut up to "day precision" of the date. But, for example, what should happen if an entry had date = {2017}, that is, only with the year information? Should it be included in that interval? – gusbrs Apr 12 '18 at 20:41
  • Sadly, I do want to specify the day. It's for my annual report, and the year runs from May 1st to April 30th. So I'd like to only print documents that appear in those days, or, possibly just after May 1st. So I realize I do need to be accurate in the underlying bib file, but it's not that many documents. – spindoctor Apr 13 '18 at 02:18

2 Answers2

2

A straightforward way is to add a test if your entry was written (on or) after a specific date. That can then be used as in biblatex, biber, is it possible to \printbibliography between two years?. The test is very naive at the moment and will throw an error if an entry without month or day information is encountered - of course one could guard against that, but it is not sure whether something written in year = {2018} is from after 2018-05-08 or not.

\ifdateafter{yyyy}{mm}{dd} checks if an entry's date is after yyyy-mm-dd (">"), \ifdateonorafter{yyyy}{mm}{dd} checks if the date is not before yyyy-mm-dd (">="). The commands have an optional argument that can be used to check different dates, use \ifdateonorafter[url] to check the URL date of an entry or \ifdateonorafter[orig] to check the origdate field; the default is an empty optional argument, which checks date.

You can now use \ifdateonorafter in \defbibcheck to only select entries written on or after 2017-05-01 but before 2018-05-01.

\documentclass{article}
\usepackage{biblatex}

% this macro is not used in the check below, but might still be useful
% check if entry's date > {yyyy}{mm}{dd} 
\newcommand*{\ifdateafter}[4][]{%
  \ifboolexpr{test {\ifnumgreater{\thefield{#1year}}{#2}}
              or (test {\ifnumequal{\thefield{#1year}}{#2}}
                  and (test {\ifnumgreater{\thefield{#1month}}{#3}}
                       or (test {\ifnumequal{\thefield{#1month}}{#3}}
                           and test {\ifnumgreater{\thefield{#1day}}{#4}})))}}

% check if entry's date >= {yyyy}{mm}{dd} 
\newcommand*{\ifdateonorafter}[4][]{%
  \ifboolexpr{test {\ifnumgreater{\thefield{#1year}}{#2}}
              or (test {\ifnumequal{\thefield{#1year}}{#2}}
                  and (test {\ifnumgreater{\thefield{#1month}}{#3}}
                       or (test {\ifnumequal{\thefield{#1month}}{#3}}
                           and not test {\ifnumless{\thefield{#1day}}{#4}})))}}

\defbibcheck{thisyear}{%
  \iffieldint{year}
    {\ifdateonorafter{2017}{5}{1}      % date >= 2017-05-01?
       {\ifdateonorafter{2018}{5}{1}   % date >= 2018-05-01
          {\skipentry}                 % too new for us (date >= 2018-05-01)
          {}}                          % just right (2017-05-01 <= date < 2018-05-01)
       {\skipentry}}                   % too old (date <2017-05-01)
    {\skipentry}}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@article{greenwade93,
  author  = "A Guy",
  title   = "A document",
  date    = "2018-05-01",
  journal = "Journal of Post-Modern Mysticisms",
  volume  = "14",
  number  = "3",
  pages   = "342--351"
}

@book{abook,
  author    = "An Other Auther",
  title     = "Something Really Important",
  date      = "2017-06-01",
  publisher = "Addison-Wesley",
  address   = "Somewhere Town"
}
\end{filecontents}

\addbibresource{\jobname.bib}
\begin{document}
Test
\nocite{*}
\printbibliography[check=thisyear]
\end{document}

enter image description here

moewe
  • 175,683
  • Shouldn't this be testing the "date" field, not the "year" field? – spindoctor Apr 13 '18 at 13:35
  • @spindoctor Nope. Internally for biblatex there is no date field. All date fields are decomposed into their date parts: year, month, day, .... Only the latter are available to the programming layer of biblatex. date is only the input field. – moewe Apr 13 '18 at 13:38
  • OK, and I see you've defined two new commands here ifdateonorafter and ifdateafter, but in the bibcheck, you only use theifdateonorafter`. Is this an oversight? Should I be using both? – spindoctor Apr 13 '18 at 14:10
  • @spindoctor I first defined \ifdateafter, then I defined and used \ifdateonorafter because it was more natural for your particular question. Because both are useful I kept both of them. In the answer we defined $<$ and $\leq$ and with that we can define $=$ as $\leq \setminus <$. On second thoughts I expected $\leq$ to be the most useful command, so I did not want to define it in terms of the other two as $< \cup =$ to save a few macro calls. – moewe Apr 13 '18 at 14:24
  • One last question: Does it matter if the bibtex entries are wrapped in curly braces {} or "" ? All my entries are in {}. – spindoctor Apr 13 '18 at 14:53
  • @spindoctor Why don't you use the code example to find out? For almost all intents and purposes {...} and "..." are equivalent as field delimiters. It certainly makes no difference here. – moewe Apr 13 '18 at 14:59
  • This works great as an answer; the only trick is keeping bibtex entries with a year, month and day. But it's just a bib file with my own activities, so it's not that big of a deal. – spindoctor Apr 26 '18 at 15:50
  • @spindoctor Yes a full date in YYYY-MM-DD format is required. But that is self-evident, how should the code treat a work with only date = {2017} if you ask \ifdateonorafter{2017}{5}{1}. There is no way of knowing if the work was written before or after the cut-off date. – moewe Apr 26 '18 at 16:31
  • I'm not complaining, just pointing out the one wrinkle in an otherwise ideal solution. – spindoctor May 01 '18 at 19:57
0

An alternative method would be to use a regex on the date in a sourcemap to add a keyword to the entries of interest (That's an adaptation to your requirements of jon's answer in the link provided by moewe in the comments, that is: https://tex.stackexchange.com/a/346299/105447).

For your case, as your interval stretches from the first day of a month to the last day of another, we only need to control for the months. But the technique is extensible for the case in which the day is actually needed or to the case in which the date might not always be specified in full.

\documentclass{article}
\usepackage{biblatex}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
  @article{greenwade93,
    author  = "A Guy",
    title   = "A document",
    date    = "2016-01-05",
    journal = "Journal of Post-Modern Mysticisms",
    volume  = "14",
    number  = "3",
    pages   = "342--351"
  }

  @book{abook,
    author    = "An Other Auther",
    title     = "Something Really Important",
    date      = "2017-06-01",
    publisher = "Addison-Wesley",
    address   = "Somewhere Town"
  }
\end{filecontents}

\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map[overwrite]{
      \step[fieldsource=date,  match=\regexp{^(2017-(0[5-9]|1[1-2])|2018-0[1-4])}, final]
      \step[fieldset=keywords, fieldvalue={,daterange}, append]
      \step[fieldsource=keywords, match=\regexp{\A,}, replace={}]
    }
  }
}

\addbibresource{\jobname.bib}

\begin{document}
\nocite{*}
\printbibliography[keyword=daterange]
\end{document}
gusbrs
  • 13,740