From 5bbaedac57d656d3f38a574763b2ab5451a20158 Mon Sep 17 00:00:00 2001
From: John MacFarlane <jgm@berkeley.edu>
Date: Tue, 11 Jun 2019 17:01:36 -0700
Subject: [PATCH] JATS writer: ensure validity of pub-date.

We try to parse the date and convert to year, month, day,
as expected in pub-date.  We also add an iso-8601-date attribute
if possible.
---
 data/templates/default.jats     | 16 ++++------------
 src/Text/Pandoc/Writers/JATS.hs | 22 ++++++++++++++++++++++
 test/writer.jats                |  6 ++++--
 3 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/data/templates/default.jats b/data/templates/default.jats
index 966da5c29..5fd3590a5 100644
--- a/data/templates/default.jats
+++ b/data/templates/default.jats
@@ -120,22 +120,14 @@ $endif$
 </author-notes>
 $endif$
 $if(date)$
-$if(date.iso-8601)$
-<pub-date pub-type="epub" iso-8601-date="$date.iso-8601$">
-$else$
-<pub-date pub-type="epub">
-$endif$
+<pub-date pub-type="epub"$if(date.iso-8601)$ iso-8601-date="$date.iso-8601$"$endif$>
 $if(date.day)$
-<day>$pub-date.day$</day>
+<day>$date.day$</day>
 $endif$
 $if(date.month)$
-<month>$pub-date.month$</month>
-$endif$
-$if(date.year)$
-<year>$pub-date.year$</year>
-$else$
-<string-date>$date$</string-date>
+<month>$date.month$</month>
 $endif$
+<year>$date.year$</year>
 </pub-date>
 $endif$
 $if(article.volume)$
diff --git a/src/Text/Pandoc/Writers/JATS.hs b/src/Text/Pandoc/Writers/JATS.hs
index 07a49ceac..145d37bee 100644
--- a/src/Text/Pandoc/Writers/JATS.hs
+++ b/src/Text/Pandoc/Writers/JATS.hs
@@ -20,7 +20,9 @@ import Control.Monad.State
 import Data.Char (toLower)
 import Data.Generics (everywhere, mkT)
 import Data.List (isSuffixOf, partition, isPrefixOf)
+import qualified Data.Map as M
 import Data.Maybe (fromMaybe)
+import Data.Time (toGregorian, Day, parseTimeM, defaultTimeLocale, formatTime)
 import Data.Text (Text)
 import Text.Pandoc.Class (PandocMonad, report)
 import Text.Pandoc.Definition
@@ -88,8 +90,21 @@ docToJATS opts (Pandoc meta blocks) = do
   backs <- mapM (elementToJATS opts' startLvl) backElements
   let fns = inTagsIndented "fn-group" $ vcat notes
   let back = render' $ vcat backs $$ fns
+  let date = case  getField "date" metadata -- an object
+               `mplus`
+                   (getField "date" metadata >>= parseDate) of
+               Nothing  -> mempty
+               Just day ->
+                 let (y,m,d) = toGregorian day
+                 in  M.insert ("year" :: String) (show y)
+                      $ M.insert "month" (show m)
+                      $ M.insert "day" (show d)
+                      $ M.insert "iso-8601"
+                         (formatTime defaultTimeLocale "%F" day)
+                      $ mempty
   let context = defField "body" main
               $ defField "back" back
+              $ resetField ("date" :: String) date
               $ defField "mathml" (case writerHTMLMathMethod opts of
                                         MathML -> True
                                         _      -> False) metadata
@@ -505,3 +520,10 @@ demoteHeaderAndRefs (Header _ _ ils) = Para ils
 demoteHeaderAndRefs (Div ("refs",cls,kvs) bs) =
                        Div ("",cls,kvs) bs
 demoteHeaderAndRefs x = x
+
+parseDate :: String -> Maybe Day
+parseDate s = msum (map (\fs -> parsetimeWith fs s) formats) :: Maybe Day
+  where parsetimeWith = parseTimeM True defaultTimeLocale
+        formats = ["%x","%m/%d/%Y", "%D","%F", "%d %b %Y",
+                    "%e %B %Y", "%b. %e, %Y", "%B %e, %Y",
+                    "%Y%m%d", "%Y%m", "%Y"]
diff --git a/test/writer.jats b/test/writer.jats
index ba5736cdd..7bbf8304d 100644
--- a/test/writer.jats
+++ b/test/writer.jats
@@ -22,8 +22,10 @@
 <string-name>Anonymous</string-name>
 </contrib>
 </contrib-group>
-<pub-date pub-type="epub">
-<string-date>July 17, 2006</string-date>
+<pub-date pub-type="epub" iso-8601-date="2006-07-17">
+<day>17</day>
+<month>7</month>
+<year>2006</year>
 </pub-date>
 </article-meta>
 </front>