Skip to content

Commit a67e9cc

Browse files
committed
Add support for "$DATE(format)" and "$TIME(format)" header/footer strings
(Issue michaelrsweet#472)
1 parent ffb68b6 commit a67e9cc

File tree

5 files changed

+147
-10
lines changed

5 files changed

+147
-10
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Changes in HTMLDOC v1.9.16
22

3+
- Added support for `$DATE(format)` and `$TIME(format)` header/footer strings
4+
(Issue #472)
35
- Fixed a potential image overflow bug with JPEG and PNG images (Issue #471)
46
- Fixed potential heap overflow bugs with pages (Issue #477, Issue #478,
57
Issue #480, Issue #482, Issue #483)

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
dnl
2-
dnl Con])guration script for HTMLDOC, an HTML document processing program.
2+
dnl Configuration script for HTMLDOC, an HTML document processing program.
33
dnl
44
dnl Copyright © 2011-2022 by Michael R Sweet.
55
dnl Copyright © 1997-2010 by Easy Software Products.

doc/4-htmlref.html

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,10 @@ <H3>Header/Footer Strings</H3>
298298

299299
<!-- NEED 1in -->
300300
<DT><CODE>$DATE</CODE>
301-
<DD>Inserts the current date.
301+
<DT><CODE>$DATE(format)</CODE>
302+
<DD>Inserts the current date. See <a href="#DATETIME">Date/Time
303+
Formats</a> for details on the format string. When no format is
304+
supplied, the default date format for the current locale is used.
302305

303306
<!-- NEED 1in -->
304307
<DT><CODE>$HEADING</CODE>
@@ -348,7 +351,10 @@ <H3>Header/Footer Strings</H3>
348351

349352
<!-- NEED 1in -->
350353
<DT><CODE>$TIME</CODE>
351-
<DD>Inserts the current time.
354+
<DT><CODE>$TIME(format)</CODE>
355+
<DD>Inserts the current time. See <a href="#DATETIME">Date/Time
356+
Formats</a> for details on the format string. When no format is
357+
supplied, the default time format for the current locale is used.
352358

353359
<!-- NEED 1in -->
354360
<DT><CODE>$TITLE</CODE>
@@ -360,6 +366,47 @@ <H3>Header/Footer Strings</H3>
360366

361367
</DL>
362368

369+
<H3><A NAME="DATETIME">Date/Time Formats</A></H3>
370+
371+
<p>The <CODE>$DATE</CODE> and <CODE>$TIME</CODE> header/footer strings support
372+
an optional format string in parenthesis. Letters represent date/time values
373+
while other characters are inserted verbatim. The following letters are
374+
supported:</p>
375+
376+
<center>
377+
<table border="1" cellpadding="5">
378+
<tr><th>Letter</th><th>Description</th></tr>
379+
<tr><td><code>A</code></td><td>Full weekday name</td></tr>
380+
<tr><td><code>a</code></td><td>Abbreviated weekday name</td></tr>
381+
<tr><td><code>B</code></td><td>Full month name</td></tr>
382+
<tr><td><code>b</code></td><td>Abbreviated month name</td></tr>
383+
<tr><td><code>C</code></td><td>Century (CC)</td></tr>
384+
<tr><td><code>c</code></td><td>Default date and time format</td></tr>
385+
<tr><td><code>d</code></td><td>Day of the month ("01" to "31")</td></tr>
386+
<tr><td><code>e</code></td><td>Day of the month (" 1" to "31")</td></tr>
387+
<tr><td><code>F</code></td><td>YYYY-MM-DD</td></tr>
388+
<tr><td><code>H</code></td><td>Hours for 24-hour clock ("00" to "23")</td></tr>
389+
<tr><td><code>I</code></td><td>Hours for 12-hour clock ("01" to "12")</td></tr>
390+
<tr><td><code>j</code></td><td>Day of the year ("001" to "366")</td></tr>
391+
<tr><td><code>k</code></td><td>Hours for 24-hour clock (" 0" to "23")</td></tr>
392+
<tr><td><code>l</code></td><td>Hours for 12-hour clock (" 1" to "12")</td></tr>
393+
<tr><td><code>M</code></td><td>Minutes ("00" to "59")</td></tr>
394+
<tr><td><code>m</code></td><td>Month number ("01" to "12")</td></tr>
395+
<tr><td><code>p</code></td><td>"am" or "pm"</td></tr>
396+
<tr><td><code>R</code></td><td>Hours and minutes ("HH:MM")</td></tr>
397+
<tr><td><code>r</code></td><td>Hours, minutes, seconds, and am/pm ("HH:MM:SS am/pm")</td></tr>
398+
<tr><td><code>S</code></td><td>Seconds ("00" to "60")</td></tr>
399+
<tr><td><code>T</code></td><td>Hours, minutes, and seconds ("HH:MM:SS")</td></tr>
400+
<tr><td><code>X</code></td><td>Default time format</td></tr>
401+
<tr><td><code>x</code></td><td>Default date format</td></tr>
402+
<tr><td><code>Y</code></td><td>Year with century (CCYY)</td></tr>
403+
<tr><td><code>y</code></td><td>Year without century (YY)</td></tr>
404+
<tr><td><code>Z</code></td><td>Time zone name</td></tr>
405+
<tr><td><code>z</code></td><td>Time zone offset from UTC</td></tr>
406+
</table>
407+
</center>
408+
409+
363410
<!-- NEED 5in -->
364411
<H2><A NAME="FONT">FONT Attributes</A></H2>
365412

htmldoc/ps-pdf.cxx

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ pspdf_export(tree_t *document, /* I - Document to export */
537537
if (!source_date_epoch || (doc_time = (time_t)strtol(source_date_epoch, NULL, 10)) <= 0)
538538
doc_time = time(NULL);
539539

540-
gmtime_r(&doc_time, &doc_date);
540+
localtime_r(&doc_time, &doc_date);
541541

542542
num_headings = 0;
543543
alloc_headings = 0;
@@ -1706,14 +1706,96 @@ pspdf_prepare_heading(int page, // I - Page number
17061706
}
17071707
else if (formatlen == 4 && strncasecmp(formatptr, "TIME", 4) == 0)
17081708
{
1709+
chartimefmt[256];// Time format
1710+
17091711
formatptr += 4;
1710-
strftime(bufptr, sizeof(buffer) - 1 - (size_t)(bufptr - buffer), "%X", &doc_date);
1712+
if (*formatptr == '(')
1713+
{
1714+
// Support "$TIME(format)"
1715+
char*timeptr;// Pointer into time format
1716+
1717+
for (timeptr = timefmt, formatptr ++; *formatptr && *formatptr != ')'; formatptr ++)
1718+
{
1719+
if (isalpha(*formatptr))
1720+
{
1721+
if (timeptr < (timefmt + sizeof(timefmt) - 2))
1722+
{
1723+
*timeptr++ = '%';
1724+
*timeptr++ = *formatptr;
1725+
}
1726+
else
1727+
break;
1728+
}
1729+
else if (timeptr < (timefmt + sizeof(timefmt) - 1))
1730+
{
1731+
*timeptr++ = *formatptr;
1732+
}
1733+
else
1734+
break;
1735+
}
1736+
1737+
*timeptr = '\0';
1738+
1739+
while (*formatptr && *formatptr != ')')
1740+
formatptr ++;
1741+
1742+
if (*formatptr)
1743+
formatptr ++;
1744+
}
1745+
else
1746+
{
1747+
// Use the locale default format...
1748+
strlcpy(timefmt, "%X", sizeof(timefmt));
1749+
}
1750+
1751+
strftime(bufptr, sizeof(buffer) - 1 - (size_t)(bufptr - buffer), timefmt, &doc_date);
17111752
bufptr += strlen(bufptr);
17121753
}
17131754
else if (formatlen == 4 && strncasecmp(formatptr, "DATE", 4) == 0)
17141755
{
1756+
chardatefmt[256];// Date format
1757+
17151758
formatptr += 4;
1716-
strftime(bufptr, sizeof(buffer) - 1 - (size_t)(bufptr - buffer), "%x", &doc_date);
1759+
if (*formatptr == '(')
1760+
{
1761+
// Support "$DATE(format)"
1762+
char*dateptr;// Pointer into date format
1763+
1764+
for (dateptr = datefmt, formatptr ++; *formatptr && *formatptr != ')'; formatptr ++)
1765+
{
1766+
if (isalpha(*formatptr))
1767+
{
1768+
if (dateptr < (datefmt + sizeof(datefmt) - 2))
1769+
{
1770+
*dateptr++ = '%';
1771+
*dateptr++ = *formatptr;
1772+
}
1773+
else
1774+
break;
1775+
}
1776+
else if (dateptr < (datefmt + sizeof(datefmt) - 1))
1777+
{
1778+
*dateptr++ = *formatptr;
1779+
}
1780+
else
1781+
break;
1782+
}
1783+
1784+
*dateptr = '\0';
1785+
1786+
while (*formatptr && *formatptr != ')')
1787+
formatptr ++;
1788+
1789+
if (*formatptr)
1790+
formatptr ++;
1791+
}
1792+
else
1793+
{
1794+
// Use the locale default format...
1795+
strlcpy(datefmt, "%x", sizeof(datefmt));
1796+
}
1797+
1798+
strftime(bufptr, sizeof(buffer) - 1 - (size_t)(bufptr - buffer), datefmt, &doc_date);
17171799
bufptr += strlen(bufptr);
17181800
}
17191801
else if (formatlen == 3 && strncasecmp(formatptr, "URL", 3) == 0)
@@ -11565,9 +11647,9 @@ write_prolog(FILE *out, /* I - Output file */
1156511647
fprintf(out, "%%%%BoundingBox: 0 0 %d %d\n", PageWidth, PageLength);
1156611648
fprintf(out,"%%%%LanguageLevel: %d\n", PSLevel);
1156711649
fputs("%%Creator: " HTMLDOC_PRODUCER "\n", out);
11568-
fprintf(out, "%%%%CreationDate: D:%04d%02d%02d%02d%02d%02d+0000\n",
11650+
fprintf(out, "%%%%CreationDate: D:%04d%02d%02d%02d%02d%02d%03d00\n",
1156911651
doc_date.tm_year + 1900, doc_date.tm_mon + 1, doc_date.tm_mday,
11570-
doc_date.tm_hour, doc_date.tm_min, doc_date.tm_sec);
11652+
doc_date.tm_hour, doc_date.tm_min, doc_date.tm_sec, (int)(doc_date.tm_gmtoff / 3600));
1157111653
if (doc_title != NULL)
1157211654
fprintf(out, "%%%%Title: %s\n", doc_title);
1157311655
if (author != NULL)
@@ -11949,9 +12031,9 @@ write_prolog(FILE *out, /* I - Output file */
1194912031
fputs("/Producer", out);
1195012032
write_string(out, (uchar *)HTMLDOC_PRODUCER, 0);
1195112033
fputs("/CreationDate", out);
11952-
snprintf(temp, sizeof(temp), "D:%04d%02d%02d%02d%02d%02dZ",
12034+
snprintf(temp, sizeof(temp), "D:%04d%02d%02d%02d%02d%02d%03d00",
1195312035
doc_date.tm_year + 1900, doc_date.tm_mon + 1, doc_date.tm_mday,
11954-
doc_date.tm_hour, doc_date.tm_min, doc_date.tm_sec);
12036+
doc_date.tm_hour, doc_date.tm_min, doc_date.tm_sec, (int)(doc_date.tm_gmtoff / 3600));
1195512037
write_string(out, (uchar *)temp, 0);
1195612038

1195712039
if (doc_title != NULL)

testsuite/basic.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
</HEAD>
55
<BODY>
66

7+
<!--
8+
FOOTER LEFT "Date: $DATE(Y-m-d)"
9+
FOOTER CENTER "Time: $TIME(I:M:Sp)"
10+
FOOTER RIGHT "Page: $PAGE of $PAGES"
11+
-->
12+
713
<H1>Basic HTML Test</H1>
814

915
<H1>Heading 1</H1>

0 commit comments

Comments
 (0)