# BibLaTeX (authoryear) puts empty parentheses when date is empty

I want to use BibLaTeX' pubstate field for "in preparation" publications that do not have a publication date yet (empty date field), like this one in authoryear style:

@Article{Test,
author       = {Author, A.},
journaltitle = {A Journal},
title        = {A Title},
pubstate     = {inpreparation},
}


However, this leaves an empty parenthesis after the journal name:

\documentclass{article}
\usepackage[backend=biber, style=authoryear]{biblatex}

\begin{document}
Test \parencite{Test}.

\printbibliography
\end{document}


How can I remove this?

The underlying issue here is that unlike its colleagues \print(field|list|names|date) the command \printtext does not know beforehand if it will print something. So it will always apply the formatting argument even if it later turns out that nothing is to be printed. Here that means that we end up with an empty pair of parentheses.

One way around that is to check if we want to print something before we call \printtext.

While some biblatex code use \ifthenelse most newer code uses etoolbox's \ifboolexpr. Note that internally for biblatex there is no field date, if you want to test for the existence of a date it is better to test for year

\renewbibmacro*{issue+date}{%
\ifboolexpr{test {\iffieldundef{issue}} and test {\iffieldundef{year}}}
{}
{\printtext[parens]{%
\printfield{issue}%
\usebibmacro{date}}%
\newunit}}


It may interest some people that biblatex-apa recently implemented a version of \printtext that automatically checks if it prints something and suppresses the formatting if it doesn't. See https://github.com/plk/biblatex-apa/pull/99. If it turns out that this command does not have any negative side effects we may want to think about moving it to the biblatex core, but it needs more testing (and the implementation feels a lot like cheating).

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{csquotes}

\usepackage[style=authoryear, backend=biber]{biblatex}

\renewbibmacro*{issue+date}{%
\printtexte[parens]{%
\printfield{issue}%
\usebibmacro{date}}%
\newunit}

% implement \printtexte
\makeatletter
% Optional parens/brackets
% Thanks to egreg from https://tex.stackexchange.com/questions/53068/how-to-check-if-a-macro-value-is-empty-or-will-not-create-text-with-plain-tex-co
% for this test for expanded emptiness so that we can easily opt to not print parens around nothing
% Without this, it is very messy - you have to test all potential fields for defness first and this
% is messy because the fields in the additional info vary betwee entrytypes
\def\foreverunspace{%
\ifnum\lastnodetype=11
\unskip\foreverunspace
\else
\ifnum\lastnodetype=12
\unkern\foreverunspace
\else
\ifnum\lastnodetype=13
\unpenalty\foreverunspace
\fi
\fi
\fi
}

% we need a way to save the state of the punctuation buffer
% cf. \blx@initunit in biblatex.sty for what we need to copy

% this uses the internal implementation of etoolbox toggles
% fingers crossed no one messes with it
\newrobustcmd*{\apablx@savetoggle}[1]{%
\csletcs{apablx@savedtoggle@#1}{etb@tgl@#1}}

\newrobustcmd*{\apablx@restoretoggle}[1]{%
\csletcs{etb@tgl@#1}{apablx@savedtoggle@#1}}

\newrobustcmd*{\apablx@savepunctstate}{%
\apablx@savetoggle{blx@block}%
\apablx@savetoggle{blx@unit}%
\apablx@savetoggle{blx@insert}%
\apablx@savetoggle{blx@lastins}%
\apablx@savetoggle{blx@keepunit}%
\let\apablx@savd@unitpunct\blx@unitpunct
\let\apablx@savd@puncthook\abx@puncthook}

\newrobustcmd*{\apablx@restorepunctstate}{%
\global\apablx@restoretoggle{blx@block}%
\global\apablx@restoretoggle{blx@unit}%
\global\apablx@restoretoggle{blx@insert}%
\global\apablx@restoretoggle{blx@lastins}%
\global\apablx@restoretoggle{blx@keepunit}%
\global\let\blx@unitpunct\apablx@savd@unitpunct
\global\let\abx@puncthook\apablx@savd@puncthook}

% printtext that checks if it would print anything
\newrobustcmd{\printtexte}[2][]{%
\apablx@savepunctstate
\setbox0=\hbox{#2\foreverunspace}%
\apablx@restorepunctstate
\ifdim\wd0=0pt
\else
\ifblank{#1}
{\printtext{#2}}
{\printtext[#1]{#2}}%
\fi}
\makeatother

\begin{filecontents}{\jobname.bib}
@article{test,
author       = {Author, A.},
journaltitle = {A Journal},
title        = {A Title},
pubstate     = {inpreparation},
}
\end{filecontents}

\begin{document}
\autocite{test}
\printbibliography
\end{document}


Found the solution:

\renewbibmacro*{issue+date}{%
\ifthenelse{\ifentrytype{article}\AND\iffieldundef{date}\AND\iffieldundef{issue}}
{}
{\ifthenelse{\iffieldundef{issue}}
{}
{\printtext[parens]{%
\printfield{issue}%