7 /* return formatted time
9 /* #include <mail_date.h>
11 /* const char *mail_date(when)
14 /* mail_date() converts the time specified in \fIwhen\fR to the
15 /* form: "Mon, 9 Dec 1996 05:38:26 -0500 (EST)" and returns
16 /* a pointer to the result. The result is overwritten upon
19 /* Panic: the offset from UTC is more than a whole day. Fatal
20 /* error: out of memory.
24 /* The Secure Mailer license must be distributed with this software.
27 /* IBM T.J. Watson Research
29 /* Yorktown Heights, NY 10598, USA
38 /* Utility library. */
45 #include "mail_date.h"
48 * Application-specific.
50 #define DAY_MIN (24 * HOUR_MIN) /* minutes in a day */
51 #define HOUR_MIN 60 /* minutes in an hour */
52 #define MIN_SEC 60 /* seconds in a minute */
54 /* mail_date - return formatted time */
56 const char *mail_date(time_t when
)
64 * As if strftime() isn't expensive enough, we're dynamically adjusting
65 * the size for the result, so we won't be surprised by long names etc.
68 vp
= vstring_alloc(100);
73 * POSIX does not require that struct tm has a tm_gmtoff field, so we
74 * must compute the time offset from UTC by hand.
76 * Starting with the difference in hours/minutes between 24-hour clocks,
77 * adjust for differences in years, in yeardays, and in (leap) seconds.
79 * Assume 0..23 hours in a day, 0..59 minutes in an hour. The library spec
80 * has changed: we can no longer assume that there are 0..59 seconds in a
84 lt
= localtime(&when
);
85 gmtoff
= (lt
->tm_hour
- gmt
.tm_hour
) * HOUR_MIN
+ lt
->tm_min
- gmt
.tm_min
;
86 if (lt
->tm_year
< gmt
.tm_year
)
88 else if (lt
->tm_year
> gmt
.tm_year
)
90 else if (lt
->tm_yday
< gmt
.tm_yday
)
92 else if (lt
->tm_yday
> gmt
.tm_yday
)
94 if (lt
->tm_sec
<= gmt
.tm_sec
- MIN_SEC
)
96 else if (lt
->tm_sec
>= gmt
.tm_sec
+ MIN_SEC
)
100 * First, format the date and wall-clock time. XXX The %e format (day of
101 * month, leading zero replaced by blank) isn't in my POSIX book, but
102 * many vendors seem to support it.
104 #ifdef MISSING_STRFTIME_E
105 #define STRFTIME_FMT "%a, %d %b %Y %H:%M:%S "
107 #define STRFTIME_FMT "%a, %e %b %Y %H:%M:%S "
110 while (strftime(vstring_end(vp
), vstring_avail(vp
), STRFTIME_FMT
, lt
) == 0)
111 VSTRING_SPACE(vp
, 100);
115 * Then, add the UTC offset.
117 if (gmtoff
< -DAY_MIN
|| gmtoff
> DAY_MIN
)
118 msg_panic("UTC time offset %d is larger than one day", gmtoff
);
119 vstring_sprintf_append(vp
, "%+03d%02d", (int) (gmtoff
/ HOUR_MIN
),
120 (int) (abs(gmtoff
) % HOUR_MIN
));
123 * Finally, add the time zone name.
125 while (strftime(vstring_end(vp
), vstring_avail(vp
), " (%Z)", lt
) == 0)
126 VSTRING_SPACE(vp
, vstring_avail(vp
) + 100);
129 return (vstring_str(vp
));
138 vstream_printf("%s\n", mail_date(time((time_t *) 0)));
139 vstream_fflush(VSTREAM_OUT
);