1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/*++
/* NAME
/* mail_date 3
/* SUMMARY
/* return formatted time
/* SYNOPSIS
/* #include <mail_date.h>
/*
/* const char *mail_date(when)
/* time_t when;
/* DESCRIPTION
/* mail_date() converts the time specified in \fIwhen\fR to the
/* form: "Mon, 9 Dec 1996 05:38:26 -0500 (EST)" and returns
/* a pointer to the result. The result is overwritten upon
/* each call.
/* DIAGNOSTICS
/* Panic: the offset from UTC is more than a whole day. Fatal
/* error: out of memory.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <time.h>
#include <stdlib.h>
/* Utility library. */
#include <msg.h>
#include <vstring.h>
/* Global library. */
#include "mail_date.h"
/*
* Application-specific.
*/
#define DAY_MIN (24 * HOUR_MIN) /* minutes in a day */
#define HOUR_MIN 60 /* minutes in an hour */
#define MIN_SEC 60 /* seconds in a minute */
/* mail_date - return formatted time */
const char *mail_date(time_t when)
{
static VSTRING *vp;
struct tm *lt;
struct tm gmt;
int gmtoff;
/*
* As if strftime() isn't expensive enough, we're dynamically adjusting
* the size for the result, so we won't be surprised by long names etc.
*/
if (vp == 0)
vp = vstring_alloc(100);
else
VSTRING_RESET(vp);
/*
* POSIX does not require that struct tm has a tm_gmtoff field, so we
* must compute the time offset from UTC by hand.
*
* Starting with the difference in hours/minutes between 24-hour clocks,
* adjust for differences in years, in yeardays, and in (leap) seconds.
*
* Assume 0..23 hours in a day, 0..59 minutes in an hour. The library spec
* has changed: we can no longer assume that there are 0..59 seconds in a
* minute.
*/
gmt = *gmtime(&when);
lt = localtime(&when);
gmtoff = (lt->tm_hour - gmt.tm_hour) * HOUR_MIN + lt->tm_min - gmt.tm_min;
if (lt->tm_year < gmt.tm_year)
gmtoff -= DAY_MIN;
else if (lt->tm_year > gmt.tm_year)
gmtoff += DAY_MIN;
else if (lt->tm_yday < gmt.tm_yday)
gmtoff -= DAY_MIN;
else if (lt->tm_yday > gmt.tm_yday)
gmtoff += DAY_MIN;
if (lt->tm_sec <= gmt.tm_sec - MIN_SEC)
gmtoff -= 1;
else if (lt->tm_sec >= gmt.tm_sec + MIN_SEC)
gmtoff += 1;
/*
* First, format the date and wall-clock time. XXX The %e format (day of
* month, leading zero replaced by blank) isn't in my POSIX book, but
* many vendors seem to support it.
*/
#ifdef MISSING_STRFTIME_E
#define STRFTIME_FMT "%a, %d %b %Y %H:%M:%S "
#else
#define STRFTIME_FMT "%a, %e %b %Y %H:%M:%S "
#endif
while (strftime(vstring_end(vp), vstring_avail(vp), STRFTIME_FMT, lt) == 0)
VSTRING_SPACE(vp, 100);
VSTRING_SKIP(vp);
/*
* Then, add the UTC offset.
*/
if (gmtoff < -DAY_MIN || gmtoff > DAY_MIN)
msg_panic("UTC time offset %d is larger than one day", gmtoff);
vstring_sprintf_append(vp, "%+03d%02d", (int) (gmtoff / HOUR_MIN),
(int) (gmtoff % HOUR_MIN));
/*
* Finally, add the time zone name.
*/
while (strftime(vstring_end(vp), vstring_avail(vp), " (%Z)", lt) == 0)
VSTRING_SPACE(vp, 100);
VSTRING_SKIP(vp);
return (vstring_str(vp));
}
#ifdef TEST
#include <vstream.h>
main(void)
{
vstream_printf("%s\n", mail_date(time((time_t *) 0)));
vstream_fflush(VSTREAM_OUT);
return (0);
}
#endif
|